2020-01-14 22:25:43 +01:00
< ? php
2017-11-08 17:39:50 +01:00
2020-01-19 13:16:40 +01:00
class Programs implements IWebsiteModule
2017-11-08 17:39:50 +01:00
{
2020-12-25 16:42:43 +01:00
const PROG_LANGS = [ 'Java' , 'C#' , 'Delphi' , 'PHP' , 'C++' , 'Rust' , 'Typescript' ];
2018-01-27 14:21:34 +01:00
2018-01-26 21:49:09 +01:00
const URL_ORDER =
[
'github' ,
'sourceforge' ,
'download' ,
'playstore' ,
'amazonappstore' ,
'windowsstore' ,
'itunesstore' ,
'homepage' ,
'wiki' ,
'alternativeto' ,
2018-02-08 20:48:34 +01:00
'changelog' ,
2018-01-26 21:49:09 +01:00
];
const LICENSES =
[
'MIT' => 'https://choosealicense.com/licenses/mit/' ,
'Unlicense' => 'https://choosealicense.com/licenses/unlicense/' ,
'GPL-3.0' => 'https://choosealicense.com/licenses/gpl-3.0/' ,
'Apache-2.0' => 'https://choosealicense.com/licenses/apache-2.0/' ,
'Mozilla-2.0' => 'https://choosealicense.com/licenses/mpl-2.0/' ,
];
2020-01-15 00:37:08 +01:00
/** @var array */
private $staticData ;
public function __construct ()
{
$this -> load ();
}
private function load ()
{
2020-01-15 02:50:23 +01:00
$all = require ( __DIR__ . '/../../statics/programs/__all.php' );
2020-01-15 00:37:08 +01:00
$this -> staticData = array_map ( function ( $a ){ return self :: readSingle ( $a );}, $all );
}
private static function readSingle ( $a )
2017-11-08 17:39:50 +01:00
{
2018-01-27 14:21:34 +01:00
$a [ 'mainimage_url' ] = '/data/images/program_img/' . $a [ 'internal_name' ] . '.png' ;
2020-01-16 11:34:01 +01:00
$a [ 'mainimage_path' ] = __DIR__ . '/../../data/images/program_img/' . $a [ 'internal_name' ] . '.png' ;
2018-01-27 14:21:34 +01:00
$a [ 'preview_url' ] = '/data/dynamic/progprev_' . $a [ 'internal_name' ] . '.png' ;
2020-01-16 11:34:01 +01:00
$a [ 'preview_path' ] = __DIR__ . '/../../data/dynamic/progprev_' . $a [ 'internal_name' ] . '.png' ;
2018-01-27 14:21:34 +01:00
2020-01-16 11:34:01 +01:00
$a [ 'file_longdescription' ] = ( __DIR__ . '/../../statics/programs/' . $a [ 'internal_name' ] . '_description.md' );
2018-01-27 14:21:34 +01:00
2018-01-04 01:11:41 +01:00
$a [ 'url' ] = '/programs/view/' . $a [ 'internal_name' ];
2018-02-09 22:59:02 +01:00
$a [ 'has_extra_images' ] = array_key_exists ( 'extra_images' , $a ) && count ( $a [ 'extra_images' ]) > 0 ;
$a [ 'extraimages_urls' ] = [];
$a [ 'extraimages_paths' ] = [];
if ( $a [ 'has_extra_images' ])
{
foreach ( $a [ 'extra_images' ] as $fn )
{
2020-01-19 13:16:40 +01:00
$a [ 'extraimages_urls' ] [] = '/data/images/program_img/' . $fn ;
$a [ 'extraimages_paths' ] [] = __DIR__ . '/../../data/images/program_img/' . $fn ;
2018-02-09 22:59:02 +01:00
}
}
2017-11-08 17:39:50 +01:00
return $a ;
}
2020-01-15 00:37:08 +01:00
public function listAll ()
2017-11-08 17:39:50 +01:00
{
2020-01-15 00:37:08 +01:00
return $this -> staticData ;
2018-01-03 21:02:40 +01:00
}
2020-01-15 00:37:08 +01:00
public function listAllNewestFirst ( $filter = '' )
2018-01-03 21:02:40 +01:00
{
2020-01-15 00:37:08 +01:00
$data = $this -> staticData ;
2018-01-03 21:02:40 +01:00
usort ( $data , function ( $a , $b ) { return strcasecmp ( $b [ 'add_date' ], $a [ 'add_date' ]); });
2018-01-04 16:55:26 +01:00
if ( $filter !== '' ) $data = array_filter ( $data , function ( $a ) use ( $filter ) { return strtolower ( $a [ 'category' ]) === strtolower ( $filter ); });
2018-01-03 21:02:40 +01:00
return $data ;
2017-11-08 17:39:50 +01:00
}
2017-11-20 17:15:12 +01:00
2020-01-15 00:37:08 +01:00
public function getProgramByInternalName ( $id )
2017-11-20 17:15:12 +01:00
{
2020-01-15 00:37:08 +01:00
foreach ( $this -> staticData as $prog ) {
2018-01-20 03:05:15 +01:00
if ( strcasecmp ( $prog [ 'internal_name' ], $id ) === 0 ) return $prog ;
if ( $prog [ 'internal_name_alt' ] !== null && strcasecmp ( $prog [ 'internal_name_alt' ], $id ) === 0 ) return $prog ;
}
return null ;
}
2020-01-15 00:37:08 +01:00
public function getProgramDescription ( $prog )
2018-01-20 03:05:15 +01:00
{
return file_get_contents ( $prog [ 'file_longdescription' ]);
}
2018-01-26 21:49:09 +01:00
2020-01-15 00:37:08 +01:00
private static function urlComparator ( $a , $b )
2018-01-26 21:49:09 +01:00
{
2018-01-27 14:21:34 +01:00
$na = 0 ;
$nb = 0 ;
if ( strpos ( $a , '#' ) !== FALSE ) { $na = intval ( explode ( '#' , $a )[ 1 ]); $a = explode ( '#' , $a )[ 0 ]; }
if ( strpos ( $b , '#' ) !== FALSE ) { $nb = intval ( explode ( '#' , $b )[ 1 ]); $b = explode ( '#' , $b )[ 0 ]; }
2018-01-26 21:49:09 +01:00
$ia = array_search ( $a , Programs :: URL_ORDER );
$ib = array_search ( $b , Programs :: URL_ORDER );
if ( $ia === false && $ib === false ) return strcasecmp ( $a , $b );
if ( $ia === false && $ib !== false ) return + 1 ; // sort [IA | IB]
if ( $ia !== false && $ib === false ) return - 1 ; // sort [IB | IA]
2018-01-27 14:21:34 +01:00
if ( $ia === $ib ) return ( $na < $nb ) ? - 1 : + 1 ;
2018-01-26 21:49:09 +01:00
return ( $ia < $ib ) ? - 1 : + 1 ;
}
2020-01-15 00:37:08 +01:00
public function getURLs ( $prog )
2018-01-26 21:49:09 +01:00
{
2018-01-27 14:21:34 +01:00
$urls = $prog [ 'urls' ];
2020-01-15 00:37:08 +01:00
uksort ( $urls , function ( $a , $b ){ return self :: urlComparator ( $a , $b );});
2018-01-27 14:21:34 +01:00
$result = [];
foreach ( $urls as $fulltype => $urldata )
{
$type = $fulltype ;
if ( strpos ( $fulltype , '#' ) !== FALSE ) $type = explode ( '#' , $fulltype )[ 0 ];
$caption = '?' ;
$css = '?' ;
$svg = '?' ;
$direct = false ;
if ( $type === 'download' ) { $caption = 'Download' ; $css = 'prgv_dl_download' ; $svg = 'download' ; }
if ( $type === 'github' ) { $caption = 'Github' ; $css = 'prgv_dl_github' ; $svg = 'github' ; }
if ( $type === 'homepage' ) { $caption = 'Homepage' ; $css = 'prgv_dl_homepage' ; $svg = 'home' ; }
if ( $type === 'wiki' ) { $caption = 'Wiki' ; $css = 'prgv_dl_wiki' ; $svg = 'wiki' ; }
if ( $type === 'playstore' ) { $caption = 'Google Playstore' ; $css = 'prgv_dl_playstore' ; $svg = 'playstore' ; }
if ( $type === 'amazonappstore' ) { $caption = 'Amazon Appstore' ; $css = 'prgv_dl_amznstore' ; $svg = 'amazon' ; }
if ( $type === 'windowsstore' ) { $caption = 'Microsoft Store' ; $css = 'prgv_dl_winstore' ; $svg = 'windows' ; }
if ( $type === 'itunesstore' ) { $caption = 'App Store' ; $css = 'prgv_dl_appstore' ; $svg = 'apple' ; }
if ( $type === 'sourceforge' ) { $caption = 'Sourceforge' ; $css = 'prgv_dl_sourceforge' ; $svg = 'sourceforge' ; }
if ( $type === 'alternativeto' ) { $caption = 'AlternativeTo' ; $css = 'prgv_dl_alternativeto' ; $svg = 'alternativeto' ; }
2018-02-08 20:48:34 +01:00
if ( $type === 'changelog' ) { $caption = 'Changelog' ; $css = 'prgv_dl_changelog' ; $svg = 'changelog' ; }
2018-01-27 14:21:34 +01:00
if ( is_array ( $urldata ))
{
$url = $urldata [ 'url' ];
if ( isset ( $urldata [ 'caption' ])) $caption = $urldata [ 'caption' ];
if ( isset ( $urldata [ 'css' ])) $css = $urldata [ 'css' ];
if ( isset ( $urldata [ 'svg' ])) $svg = $urldata [ 'svg' ];
}
else
{
$url = $urldata ;
}
if ( $url === 'direct' )
{
$direct = true ;
$url = Programs :: getDirectDownloadURL ( $prog );
}
$result [] =
[
'type' => $type ,
'caption' => $caption ,
'svg' => $svg ,
'href' => $url ,
'css' => $css ,
'isdirect' => $direct ,
];
}
return $result ;
2018-01-26 21:49:09 +01:00
}
2020-01-15 00:37:08 +01:00
public function getLicenseUrl ( $license )
2018-01-26 21:49:09 +01:00
{
return self :: LICENSES [ $license ];
}
2018-01-27 14:21:34 +01:00
2020-01-15 00:37:08 +01:00
public function getDirectDownloadURL ( $prog )
2018-01-27 14:21:34 +01:00
{
return '/data/binaries/' . $prog [ 'internal_name' ] . '.zip' ;
}
2020-01-15 00:37:08 +01:00
public function getDirectDownloadPath ( $prog )
2018-01-27 14:21:34 +01:00
{
2020-01-15 02:50:23 +01:00
return ( __DIR__ . '/../../data/binaries/' . $prog [ 'internal_name' ] . '.zip' );
2018-01-27 14:21:34 +01:00
}
2020-01-15 00:37:08 +01:00
public function checkConsistency ()
2018-01-27 14:21:34 +01:00
{
$warn = null ;
2020-01-15 00:37:08 +01:00
$this -> load ();
2018-01-27 14:21:34 +01:00
$intname = [];
$realname = [];
2020-01-15 00:37:08 +01:00
foreach ( $this -> staticData as $prog )
2018-01-27 14:21:34 +01:00
{
if ( in_array ( $prog [ 'internal_name' ], $intname )) return [ 'result' => 'err' , 'message' => 'Duplicate internal_name ' . $prog [ 'name' ]];
$intname [] = $prog [ 'internal_name' ];
if ( $prog [ 'internal_name_alt' ] !== null )
{
if ( in_array ( $prog [ 'internal_name_alt' ], $intname )) return [ 'result' => 'err' , 'message' => 'Duplicate internal_name ' . $prog [ 'name' ]];
$intname [] = $prog [ 'internal_name_alt' ];
}
if ( in_array ( $prog [ 'name' ], $realname )) return [ 'result' => 'err' , 'message' => 'Duplicate name ' . $prog [ 'name' ]];
$realname [] = $prog [ 'name' ];
if ( strpos ( $prog [ 'internal_name' ], ' ' ) !== FALSE ) return [ 'result' => 'err' , 'message' => 'Internal name contains spaces ' . $prog [ 'name' ]];
2020-12-21 06:03:54 +01:00
foreach ( explode_allow_empty ( '|' , $prog [ 'ui_language' ]) as $lang ) if ( $this -> convertLanguageToFlag ( $lang ) === null ) return [ 'result' => 'err' , 'message' => 'Unknown ui-lang ' . $prog [ 'name' ]];
2018-01-27 14:21:34 +01:00
if ( ! in_array ( $prog [ 'prog_language' ], self :: PROG_LANGS )) return [ 'result' => 'err' , 'message' => 'Unknown prog-lang ' . $prog [ 'name' ]];
if ( strlen ( $prog [ 'short_description' ]) > 128 ) $warn = [ 'result' => 'warn' , 'message' => 'short_description too long ' . $prog [ 'name' ]];
if ( $prog [ 'license' ] !== null && ! array_key_exists ( $prog [ 'license' ], self :: LICENSES )) return [ 'result' => 'err' , 'message' => 'Unknown license ' . $prog [ 'name' ]];
$isdl = false ;
2020-01-17 01:28:34 +01:00
foreach ( $this -> getURLs ( $prog ) as $xurl )
2018-01-27 14:21:34 +01:00
{
if ( ! in_array ( $xurl [ 'type' ], self :: URL_ORDER )) return [ 'result' => 'err' , 'message' => 'Unknown url ' . $xurl [ 'type' ]];
2020-01-17 01:28:34 +01:00
if ( $xurl [ 'type' ] === 'download' && $xurl [ 'isdirect' ] && ! file_exists ( $this -> getDirectDownloadPath ( $prog ))) return [ 'result' => 'err' , 'message' => 'Direct download not found ' . $prog [ 'name' ]];
2018-01-27 14:21:34 +01:00
if ( $xurl [ 'type' ] === 'download' || $xurl [ 'type' ] === 'playstore' || $xurl [ 'type' ] === 'itunesstore' ) $isdl = true ;
}
if ( ! $isdl ) return [ 'result' => 'err' , 'message' => 'No download link ' . $prog [ 'name' ]];
if ( ! file_exists ( $prog [ 'mainimage_path' ])) return [ 'result' => 'err' , 'message' => 'Image not found ' . $prog [ 'name' ]];
if ( ! file_exists ( $prog [ 'file_longdescription' ])) return [ 'result' => 'err' , 'message' => 'Description not found ' . $prog [ 'name' ]];
2018-02-09 22:59:02 +01:00
foreach ( $prog [ 'extraimages_paths' ] as $eipath )
{
2020-01-19 13:16:40 +01:00
if ( ! file_exists ( $eipath )) return [ 'result' => 'err' , 'message' => 'Extra-Image not found ' . $prog [ 'name' ], 'long' => $eipath ];
2018-02-09 22:59:02 +01:00
}
2018-01-27 14:21:34 +01:00
2020-01-23 12:14:13 +01:00
if ( ! file_exists ( $prog [ 'preview_path' ])) $warn = [ 'result' => 'warn' , 'message' => 'Preview not found ' . $prog [ 'name' ]];
2018-01-27 14:21:34 +01:00
}
2020-01-23 12:14:13 +01:00
if ( $warn != null ) return $warn ;
2018-01-27 14:21:34 +01:00
return [ 'result' => 'ok' , 'message' => '' ];
}
2020-01-15 00:37:08 +01:00
public function createPreview ( $prog )
2018-01-27 14:21:34 +01:00
{
$src = $prog [ 'mainimage_path' ];
$dst = $prog [ 'preview_path' ];
2020-01-15 00:37:08 +01:00
if ( Website :: inst () -> config [ 'use_magick' ])
2018-02-03 23:49:44 +01:00
magick_resize_image ( $src , 250 , 0 , $dst );
else
smart_resize_image ( $src , 250 , 0 , true , $dst );
2018-01-27 14:21:34 +01:00
}
2020-01-16 11:34:01 +01:00
public function convertLanguageToFlag ( $lang ) {
$lang = trim ( strtolower ( $lang ));
if ( $lang === 'italian' ) return '/data/images/flags/013-italy.svg' ;
if ( $lang === 'english' ) return '/data/images/flags/226-united-states.svg' ;
if ( $lang === 'french' ) return '/data/images/flags/195-france.svg' ;
if ( $lang === 'german' ) return '/data/images/flags/162-germany.svg' ;
if ( $lang === 'spanish' ) return '/data/images/flags/128-spain.svg' ;
return null ;
}
2017-11-08 17:39:50 +01:00
}