| 1: | <?php
|
| 2: | pkgmgr::init();
|
| 3: |
|
| 4: | |
| 5: | |
| 6: |
|
| 7: | class pkgmgr{
|
| 8: | private static $downloadSite = 'https://www.tomgriffiths.net';
|
| 9: | private static $downloadSiteFiles = 'https://files.tomgriffiths.net';
|
| 10: | private static $packageCount = 0;
|
| 11: | private static $packageInitCount = 0;
|
| 12: | private static $packages = [];
|
| 13: | private static $preloadedPackages = ["self","cli","pkgmgr","extensions","inimgmt","linuxcmd","cli_formatter","cmd","commandline_list","data_types","downloader","files","json","time","timetest","txtrw","user_input"];
|
| 14: |
|
| 15: | |
| 16: | |
| 17: |
|
| 18: | public static function command(string $line):void{
|
| 19: | $lines = explode(" ",$line);
|
| 20: | if($lines[0] === "list"){
|
| 21: | $columnNames["Package ID"] = 25;
|
| 22: | $columnNames["Package Name"] = 35;
|
| 23: | if(isset($lines[1])){
|
| 24: | if($lines[1] === "desc"){
|
| 25: | $columnNames["Package Description"] = 40;
|
| 26: | }
|
| 27: | elseif($lines[1] === "depend"){
|
| 28: | $columnNames["Package Dependencies"] = 40;
|
| 29: | }
|
| 30: | }
|
| 31: | $columnNames["Version"] = 8;
|
| 32: |
|
| 33: | $rowsData = array();
|
| 34: | foreach(self::$packages as $packageId => $packageInfo){
|
| 35: | $rowData = array();
|
| 36: | $rowData[] = $packageId;
|
| 37: | $rowData[] = $packageInfo['name'];
|
| 38: | if(isset($lines[1])){
|
| 39: | if($lines[1] === "desc"){
|
| 40: | $rowData[] = $packageInfo['description'];
|
| 41: | }
|
| 42: | elseif($lines[1] === "depend"){
|
| 43: | $dependenciesString = count($packageInfo['dependencies']) . ": ";
|
| 44: | ksort($packageInfo['dependencies']);
|
| 45: | foreach($packageInfo['dependencies'] as $dependencyId => $dependencyVersion){
|
| 46: | $dependenciesString .= $dependencyId . ", ";
|
| 47: | }
|
| 48: | $rowData[] = substr($dependenciesString,0,-2);
|
| 49: | }
|
| 50: | }
|
| 51: |
|
| 52: | $rowData[] = $packageInfo['version'];
|
| 53: | $rowsData[] = $rowData;
|
| 54: | }
|
| 55: | echo commandline_list::table($columnNames,$rowsData);
|
| 56: | }
|
| 57: | elseif($lines[0] === "install"){
|
| 58: | if(!isset($lines[1])){
|
| 59: | echo "pkgmgr: Package id not specified\n";
|
| 60: | }
|
| 61: | if(!self::downloadPackage($lines[1])){
|
| 62: | echo "\npkgmgr: Failed to download package " . $lines[1] . "\n\n";
|
| 63: | }
|
| 64: | }
|
| 65: | elseif($lines[0] === "update"){
|
| 66: | if(isset($lines[1])){
|
| 67: | if(self::doesPackageExist($lines[1],false)){
|
| 68: | if(!self::downloadPackage($lines[1],false,false,false)){
|
| 69: | mklog('warning','Failed to update package ' . $lines[1],false);
|
| 70: | }
|
| 71: | else{
|
| 72: | mklog('general','Please restart for changes to take effect',false);
|
| 73: | }
|
| 74: | }
|
| 75: | }
|
| 76: | else{
|
| 77: | self::updatePackages();
|
| 78: | }
|
| 79: | }
|
| 80: | elseif($lines[0] === "update-core"){
|
| 81: | mklog('general','Running Update',false);
|
| 82: | files::ensureFolder("temp/coreupdates");
|
| 83: | if(!downloader::downloadFile("https://files.tomgriffiths.net/php-cli/updates/latest.zip","temp/coreupdates/latest.zip")){
|
| 84: | echo "Failed to download update file\n";
|
| 85: | return;
|
| 86: | }
|
| 87: |
|
| 88: | $zip = new ZipArchive;
|
| 89: | $result = $zip->open("temp/coreupdates/latest.zip");
|
| 90: | if($result === true){
|
| 91: | $zip->extractTo(".");
|
| 92: | $zip->close();
|
| 93: | unlink("temp/coreupdates/latest.zip");
|
| 94: | }
|
| 95: | else{
|
| 96: | echo "Failed to unzip update file\n";
|
| 97: | @unlink("temp/coreupdates/latest.zip");
|
| 98: | return;
|
| 99: | }
|
| 100: |
|
| 101: | cli::command("reload");
|
| 102: | exit;
|
| 103: | }
|
| 104: | else{
|
| 105: | echo "pkgmgr: Command not found\n";
|
| 106: | }
|
| 107: | }
|
| 108: | |
| 109: | |
| 110: |
|
| 111: | public static function init():void{
|
| 112: | if(!is_dir('packages')){
|
| 113: | if(!mkdir('packages',0777,true)){
|
| 114: | mklog(3,'Failed to create packages directory');
|
| 115: | }
|
| 116: | }
|
| 117: |
|
| 118: | foreach(glob('packages/*') as $dir){
|
| 119: | $package = substr($dir,strripos($dir,"/")+1);
|
| 120: | if(!class_exists($package)){
|
| 121: | if(!self::loadPackage($package)){
|
| 122: | mklog(3,'Unable to load package ' . $package,false);
|
| 123: | }
|
| 124: | }
|
| 125: | }
|
| 126: |
|
| 127: | mklog(1,'Loaded ' . self::$packageCount . ' packages, ' . self::$packageInitCount . ' initialized');
|
| 128: | }
|
| 129: |
|
| 130: | |
| 131: | |
| 132: | |
| 133: | |
| 134: | |
| 135: |
|
| 136: | public static function loadPackage(string $package):bool{
|
| 137: | if(!self::validatePackageId($package)){
|
| 138: | mklog(2, 'Invalid package id');
|
| 139: | return false;
|
| 140: | }
|
| 141: |
|
| 142: | if(in_array($package, self::$preloadedPackages)){
|
| 143: | return true;
|
| 144: | }
|
| 145: |
|
| 146: | if(class_exists($package)){
|
| 147: | mklog(1,'Package ' . $package . ' is allready loaded');
|
| 148: | return false;
|
| 149: | }
|
| 150: |
|
| 151: | $info = self::getPackageInfo($package, false);
|
| 152: | if($info === false){
|
| 153: | mklog(2, 'Failed to get package info while loading package ' . $package);
|
| 154: | return false;
|
| 155: | }
|
| 156: |
|
| 157: | foreach($info['dependencies'] as $dependencyId => $dependencyVersion){
|
| 158: | if(!in_array($dependencyId, self::$preloadedPackages)){
|
| 159: | $dependencyInfo = self::getPackageInfo($dependencyId,false);
|
| 160: | if(is_array($dependencyInfo)){
|
| 161: | if($dependencyInfo['version'] < $dependencyVersion){
|
| 162: | mklog(2,'Unable to load package ' . $package . ' as one of its dependencies (' . $dependencyId . ') has an incorrect version of ' . $dependencyVersion);
|
| 163: | return false;
|
| 164: | }
|
| 165: | }
|
| 166: | else{
|
| 167: | mklog(2,'Unable to load package ' . $package . ' as one of its dependencies (' . $dependencyId . ') does not exist');
|
| 168: | return false;
|
| 169: | }
|
| 170: | }
|
| 171: | }
|
| 172: | foreach($info['dependencies'] as $dependencyId => $dependencyVersion){
|
| 173: | if(!class_exists($dependencyId)){
|
| 174: | if(!self::loadPackage($dependencyId)){
|
| 175: | mklog(2,'Unable to load dependency ' . $dependencyId . ' for ' . $package);
|
| 176: | return false;
|
| 177: | }
|
| 178: | }
|
| 179: | }
|
| 180: |
|
| 181: | mklog(0, 'Loading package ' . $package);
|
| 182: |
|
| 183: | if(!is_file($info['dir'] . "/main.php")){
|
| 184: | return false;
|
| 185: | }
|
| 186: |
|
| 187: | if($GLOBALS['arguments']['check-syntax']){
|
| 188: | if(!self::isPhpFileSyntaxOk($info['dir'] . "/main.php")){
|
| 189: | mklog(2, "The package " . $package . " has invalid syntax");
|
| 190: | }
|
| 191: | }
|
| 192: |
|
| 193: | include_once $info['dir'] . "/main.php";
|
| 194: | self::$packageCount++;
|
| 195: | self::$packages[$package] = $info;
|
| 196: |
|
| 197: | if(method_exists($package,"init")){
|
| 198: | mklog(1,'Running init for package ' . $info['name']);
|
| 199: |
|
| 200: | try{
|
| 201: | $package::init();
|
| 202: | self::$packageInitCount++;
|
| 203: | }
|
| 204: | catch(Throwable $throwable){
|
| 205: | mklog(2, "Failed to run init for package " . $package . " (" . substr($throwable,0,strpos($throwable,"\n")) . ")");
|
| 206: | return false;
|
| 207: | }
|
| 208: |
|
| 209: | }
|
| 210: |
|
| 211: | return true;
|
| 212: | }
|
| 213: | |
| 214: | |
| 215: | |
| 216: | |
| 217: | |
| 218: |
|
| 219: | public static function validatePackageId(string $packageId):bool{
|
| 220: | return (preg_match("/^[a-zA-Z0-9_]+$/",$packageId) === 1);
|
| 221: | }
|
| 222: | |
| 223: | |
| 224: | |
| 225: | |
| 226: | |
| 227: |
|
| 228: | public static function validatePackageInfo(array $info):bool{
|
| 229: | if(!isset($info['id_name'])){
|
| 230: | mklog(0, 'Package does not have id_name');
|
| 231: | return false;
|
| 232: | }
|
| 233: | if(!is_string($info['id_name']) || !self::validatePackageId($info['id_name'])){
|
| 234: | mklog(0, 'Package has an invalid id');
|
| 235: | return false;
|
| 236: | }
|
| 237: |
|
| 238: | foreach(['version', 'author', 'name', 'dependencies'] as $thing){
|
| 239: | if(!isset($info[$thing])){
|
| 240: | mklog(0, 'Package ' . $info['id_name'] . ' does not have ' . $thing);
|
| 241: | return false;
|
| 242: | }
|
| 243: | }
|
| 244: |
|
| 245: | if(!is_int($info['version']) || $info['version'] < 1){
|
| 246: | mklog(0, 'Package ' . $info['id_name'] . ' has an invalid version');
|
| 247: | return false;
|
| 248: | }
|
| 249: | if(!is_string($info['author']) || !preg_match("/[a-z0-9_]/", $info['author'])){
|
| 250: | mklog(0, 'Package ' . $info['id_name'] . ' has an invalid author');
|
| 251: | return false;
|
| 252: | }
|
| 253: |
|
| 254: | if(!is_string($info['name'])){
|
| 255: | mklog(0, 'Package ' . $info['id_name'] . ' has an invalid name');
|
| 256: | return false;
|
| 257: | }
|
| 258: |
|
| 259: | if(!is_array($info['dependencies'])){
|
| 260: | mklog(0, 'Package ' . $info['id_name'] . ' does not have a dependencies list');
|
| 261: | return false;
|
| 262: | }
|
| 263: | foreach($info['dependencies'] as $key => $value){
|
| 264: | if(!is_string($key) || !self::validatePackageId($key) || !is_int($value) || $value < 1){
|
| 265: | mklog(0, 'Package ' . $info['id_name'] . ' has an invalid dependency');
|
| 266: | return false;
|
| 267: | }
|
| 268: | }
|
| 269: |
|
| 270: | return true;
|
| 271: | }
|
| 272: | |
| 273: | |
| 274: | |
| 275: | |
| 276: | |
| 277: |
|
| 278: | public static function getPackageDependencies(array $packageInfo):array|false{
|
| 279: | if(self::validatePackageInfo($packageInfo)){
|
| 280: | return $packageInfo['dependencies'];
|
| 281: | }
|
| 282: | return false;
|
| 283: | }
|
| 284: | |
| 285: | |
| 286: | |
| 287: | |
| 288: | |
| 289: | |
| 290: |
|
| 291: | public static function doesPackageExist(string $packageId, bool $online):bool{
|
| 292: | if(self::getPackageInfo($packageId, $online) !== false){
|
| 293: | return true;
|
| 294: | }
|
| 295: | return false;
|
| 296: | }
|
| 297: | |
| 298: | |
| 299: | |
| 300: | |
| 301: | |
| 302: | |
| 303: |
|
| 304: | public static function getPackageInfo(string $packageId, bool $online):array|false{
|
| 305: | if(!self::validatePackageId($packageId)){
|
| 306: | mklog(2, 'Invalid package name ' . $packageId);
|
| 307: | return false;
|
| 308: | }
|
| 309: |
|
| 310: | if($online === true){
|
| 311: | $result = json::readFile(self::$downloadSite . '/php-cli/api/?function=getPackageInfo&packageId=' . $packageId);
|
| 312: | if(!is_array($result)){
|
| 313: | mklog(2, 'Failed to download information for package ' . $packageId);
|
| 314: | return false;
|
| 315: | }
|
| 316: |
|
| 317: | if(!isset($result['success']) || !$result['success'] === true || !isset($result['data']) || !is_array($result['data'])){
|
| 318: | mklog(2, 'Failed to download valid information for package ' . $packageId);
|
| 319: | return false;
|
| 320: | }
|
| 321: |
|
| 322: | return $result['data'];
|
| 323: | }
|
| 324: | else{
|
| 325: | $infoFile = 'packages/' . $packageId . '/information.json';
|
| 326: | $phpMainFile = 'packages/' . $packageId . '/main.php';
|
| 327: | if(!is_file($infoFile) || !is_file($phpMainFile)){
|
| 328: | mklog(2, 'The package ' . $packageId . ' has missing files');
|
| 329: | return false;
|
| 330: | }
|
| 331: |
|
| 332: | $packageInfo = json::readFile($infoFile);
|
| 333: | if(!is_array($packageInfo)){
|
| 334: | mklog(2,'Unable to load information for package ' . $packageId);
|
| 335: | return false;
|
| 336: | }
|
| 337: |
|
| 338: | $packageInfo['dir'] = getcwd() . '/packages/' . $packageId;
|
| 339: |
|
| 340: | if(!self::validatePackageInfo($packageInfo)){
|
| 341: | mklog(2,'The package ' . $packageId . ' has invalid data');
|
| 342: | return false;
|
| 343: | }
|
| 344: |
|
| 345: | return $packageInfo;
|
| 346: | }
|
| 347: | }
|
| 348: | |
| 349: | |
| 350: | |
| 351: | |
| 352: | |
| 353: | |
| 354: |
|
| 355: | public static function getPackageVersionInfo(string $packageId, int $version):array|false{
|
| 356: | if(!self::validatePackageId($packageId)){
|
| 357: | mklog(2, 'Unable get version info for invalid package id ' . $packageId);
|
| 358: | return false;
|
| 359: | }
|
| 360: |
|
| 361: | $result = json::readFile(self::$downloadSite . '/php-cli/api/?function=getPackageVersionInfo&packageId=' . $packageId . '&version=' . $version);
|
| 362: | if(!is_array($result)){
|
| 363: | mklog(2, 'Unable to download information for package ' . $packageId . ' v' . $version);
|
| 364: | return false;
|
| 365: | }
|
| 366: |
|
| 367: | if(!isset($result['success']) || !$result['success'] || !isset($result['data']) || !is_array($result['data'])){
|
| 368: | mklog(2, 'Unable to download valid information for package ' . $packageId . ' v' . $version);
|
| 369: | return false;
|
| 370: | }
|
| 371: |
|
| 372: | return $result['data'];
|
| 373: | }
|
| 374: | |
| 375: | |
| 376: | |
| 377: | |
| 378: | |
| 379: | |
| 380: | |
| 381: | |
| 382: |
|
| 383: | public static function downloadPackage(string $packageId, int|bool $version=false, bool $getDependencies=true, bool $load=true):bool{
|
| 384: | if(!self::validatePackageId($packageId)){
|
| 385: | mklog(2, 'Invalid package id ' . $packageId);
|
| 386: | return false;
|
| 387: | }
|
| 388: |
|
| 389: | $info = self::getPackageInfo($packageId, true);
|
| 390: | if(!is_array($info)){
|
| 391: | mklog(2, 'Failed to download information about package ' . $packageId);
|
| 392: | return false;
|
| 393: | }
|
| 394: |
|
| 395: | foreach(['id_name','author','versions','name','latest_version'] as $thing){
|
| 396: | if(!isset($info[$thing])){
|
| 397: | mklog(2, 'Incomplete data for download for ' . $packageId);
|
| 398: | return false;
|
| 399: | }
|
| 400: | }
|
| 401: |
|
| 402: | $downloadVersion = false;
|
| 403: | if(is_int($version)){
|
| 404: | if(in_array($version, $info['versions'])){
|
| 405: | $downloadVersion = $version;
|
| 406: | }
|
| 407: | }
|
| 408: | if(!is_int($downloadVersion)){
|
| 409: | mklog(0, 'No download version set, assuming latest version ' . $info['latest_version']);
|
| 410: | $downloadVersion = $info['latest_version'];
|
| 411: | }
|
| 412: |
|
| 413: | if(is_file('packages/' . $packageId . '/information.json')){
|
| 414: | $localInfo = json::readFile('packages/' . $packageId . '/information.json');
|
| 415: | if(!is_array($localInfo)){
|
| 416: | mklog(1, 'Local package information for package ' . $packageId . ' is not correct, overwriting');
|
| 417: | }
|
| 418: | if(isset($localInfo['version'])){
|
| 419: | if($localInfo['version'] == $downloadVersion){
|
| 420: | mklog(1,'Version of package ' . $packageId . ' already matches');
|
| 421: | return true;
|
| 422: | }
|
| 423: | }
|
| 424: | }
|
| 425: |
|
| 426: | if(is_file('packages/' . $packageId . '/.noupdate')){
|
| 427: | mklog(1,'Package ' . $packageId . ' is marked for not updating (.noupdate file found)');
|
| 428: | return false;
|
| 429: | }
|
| 430: |
|
| 431: | if(is_dir('packages/' . $packageId . '/files')){
|
| 432: | if(!cmd::run('rmdir "packages/' . $packageId . '/files" /S /Q')){
|
| 433: | mklog(2,'Failed to remove old files dir for package ' . $packageId);
|
| 434: | }
|
| 435: | }
|
| 436: |
|
| 437: | $info2 = self::getPackageVersionInfo($packageId,$downloadVersion);
|
| 438: | if($info2 === false){
|
| 439: | mklog(2, 'Failed to download information about package ' . $packageId . ' v' . $downloadVersion);
|
| 440: | return false;
|
| 441: | }
|
| 442: |
|
| 443: | $info2['id_name'] = $info['id_name'];
|
| 444: | $info2['author'] = $info['author'];
|
| 445: |
|
| 446: | foreach(['version', 'name'] as $thing){
|
| 447: | if(!isset($info2[$thing])){
|
| 448: | mklog(2,'Incomplete data for version download of ' . $packageId);
|
| 449: | return false;
|
| 450: | }
|
| 451: | }
|
| 452: |
|
| 453: | $downloadFile = 'temp/pkgmgr/downloads/' . $packageId . '-' . time() . '.zip';
|
| 454: | mklog(1,'Downloading package ' . $packageId . ' version ' . $downloadVersion);
|
| 455: |
|
| 456: | $downloadTries = 0;
|
| 457: | retrydownload:
|
| 458: | if(!downloader::downloadFile(self::$downloadSiteFiles . '/php-cli/packages/' . $packageId . '/' . $downloadVersion . '.zip',$downloadFile)){
|
| 459: | mklog(2,'Failed to download zip file for package ' . $packageId);
|
| 460: | return false;
|
| 461: | }
|
| 462: |
|
| 463: | $downloadTries++;
|
| 464: | $zip = new ZipArchive;
|
| 465: | $result = $zip->open($downloadFile);
|
| 466: | if($result !== true){
|
| 467: | mklog(1, 'Failed to download valid package file, retrying');
|
| 468: | if($downloadTries < 5){
|
| 469: | goto retrydownload;
|
| 470: | }
|
| 471: | else{
|
| 472: | mklog(2,'Failed to download a valid zip file for package ' . $packageId);
|
| 473: | return false;
|
| 474: | }
|
| 475: | }
|
| 476: | $zip->close();
|
| 477: |
|
| 478: | if($getDependencies){
|
| 479: | mklog(0, 'Downloading dependencies for package ' . $packageId);
|
| 480: | if(isset($info2['dependencies'])){
|
| 481: | if(is_array($info2['dependencies'])){
|
| 482: | foreach($info2['dependencies'] as $dependency => $dependencyVersion){
|
| 483: | if(!class_exists($dependency) || (isset(self::$packages[$dependency]) && self::$packages[$dependency]['version'] < $dependencyVersion)){
|
| 484: | if(!self::downloadPackage($dependency)){
|
| 485: | mklog(2, 'Failed to download dependency for ' . $packageId . ' which requires ' . $dependency . ' v' . $dependencyVersion);
|
| 486: | }
|
| 487: | }
|
| 488: | }
|
| 489: | }
|
| 490: | else{
|
| 491: | mklog(2,'Unknown dependencies format for package ' . $packageId);
|
| 492: | }
|
| 493: | }
|
| 494: | }
|
| 495: |
|
| 496: | files::ensureFolder('packages/' . $packageId);
|
| 497: |
|
| 498: | mklog(0, "Unpacking " . $packageId);
|
| 499: | $zip = new ZipArchive;
|
| 500: | $result = $zip->open($downloadFile);
|
| 501: | if($result !== true){
|
| 502: | mklog(2, 'Failed to open package zip file ' . $downloadFile);
|
| 503: | return false;
|
| 504: | }
|
| 505: | if(!$zip->extractTo('packages/' . $packageId)){
|
| 506: | mklog(2, 'Failed to extract contents from package zip file to packages/' . $packageId);
|
| 507: | return false;
|
| 508: | }
|
| 509: | $zip->close();
|
| 510: |
|
| 511: | if(!json::writeFile('packages/' . $packageId . '/information.json',$info2,true)){
|
| 512: | mklog(2,'Unable to write information file for package ' . $packageId);
|
| 513: | return false;
|
| 514: | }
|
| 515: |
|
| 516: | if(!unlink($downloadFile)){
|
| 517: | mklog(0,'Unable to delete temporary download file ' . $downloadFile);
|
| 518: | }
|
| 519: |
|
| 520: | if($load){
|
| 521: | mklog(1, "Loading " . $packageId);
|
| 522: | return self::loadPackage($packageId);
|
| 523: | }
|
| 524: |
|
| 525: | mklog(1, 'Please restart PHP-CLI for the update to apply');
|
| 526: | return true;
|
| 527: | }
|
| 528: | |
| 529: | |
| 530: | |
| 531: | |
| 532: |
|
| 533: | public static function updatePackages():bool{
|
| 534: | $return = false;
|
| 535: |
|
| 536: | $glob = glob('packages/*');
|
| 537: | if(!is_array($glob)){
|
| 538: | mklog(2, 'Unable to read packages folder');
|
| 539: | return false;
|
| 540: | }
|
| 541: |
|
| 542: | foreach($glob as $dir){
|
| 543: | $packageId = files::getFileName($dir);
|
| 544: | if(self::doesPackageExist($packageId, false)){
|
| 545: | if(self::downloadPackage($packageId, false, true, false)){
|
| 546: | $return = true;
|
| 547: | }
|
| 548: | else{
|
| 549: | mklog(2, 'Failed to update package ' . $packageId,false);
|
| 550: | }
|
| 551: | }
|
| 552: | }
|
| 553: | return $return;
|
| 554: | }
|
| 555: | |
| 556: | |
| 557: | |
| 558: | |
| 559: | |
| 560: | |
| 561: |
|
| 562: | public static function getPackageFileDependencies(string $packageId, bool $getLatestVersions=true):array|false{
|
| 563: | if(!self::validatePackageId($packageId)){
|
| 564: | return false;
|
| 565: | }
|
| 566: |
|
| 567: | if(in_array($packageId, self::$preloadedPackages)){
|
| 568: | return [];
|
| 569: | }
|
| 570: |
|
| 571: | $file = 'packages/' . $packageId . '/main.php';
|
| 572: | if(!is_file($file)){
|
| 573: | return false;
|
| 574: | }
|
| 575: |
|
| 576: | mklog(0, 'Reading ' . $file);
|
| 577: |
|
| 578: | $text = file_get_contents($file);
|
| 579: | if($text === false){
|
| 580: | mklog(2,'Unable to read package file ' . $file);
|
| 581: | }
|
| 582: | $offset = 0;
|
| 583: | $dependencies = array();
|
| 584: | while(true){
|
| 585: | $pos = strpos($text,"::",$offset);
|
| 586: | if($pos === false){
|
| 587: | break;
|
| 588: | }
|
| 589: | $pos2 = 1;
|
| 590: | while(true){
|
| 591: | $dependency = substr($text,$pos - $pos2,$pos2);
|
| 592: | if(preg_match("/^[a-zA-Z0-9_]+$/", $dependency) === 1){
|
| 593: | $pos2++;
|
| 594: | }
|
| 595: | else{
|
| 596: | break;
|
| 597: | }
|
| 598: | }
|
| 599: | $dependency = trim(substr($dependency,1));
|
| 600: | if(!in_array($dependency, self::$preloadedPackages) && is_file('packages/' . $dependency . '/main.php')){
|
| 601: | $leftfromdependency = 1;
|
| 602: | $makedependency = true;
|
| 603: | while(true){
|
| 604: | $firsttwochars = substr($text,$pos - $pos2 - $leftfromdependency,2);
|
| 605: | if($firsttwochars === "//"){
|
| 606: | $makedependency = false;
|
| 607: | break;
|
| 608: | }
|
| 609: | elseif(strpos($firsttwochars,"\n") !== false){
|
| 610: | break;
|
| 611: | }
|
| 612: | else{
|
| 613: | $leftfromdependency++;
|
| 614: | }
|
| 615: | }
|
| 616: |
|
| 617: | if($makedependency){
|
| 618: | if($getLatestVersions){
|
| 619: | if(!isset($dependencies[$dependency])){
|
| 620: | mklog(1, 'Checking latest version of ' . $dependency);
|
| 621: | $onlineInfo = self::getPackageInfo($dependency, true);
|
| 622: | if(is_array($onlineInfo) && isset($onlineInfo['latest_version'])){
|
| 623: | $dependencies[$dependency] = $onlineInfo['latest_version'];
|
| 624: | }
|
| 625: | else{
|
| 626: | $dependencies[$dependency] = 1;
|
| 627: | mklog(2, 'Failed to get latest version for ' . $dependency);
|
| 628: | }
|
| 629: | }
|
| 630: | }
|
| 631: | else{
|
| 632: | if(!in_array($dependency, $dependencies)){
|
| 633: | $dependencies[] = $dependency;
|
| 634: | }
|
| 635: | }
|
| 636: | }
|
| 637: | }
|
| 638: | $offset = $pos+2;
|
| 639: | }
|
| 640: |
|
| 641: | return $dependencies;
|
| 642: | }
|
| 643: | |
| 644: | |
| 645: | |
| 646: | |
| 647: |
|
| 648: | public static function getLoadedPackages():array{
|
| 649: | $return = [];
|
| 650: | foreach(self::$packages as $packageId => $packageInfo){
|
| 651: | $return[$packageId] = $packageInfo['version'];
|
| 652: | }
|
| 653: | return $return;
|
| 654: | }
|
| 655: | |
| 656: | |
| 657: | |
| 658: | |
| 659: |
|
| 660: | public static function getLatestPhpUrl():string|false{
|
| 661: | $data = json::readFile('https://downloads.php.net/~windows/releases/releases.json');
|
| 662: |
|
| 663: | if(!is_array($data)){
|
| 664: | mklog(2,'Unable to read php releases information');
|
| 665: | return false;
|
| 666: | }
|
| 667: |
|
| 668: |
|
| 669: | $currentVersion = "0";
|
| 670: | foreach($data as $version => $versionData){
|
| 671: | if(floatval($version) > floatval($currentVersion)){
|
| 672: | $currentVersion = $version;
|
| 673: | }
|
| 674: | }
|
| 675: |
|
| 676: | if(!isset($data[$currentVersion])){
|
| 677: | return false;
|
| 678: | }
|
| 679: | $data = $data[$currentVersion];
|
| 680: |
|
| 681: |
|
| 682: | $currentVersion = "";
|
| 683: | foreach($data as $version => $versionData){
|
| 684: | if(substr($version,0,3) === "ts-" && substr($version, -4) === "-x64"){
|
| 685: | $currentVersion = $version;
|
| 686: | break;
|
| 687: | }
|
| 688: | }
|
| 689: |
|
| 690: | if(!isset($data[$currentVersion])){
|
| 691: | return false;
|
| 692: | }
|
| 693: | $data = $data[$currentVersion];
|
| 694: |
|
| 695: |
|
| 696: | if(!isset($data['zip'])){
|
| 697: | return false;
|
| 698: | }
|
| 699: | if(!isset($data['zip']['path'])){
|
| 700: | return false;
|
| 701: | }
|
| 702: |
|
| 703: | return 'https://downloads.php.net/~windows/releases/' . $data['zip']['path'];
|
| 704: | }
|
| 705: | |
| 706: | |
| 707: | |
| 708: | |
| 709: | |
| 710: |
|
| 711: | public static function isPhpFileSyntaxOk(string $file):bool{
|
| 712: |
|
| 713: | $output = shell_exec("php -l " . escapeshellarg($file) . " 2>&1");
|
| 714: |
|
| 715: | return str_contains($output, 'No syntax errors');
|
| 716: | }
|
| 717: | } |