$output .= $keyData['key'] . " = \"\";\n"; } $output .= "\n"; } // Now generate any dialect-specific keys. foreach($baseData['dialects'] as $dialect){ $output .= "; Dialect-specific overrides for " . $dialect . "\n[" . $dialect . "]\n"; foreach($matches as $m){ $keyData = \Core\i18n\I18NLoader::Get($m, $dialect); if($keyData['found'] && $keyData['match_key'] == $dialect){ // This specific dialect has an override. $output .= $keyData['key'] . " = \"" . str_replace('"', '\\"', $keyData['match_str']) . "\";\n"; } } $output .= "\n"; } if($arguments->getArgumentValue('dry-run')){ echo $output; } else{ // Write this output to the requested ini file! $file = \Core\Filestore\Factory::File($dir . '/i18n/' . $lang . '.ini'); $file->putContents($output); \Core\CLI\CLI::PrintSuccess('Updated ' . $file->getFilename() . ' successfully!'); } }
* Supplemental developer-only documentation * Random files useful for developers only * SASS/SCSS source files _You get the idea here._ ## SASS Assets One special use of this directory is for SASS/SCSS assets. Any `*.scss` or `*.sass` file located in `dev/assets/scss/*` will get compiled and minified to `assets/css/*`. EOF; if(\Core\CLI\CLI::PromptUser('Create standard directory structure?', 'bool', true)){ // Start making the directories and writing everything. foreach($directories as $d){ $dir = new \Core\Filestore\Backends\DirectoryLocal($dirname . $d); $dir->mkdir(); } file_put_contents($dirname . 'dev/README.md', $devreadme); } // I need to create a basic xml file for the component to use initially. $implementation = new DOMImplementation(); $dtd = $implementation->createDocumentType('component', 'SYSTEM', 'http://corepl.us/api/2_4/component.dtd');
} // I need a few variables first about the user... $packagername = ''; $packageremail = ''; \Core\CLI\CLI::LoadSettingsFile('packager'); if(!$packagername){ $packagername = \Core\CLI\CLI::PromptUser('Please provide your name you wish to use for packaging', 'text-required'); } if(!$packageremail){ $packageremail = \Core\CLI\CLI::Promptuser('Please provide your email you wish to use for packaging.', 'text-required'); } \Core\CLI\CLI::SaveSettingsFile('packager', array('packagername', 'packageremail')); if(!is_dir(ROOT_PDIR . '_gen/')) mkdir(ROOT_PDIR . '_gen/'); $backend = Core::DB(); foreach($backend->_getTables() as $name){ if(strpos($name, '_') === false){ $classname = ucwords($name); } else{ //$classname = explode('_', substr($name, 4)); $classname = explode('_', $name); foreach($classname as $k => $v){
/** * Copy in all the assets for this theme into the assets location. * * Returns false if nothing changed, else will return an array of all the changes that occured. * * @param bool $install Set to false to uninstall the assets instead of installing. * @param int $verbosity 0 for standard output, 1 for real-time, 2 for real-time verbose output. * * @return false | array * @throws \InstallerException */ public function _parseAssets($install = true, $verbosity = 0) { $assetbase = \Core\Filestore\get_asset_path(); $coretheme = \ConfigHandler::Get('/theme/selected'); // WHY is core theme set to blank?!? // Damn installer... // this happens in the installer. if ($coretheme === null) { $coretheme = 'default'; } $theme = $this->getKeyName(); $changes = []; foreach ($this->_xmlloader->getElements('/assets/file') as $node) { // Cannot install assets if the directory is not setup! if (!$this->getAssetDir()) { continue; } $b = $this->getBaseDir(); // The base filename with the directory. $filename = $node->getAttribute('filename'); // The new theme asset will be installed into the same directory as its theme. // This differs from usual components because they just follow whatever theme is currently running. //$nf = Core::File($assetbase . $theme . '/' . $filename); $trimmedfilename = substr($b . $node->getAttribute('filename'), strlen($this->getAssetDir())); $themespecificfilename = $assetbase . $theme . '/' . $trimmedfilename; $newfilename = 'assets/' . $trimmedfilename; // Before anything, check and see if this file has a custom override file present. if (file_exists(ROOT_PDIR . 'themes/custom/' . $newfilename)) { // If so, then copy that asset to the custom directory too! $f = \Core\Filestore\Factory::File(ROOT_PDIR . 'themes/custom/' . $newfilename); $srcname = '!CUSTOM!'; } else { // Otherwise, the local file is guaranteed to be a local file. $f = new \Core\Filestore\Backends\FileLocal($b . $filename); $srcname = '-theme- '; } if ($verbosity == 2) { CLI::PrintActionStart('Installing ' . $srcname . ' asset ' . $f->getBasename()); } $nf = \Core\Filestore\Factory::File($newfilename); /* // The various replacement possibilities for this file. // The new destination must be in the theme-specific directory, this is a // bit of a hack from the usual behaviour of the filestore system. // Since that's designed to return the default if the theme-specific doesn't exist. $replacements = array( // The theme is not default, but the system translated the path to the default directory. // This is because the file doesn't exist in any theme. // This is actually expected behaviour, except unwanted here. 'default/' . $trimmedfilename => $theme . '/' . $trimmedfilename, // The theme is not the currently installed, but the system translated the path to the that directory. // This is because the filename is the same as the installed theme, so the system just translated there. // We don't want that. $coretheme . '/' . $trimmedfilename => $theme . '/' . $trimmedfilename, ); foreach($replacements as $k => $v){ if($k == $v) continue; if(strpos($nf->getFilename(), $k) !== false){ $nf->setFilename( str_replace($k, $v, $nf->getFilename()) ); } } */ // Check if this file even needs updated. (this is primarily used for reporting reasons) if ($nf->exists() && $nf->identicalTo($f)) { //echo "Skipping file, it's identical.<br/>"; if ($verbosity == 2) { CLI::PrintActionStatus('skip'); } continue; } elseif ($nf->exists()) { $action = 'Replaced'; } else { $action = 'Installed'; } if (!$f->isReadable()) { throw new \InstallerException('Source file [' . $f->getFilename() . '] is not readable.'); } try { $f->copyTo($nf, true); } catch (\Exception $e) { throw new \InstallerException('Unable to copy [' . $f->getFilename() . '] to [' . $nf->getFilename() . ']'); } $change = $action . ' ' . $nf->getFilename(); $changes[] = $change; if ($verbosity == 1) { CLI::PrintLine($change); } elseif ($verbosity == 2) { CLI::PrintActionStatus('ok'); } } // If there are custom assets not registered by any application, install them too! // This will allow an admin to upload additional css resources and images easily. $directory = \Core\Filestore\Factory::Directory('themes/custom/assets'); $ls = $directory->ls(null, true); $baseStrLen = strlen(ROOT_PDIR . '/themes/custom/assets'); foreach ($ls as $fileOrDir) { if ($fileOrDir instanceof File) { $newfilename = substr($fileOrDir->getFilename(), $baseStrLen); if ($verbosity == 2) { CLI::PrintActionStart('Installing CUSTOM asset ' . $newfilename); } $nf = \Core\Filestore\Factory::File('asset/' . $newfilename); if ($nf->exists() && $nf->identicalTo($fileOrDir)) { //echo "Skipping file, it's identical.<br/>"; if ($verbosity == 2) { CLI::PrintActionStatus('skip'); } continue; } elseif ($nf->exists()) { $action = 'Replaced'; } else { $action = 'Installed'; } try { $fileOrDir->copyTo($nf, true); } catch (\Exception $e) { throw new \InstallerException('Unable to copy [' . $fileOrDir->getFilename() . '] to [' . $nf->getFilename() . ']'); } $change = $action . ' ' . $nf->getFilename(); $changes[] = $change; if ($verbosity == 1) { CLI::PrintLine($change); } elseif ($verbosity == 2) { CLI::PrintActionStatus('ok'); } } } if (!sizeof($changes)) { if ($verbosity > 0) { CLI::PrintLine('No changes required'); } return false; } // Make sure the asset cache is purged! \Core\Cache::Delete('asset-resolveurl'); return $changes; }
public function actionSkipped(){ if($this->realtime){ CLI::PrintActionStatus('skip'); } $this->_profiler->record('[SKIP]'); $this->log[] = $this->_actionMessage . ' [SKIP]'; $this->_actionMessage = null; }
file_put_contents($destdir . '/' . $desttgz . '/packages.html', $changelog); CLI::PrintHeader('Finalizing Bundling for ' . $b['name'] . ' ' . $version); // create the tarballs! CLI::PrintActionStart("Creating tarball"); //exec('tar -czf "' . $destdir . '/' . $desttgz . '.tgz" -C "' . $destdir . '" --exclude-vcs --exclude=*~ --exclude=._* ' . $desttgz); exec('tar -czf "' . $destdir . '/' . $desttgz . '.tgz" -C "' . $destdir . '/' . $desttgz . '" --exclude-vcs --exclude=*~ --exclude=._* .'); CLI::PrintActionStatus('ok'); CLI::PrintActionStart("Creating zip"); //exec('cd "' . $destdir . '/"; zip -rq "' . $desttgz . '.zip" "' . $desttgz . '"; cd -'); exec('cd "' . $destdir . '/' . $desttgz . '/"; zip -rq "../' . $desttgz . '.zip" .; cd -'); CLI::PrintActionStatus('ok'); CLI::PrintActionStart("Creating hashes"); exec('md5sum "' . $destdir . '/' . $desttgz . '.tgz" > "' . $destdir . '/' . $desttgz . '.tgz.md5"'); exec('md5sum "' . $destdir . '/' . $desttgz . '.zip" > "' . $destdir . '/' . $desttgz . '.zip.md5"'); CLI::PrintActionStatus('ok'); CLI::PrintActionStart("Cleaning up"); exec('rm -fr "' . $destdir . '/' . $desttgz . '"'); CLI::PrintActionStatus('ok'); } // Give the option to automatically commit and tag all changes for the component. if(CLI::PromptUser('Bundles created, GIT tag the release for ' . $version . '?', 'boolean', true)){ exec('git tag -m "Release Version ' . $version . '" -f ' . 'v' . str_replace('~', '-', $version)); exec('git push --tags'); }
echo "Scanning for JS resources...\n"; $results = []; // Allow specifying core, a component, or a theme. if($onlyCore === true){ exec('find "' . ROOT_PDIR . 'core/" -name "[a-z][a-z0-9_-]*.js"', $results); } elseif($onlyComponent !== null){ exec('find "' . ROOT_PDIR . 'components/' . $onlyComponent . '/" -name "[a-z][a-z0-9_-]*.js"', $results); } elseif($onlyTheme !== null){ exec('find "' . ROOT_PDIR . 'themes/' . $onlyTheme . '/" -name "[a-z][a-z0-9_-]*.js"', $results); } else{ \Core\CLI\CLI::PrintError('You must specify at least one theme, component, or core!'); exit; } foreach($results as $file) { // Is this already a minified file? if(strpos($file, '.min.js') !== false) { continue; } // Only compress files that are located within an "assets" directory. // This is because if any script is used for server-side tasks or test-related tasks, // there is no reason to need the minified version! if(strpos($file, '/assets/') === false) { continue;
public static function RebuildPackages() { $dir = \Core\Filestore\Factory::Directory(\ConfigHandler::Get('/package_repository/base_directory')); $coredir = $dir->getPath() . 'core/'; $componentdir = $dir->getPath() . 'components/'; $themedir = $dir->getPath() . 'themes/'; $tmpdir = \Core\Filestore\Factory::Directory('tmp/exports/'); $gpg = new Core\GPG\GPG(); $keysfound = []; $addedpackages = 0; $failedpackages = 0; $skippedpackages = 0; $ls = $dir->ls('asc', true); \Core\CLI\CLI::PrintProgressBar(0); $totalPackages = sizeof($ls); $percentEach = 100 / $totalPackages; $currentPercent = 0; // Ensure that the necessary temp directory exists. $tmpdir->mkdir(); foreach ($ls as $file) { /** @var \Core\Filestore\File $file */ $fullpath = $file->getFilename(); $relpath = substr($file->getFilename(), strlen($dir->getPath())); $tmpdirpath = $tmpdir->getPath(); // Drop the .asc extension. $basename = $file->getBasename(true); // Tarball of the temporary package $tgz = \Core\Filestore\Factory::File($tmpdirpath . $basename); $output = []; // I need to 1) retrieve and 2) verify the key for this package. try { $signature = $gpg->verifyFileSignature($fullpath); } catch (\Exception $e) { trigger_error($fullpath . ' was not able to be verified as authentic, (probably because the GPG public key was not available)'); $failedpackages++; continue; } // decode and untar it in a temp directory to get the package.xml file. exec('gpg --homedir "' . GPG_HOMEDIR . '" -q -d "' . $fullpath . '" > "' . $tgz->getFilename() . '" 2>/dev/null', $output, $ret); if ($ret) { trigger_error('Decryption of file ' . $fullpath . ' failed!'); $failedpackages++; continue; } // Extract the package.xml metafile, this is critical! exec('tar -xzf "' . $tgz->getFilename() . '" -C "' . $tmpdirpath . '" ./package.xml', $output, $ret); if ($ret) { trigger_error('Unable to extract package.xml from' . $tgz->getFilename()); unlink($tmpdirpath . $basename); $failedpackages++; continue; } // Read in that package file and append it to the repo xml. $package = new PackageXML($tmpdirpath . 'package.xml'); $package->getRootDOM()->setAttribute('key', $signature->keyID); $package->setFileLocation($relpath); // Core has a few differences than most components. if ($package->getKeyName() == 'core') { $pkgName = 'Core Plus'; $chngName = 'Core Plus'; $type = 'core'; $chngDepth = 3; $chngFile = './data/core/CHANGELOG'; $xmlFile = './data/core/component.xml'; } else { $pkgName = $package->getName(); $chngName = ($package->getType() == 'theme' ? 'Theme/' : '') . $package->getName(); $type = $package->getType(); $chngDepth = 2; $chngFile = './data/CHANGELOG'; $xmlFile = './data/' . ($package->getType() == 'theme' ? 'theme.xml' : 'component.xml'); } // Lookup this package in the database or create if it doesn't exist. $model = PackageRepositoryPackageModel::Find(['type = ' . $package->getType(), 'key = ' . $package->getKeyName(), 'version = ' . $package->getVersion()], 1); if (!$model) { $model = new PackageRepositoryPackageModel(); $model->set('type', $type); $model->set('key', $package->getKeyName()); $model->set('version', $package->getVersion()); } // Set the data provided by the package.xml file. $model->set('name', $pkgName); $model->set('gpg_key', $package->getKey()); $model->set('packager', $package->getPackager()); $model->set('file', $relpath); $model->set('description', $package->getDescription()); $model->set('requires', $package->getRequires()); $model->set('provides', $package->getProvides()); $model->set('upgrades', $package->getUpgrades()); unlink($tmpdirpath . 'package.xml'); // Extract out the CHANGELOG file, this is not so critical. // I need strip-components=2 to drop off the "." and "data" prefixes. exec('tar -xzf "' . $tgz->getFilename() . '" -C "' . $tmpdirpath . '" --strip-components=' . $chngDepth . ' ' . $chngFile, $output, $ret); // If there is a CHANGELOG, parse that too! if (file_exists($tmpdirpath . 'CHANGELOG')) { try { $ch = new Core\Utilities\Changelog\Parser($chngName, $tmpdirpath . 'CHANGELOG'); $ch->parse(); // Get the version for this iteration. $chsec = $ch->getSection($model->get('version')); $model->set('packager_name', $chsec->getPackagerName()); $model->set('packager_email', $chsec->getPackagerEmail()); $model->set('datetime_released', $chsec->getReleasedDateUTC()); $model->set('changelog', $chsec->fetchAsHTML(null)); } catch (Exception $e) { // meh, we just won't have a changelog. } finally { if (file_exists($tmpdirpath . 'CHANGELOG')) { // Cleanup unlink($tmpdirpath . 'CHANGELOG'); } } } // Retrieve out the screenshots from this component. exec('tar -xzf "' . $tgz->getFilename() . '" -O ' . $xmlFile . ' > "' . $tmpdirpath . 'comp.xml"', $output, $ret); if (file_exists($tmpdirpath . 'comp.xml')) { try { $images = []; $c = new Component_2_1($tmpdirpath . 'comp.xml'); $screens = $c->getScreenshots(); if (sizeof($screens)) { foreach ($screens as $s) { // Extract out this screen and save it to the filesystem. $archivedFile = dirname($xmlFile) . '/' . $s; $localFile = \Core\Filestore\Factory::File('public/packagerepo-screens/' . $model->get('type') . '-' . $model->get('key') . '-' . $model->get('version') . '/' . basename($s)); // Write something into the file so that it exists on the filesystem. $localFile->putContents(''); // And now tar can extract directly to that destination! exec('tar -xzf "' . $tgz->getFilename() . '" -O ' . $archivedFile . ' > "' . $localFile->getFilename() . '"', $output, $ret); if (!$ret) { // Return code should be 0 on a successful write. $images[] = $localFile->getFilename(false); } } } $model->set('screenshots', $images); } catch (Exception $e) { // meh, we just won't have images.. } finally { if (file_exists($tmpdirpath . 'comp.xml')) { // Cleanup unlink($tmpdirpath . 'comp.xml'); } } } if ($model->changed()) { $model->save(true); $addedpackages++; } else { $skippedpackages++; } // But I can still cleanup! $tgz->delete(); $currentPercent += $percentEach; \Core\CLI\CLI::PrintProgressBar($currentPercent); } // Commit everything! PackageRepositoryPackageModel::CommitSaves(); return ['updated' => $addedpackages, 'skipped' => $skippedpackages, 'failed' => $failedpackages]; }
public function email_test(){ // Admin-only page. if(!\Core\user()->checkAccess('g:admin')){ return View::ERROR_ACCESSDENIED; } $request = $this->getPageRequest(); $view = $this->getView(); if(!$request->isPost()){ return View::ERROR_BADREQUEST; } if(!$request->getPost('email')){ return View::ERROR_BADREQUEST; } $view->mode = View::MODE_NOOUTPUT; $view->contenttype = View::CTYPE_HTML; $view->render(); $dest = $request->getPost('email'); $method = ConfigHandler::Get('/core/email/mailer'); $smtpHost = ConfigHandler::Get('/core/email/smtp_host'); $smtpUser = ConfigHandler::Get('/core/email/smtp_user'); $smtpPass = ConfigHandler::Get('/core/email/smtp_password'); $smtpPort = ConfigHandler::Get('/core/email/smtp_port'); $smtpSec = ConfigHandler::Get('/core/email/smtp_security'); $sendmailPath = ConfigHandler::Get('/core/email/sendmail_path'); $emailDebug = []; $emailDebug[] = 'Sending Method: ' . $method; switch($method){ case 'smtp': $emailDebug[] = 'SMTP Host: ' . $smtpHost . ($smtpPort ? ':' . $smtpPort : ''); $emailDebug[] = 'SMTP User/Pass: '******'//' . ($smtpPass ? '*** saved ***' : 'NO PASS') : 'Anonymous'); $emailDebug[] = 'SMTP Security: ' . $smtpSec; break; case 'sendmail': $emailDebug[] = 'Sendmail Path: ' . $sendmailPath; break; } CLI::PrintHeader('Sending test email to ' . $dest); CLI::PrintActionStart('Initializing Email System'); try{ $email = new Email(); $email->addAddress($dest); $email->setSubject('Test Email'); $email->templatename = 'emails/admin/test_email.tpl'; $email->assign('debugs', $emailDebug); $email->getMailer()->SMTPDebug = 2; CLI::PrintActionStatus(true); } catch(Exception $e){ CLI::PrintActionStatus(false); CLI::PrintError($e->getMessage()); CLI::PrintLine($e->getTrace()); return; } CLI::PrintActionStart('Sending Email via ' . $method); try{ $email->send(); CLI::PrintActionStatus(true); } catch(Exception $e){ CLI::PrintActionStatus(false); CLI::PrintError($e->getMessage()); CLI::PrintLine(explode("\n", $e->getTraceAsString())); } CLI::PrintHeader('Sent Headers:'); CLI::PrintLine(explode("\n", $email->getMailer()->CreateHeader())); CLI::PrintHeader('Sent Body:'); CLI::PrintLine(explode("\n", $email->getMailer()->CreateBody())); }
// All Models MUST reside in the global namespace in order to be valid. continue; } $ref = new ReflectionClass($class); if(!$ref->getProperty('HasSearch')->getValue()){ // This model doesn't have the searchable flag, skip it. continue; } CLI::PrintActionStart("Syncing searchable model $class"); $fac = new ModelFactory($class); foreach($fac->get() as $m){ /** @var Model $m */ $m->set('search_index_pri', '!'); $m->save(); } CLI::PrintActionStatus('ok'); $changes[] = "Synced searchable model " . $class; } } // Flush the system cache, just in case \Core\Cache::Flush(); \Core\Templates\Backends\Smarty::FlushCache(); CLI::PrintHeader('DONE!'); foreach($changes as $line){ CLI::PrintLine($line); }
/** * Set the 'EDITOR' variable to be set. * This is a linux-specific thing that svn shares also. * * The user will usually set their preferred EDITOR, be it vi/vim, emacs or nano. * If they didn't, ask the user for their choice. */ public static function RequireEditor() { global $previous_editor; // First, check the editor in the "session" file. \Core\CLI\CLI::LoadSettingsFile('editor'); if (isset($previous_editor)) $_SERVER['EDITOR'] = $previous_editor; if (!isset($_SERVER['EDITOR']) || $_SERVER['EDITOR'] == '') { // I need to assemble a list of editors currently on the system. $opts = array(); $default = false; if (($loc = trim(`which vi`))) $opts[$loc] = $loc; if (($loc = trim(`which vim`))) $opts[$loc] = $loc; if (($loc = trim(`which emacs`))) $opts[$loc] = $loc; if (($loc = trim(`which nano`))) { $opts[$loc] = $loc; $default = $loc; } $_SERVER['EDITOR'] = \Core\CLI\CLI::PromptUser( 'Which editor do you want to use for editing text files? If you are unsure, simply press enter if there is a default option.', $opts, $default ); // And remember this option. $previous_editor = $_SERVER['EDITOR']; \Core\CLI\CLI::SaveSettingsFile('editor', array('previous_editor')); } }
if(file_exists($destdir . 'repo.xml')){ // w00t, load it up and import the info! $repo = new RepoXML($destdir . 'repo.xml'); // Don't forget to remove any previous components! $repo->clearPackages(); } else{ // Just a new one works... $repo = new RepoXML(); } // Prompt the user if there's not information already set on the necessary ones. if(!$repo->getDescription()){ $desc = \Core\CLI\CLI::PromptUser('Please enter a short description for this repo.', 'textarea'); $repo->setDescription($desc); } // Load in the keys if not set. if(!sizeof($repo->getKeys())){ // Find and use the package maintainer's key. $out = array(); exec('gpg --homedir "' . GPG_HOMEDIR . '" --no-permission-warning --list-secret-keys', $out); $key = null; $currentkey = null; foreach($out as $line){ if(strpos($line, 'sec') === 0){ // Remember this ID for the next line, it may be the email. $currentkey = preg_replace('#^.*/([A-F0-9]*).*$#', '$1', $line); }
/** * Will return an array with the newest exported versions of each component. */ function get_exported_components(){ $c = []; $dir = ROOT_PDIR . '../exports/components'; if(!is_dir($dir)){ // Doesn't exist? Don't even try opening it. return $c; } $dh = opendir($dir); if(!$dh){ // Easy enough, just return a blank array! return $c; } while(($file = readdir($dh)) !== false){ if($file{0} == '.') continue; if(is_dir($dir . '/' . $file)) continue; // Get the extension type. if(preg_match('/\.tgz$/', $file)){ $signed = false; $fbase = substr($file, 0, -4); } elseif(preg_match('/\.tgz\.asc$/', $file)){ $signed = true; $fbase = substr($file, 0, -8); } else{ continue; } // Split up the name and the version. // This is a little touchy because a dash in the package name is perfectly valid. // instead, grab the last dash in the string. // Additionally, versions such as: // name-1.2.3 // name-blah-1.2.3 // name-blah-1.2.3-4 // must all be supported. preg_match('/^([a-z\.\-]*)-(r[0-9]|[0-9][0-9abrc\.\-]*)(~.*)?$/', $fbase, $fileparts); switch(sizeof($fileparts)){ case 3: $n = $fileparts[1]; $v = $fileparts[2]; break; case 4: $n = $fileparts[1]; $v = $fileparts[2] . $fileparts[3]; break; default: CLI::PrintWarning('Unsupported file version string: [' . $fbase . '], please submit this.'); continue; } //$dash = strrpos($fbase, '-'); //$n = substr($fbase, 0, $dash); //$v = substr($fbase, ($dash+1)); // instead, I need to look for a dash followed by a number. This should indicate the version number. //preg_match('/^(.*)\-([0-9]+.*)$/', $fbase, $matches); //$n = $matches[1]; //$v = $matches[2]; // Tack it on. if(!isset($c[$n])){ $c[$n] = ['version' => $v, 'signed' => $signed, 'filename' => $dir . '/' . $file]; } else{ switch(Core::VersionCompare($c[$n]['version'], $v)){ case -1: // Existing older, overwrite! $c[$n] = ['version' => $v, 'signed' => $signed, 'filename' => $dir . '/' . $file]; break; case 0: // Same, check the signed status. if($signed) $c[$n] = ['version' => $v, 'signed' => $signed, 'filename' => $dir . '/' . $file]; break; default: // Do nothing, current is at a higher version. } } } closedir($dh); return $c; } // function get_exported_components()
/** * @param $filename * @param $verbose bool Set to true for verbose real-time output. * */ private function _includeFileForUpgrade($filename, $verbose = false){ if($verbose){ CLI::PrintLine('Loading custom PHP file ' . $filename); } include($filename); }