/** * Get the single instance of the theme handler. * @return ThemeHandler */ public static function Singleton() { if (is_null(self::$instance)) { self::$instance = new self(); } return self::$instance; }
public function execute(){ require_once(ROOT_PDIR . 'core/libs/core/Core.class.php'); require_once(ROOT_PDIR . 'core/libs/core/ComponentHandler.class.php'); require_once(ROOT_PDIR . 'core/helpers/UpdaterHelper.class.php'); // Is the system not installed yet? //if(!\Core\DB()->tableExists(DB_PREFIX . 'component')){ try{ \Core::LoadComponents(); //\ThemeHandler::GetTheme('default')->install(); \ThemeHandler::GetTheme('base-v3')->install(); unset($_SESSION['passes']); // Yup, that's it! // The core system handles all installs automatically. \core\redirect(ROOT_WDIR); } catch(\Exception $e){ $this->getTemplate()->assign('errors', $e->getMessage()); $this->getTemplate()->assign('component', 'Core Plus'); } }
/** * Listing controller of the updater. * */ public function index() { $view = $this->getView(); $sitecount = UpdateSiteModel::Count(); $components = array(); foreach(Core::GetComponents() as $k => $c){ // Skip the core. if($k == 'core') continue; $components[$k] = $c; } // These should really be sorted by name ksort($components); // Merge in the disabled ones too! $components = array_merge($components, Core::GetDisabledComponents()); // If the theme is disabled, this won't be available. if(class_exists('ThemeHandler')){ $themes = ThemeHandler::GetAllThemes(); } else{ $themes = array(); } $view->title = 't:STRING_SYSTEM_UPDATER'; $view->assign('sitecount', $sitecount); $view->assign('components', $components); $view->assign('core', Core::GetComponent('core')); $view->assign('themes', $themes); }
public static function _SaveEditorHandler(Form $form) { $newmodel = $form->getModel(); $file = $form->getElement('file')->get('value'); $activefile = $form->getElement('filetype')->get('value'); // The inbound file types depends on how to read the file. switch ($activefile) { case 'template': $filename = \Core\Templates\Template::ResolveFile($file); $customfilename = ROOT_PDIR . 'themes/custom/' . $file; break; case 'file': $filename = $file; // It'll get transposed. $customfilename = ROOT_PDIR . 'themes/custom/' . $file; break; default: \Core\set_message('Unsupported file type: ' . $activefile, 'error'); return false; } $customfh = \Core\Filestore\Factory::File($customfilename); if ($customfh->exists()) { // If the custom one exists... this will be the source file too! $sourcefh = $customfh; } else { $sourcefh = \Core\Filestore\Factory::File($filename); } // Check and see if they're the same, ie: no change. I don't want to create a bunch of moot revisions. if ($newmodel->get('content') == $sourcefh->getContents()) { \Core\set_message('No changes performed.', 'info'); return '/theme'; } // Before I overwrite this file, check and see if the original has been snapshot first! $c = ThemeTemplateChangeModel::Count(['filename = ' . $file]); if (!$c) { $original = new ThemeTemplateChangeModel(); $original->setFromArray(['comment' => 'Original File', 'filename' => $file, 'content' => $sourcefh->getContents(), 'content_md5' => $sourcefh->getHash(), 'updated' => $sourcefh->getMTime()]); $original->save(); } // All destination files get written to the custom directory! $customfh->putContents($newmodel->get('content')); $hash = $customfh->getHash(); /* // What happens now is based on the type of the inbound file. switch($activefile){ case 'skin': // Just replace the contents of that file. $fh->putContents($newmodel->get('content')); $hash = $fh->getHash(); break; case 'template': // This gets written into the current theme directory. $themefh = \Core\Filestore\Factory::File(ROOT_PDIR . 'themes/' . ConfigHandler::Get('/theme/selected') . '/' . $file); $themefh->putContents($newmodel->get('content')); $hash = $themefh->getHash(); break; case 'style': case 'file': // This gets written into the current theme directory. $themefh = \Core\Filestore\Factory::File(ROOT_PDIR . 'themes/' . ConfigHandler::Get('/theme/selected') . '/' . $file); $themefh->putContents($newmodel->get('content')); $hash = $themefh->getHash(); // This is required to get assets updated to the CDN correctly. $theme = ThemeHandler::GetTheme(); $hash = $themefh->getHash(); $theme->addAssetFile(array('file' => $file, 'md5' => $hash)); $theme->save(); $theme->reinstall(); default: } */ // Make a record of this change too! $change = new ThemeTemplateChangeModel(); $change->setFromArray(['comment' => $newmodel->get('comment'), 'filename' => $file, 'content' => $newmodel->get('content'), 'content_md5' => $hash]); $change->save(); if ($activefile == 'file') { // Reinstall all assets too! foreach (Core::GetComponents() as $component) { $component->reinstall(); } // And the current theme. ThemeHandler::GetTheme(ConfigHandler::Get('/theme/selected'))->reinstall(); } \Core\set_message('Updated file successfully', 'success'); return '/theme'; }
else{ CLI::PrintError('Invalid XML definition, all themes in the bundle.xml MUST contain either a "name" or "key" attribute.'); die(); } $export[] = [ 'name' => $name, 'keyname' => $key, 'type' => 'theme', 'src' => BASE_DIR . 'exports/themes', 'dest' => $destdir . '/' . $desttgz . '/themes/' . $key ]; } } else{ foreach(\ThemeHandler::GetAllThemes() as $t){ /** @var Theme\Theme $t */ $export[] = [ 'name' => $t->getName(), 'keyname' => $t->getKeyName(), 'type' => 'theme', 'src' => BASE_DIR . 'exports/themes', 'dest' => $destdir . '/' . $desttgz . '/themes/' . $t->getKeyName(), ]; } } CLI::PrintHeader('Assembling Packages for ' . $b['name'] . ' ' . $version); $changelog = '<h2>Packages included in ' . $b['name'] . ' ' . $version . '</h2>' . "\n\n";
/** * Load all the components in the system, replacement for the Core. * @throws CoreException */ private function _loadComponents() { // cannot reload components. if ($this->_components) return null; $this->_components = array(); $this->_libraries = array(); $tempcomponents = false; Core\Utilities\Logger\write_debug('Starting loading of component metadata'); // If the site is in DEVELOPMENT mode, component caching would probably be a bad idea; ie: the developer probably wants // those component files loaded everytime. if(DEVELOPMENT_MODE){ $enablecache = false; } else{ $enablecache = true; } // Is there a cache of elements available? This is a primary system cache that greatly increases performance, // since it will no longer have to run through each component.xml file to register each one. if($enablecache){ Core\Utilities\Logger\write_debug('Checking core-components cache'); // Try to load up the cached components and check them first. $tempcomponents = \Core\Cache::Get('core-components', (3600 * 24)); if($tempcomponents !== false){ // Cached components only need to be loaded. foreach ($tempcomponents as $c) { try { $c->load(); } catch (Exception $e) { // Don't completely bail out here, just invalidate the cache and continue on. \Core\Cache::Delete('core-components'); $tempcomponents = false; } } } } if(!$enablecache || $tempcomponents == false){ \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Scanning for component.xml files manually'); Core\Utilities\Logger\write_debug('Scanning for component.xml files manually'); // Core is first, (obviously) $tempcomponents['core'] = ComponentFactory::Load(ROOT_PDIR . 'core/component.xml'); Core\Utilities\Logger\write_debug('Core component loaded'); // First, build my cache of components, regardless if the component is installed or not. $dh = opendir(ROOT_PDIR . 'components'); if (!$dh) throw new CoreException('Unable to open directory [' . ROOT_PDIR . 'components/] for reading.'); // This will read through every directory in 'components', which is // where all components in the system are installed to. while (($file = readdir($dh)) !== false) { // skip hidden directories. if ($file{0} == '.') continue; // skip non-directories if (!is_dir(ROOT_PDIR . 'components/' . $file)) continue; // Skip directories that do not have a readable component.xml file. if (!is_readable(ROOT_PDIR . 'components/' . $file . '/component.xml')) continue; //Core\Utilities\Logger\write_debug(' * Loading component ' . $file); $c = ComponentFactory::Load(ROOT_PDIR . 'components/' . $file . '/component.xml'); Core\Utilities\Logger\write_debug('Opened component ' . $file); // All further operations are case insensitive. // The original call to Component needs to be case sensitive because it sets the filename to pull. $file = strtolower($file); // If the component was flagged as invalid.. just skip to the next one. if (!$c->isValid()) { if (DEVELOPMENT_MODE) { \Core\set_message('Component ' . $c->getName() . ' appears to be invalid.'); } continue; } $tempcomponents[$file] = $c; unset($c); } closedir($dh); \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Component XML files scanned'); // Now I probably could actually load the components! foreach ($tempcomponents as $c) { /** @var Component_2_1 $c */ try { // Load some of the data in the class so that it's available in the cached version. // This is because the component 2.1 has built-in caching for many of the XML requests. // by calling them once, that lookup data is cached in that component, which in turn gets // copied to the cache version here! $c->load(); $c->getClassList(); $c->getViewSearchDir(); $c->getSmartyPluginDirectory(); $c->getWidgetList(); } catch (Exception $e) { var_dump($e); die(); } } // Cache this list! if($enablecache){ Core\Utilities\Logger\write_debug(' * Caching core-components for next pass'); \Core\Cache::Set('core-components', $tempcomponents, (3600 * 24)); } } $list = $tempcomponents; \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Component metadata loaded, starting registration'); Core\Utilities\Logger\write_debug(' * Component metadata loaded, starting registration'); // The core component at a minimum needs to be loaded and registered. // $this->_registerComponent($list['core']); // $this->_components['core']->loadFiles(); // unset($list['core']); // Now that I have a list of components available, copy them into a list of // components that are installed. do { $size = sizeof($list); foreach ($list as $n => $c) { /** @var $c Component_2_1 */ // Disabled components don't get recognized. if($c->isInstalled() && !$c->isEnabled()){ // But they do get sent to the disabled list! $this->_componentsDisabled[$n] = $c; unset($list[$n]); continue; } // Clear out the temporary class list $this->_tmpclasses = []; // If it's loaded, register it and remove it from the list! if ($c->isInstalled() && $c->isLoadable() && $c->loadFiles()) { try{ // Allow for on-the-fly package upgrading regardless of DEV mode or not. if ($c->needsUpdated()) { // Load this component's classes in case an upgrade operation requires one. // This allows a component to be loaded partially without completely being loaded. $this->_tmpclasses = $c->getClassList(); // Lock the site first! // This is because some upgrade procedures take a long time to upgrade. file_put_contents(TMP_DIR . 'lock.message', 'Core Plus is being upgraded, please try again in a minute. '); $c->upgrade(); unlink(TMP_DIR . 'lock.message'); } } catch(Exception $e){ SystemLogModel::LogErrorEvent('/core/component/failedupgrade', 'Ignoring component [' . $n . '] due to an error during upgrading!', $e->getMessage()); unlink(TMP_DIR . 'lock.message'); //$c->disable(); $this->_componentsDisabled[$n] = $c; unset($list[$n]); continue; } try{ $this->_components[$n] = $c; $this->_registerComponent($c); $c->loadSupplementalModels(); } catch(Exception $e){ SystemLogModel::LogErrorEvent('/core/component/failedregister', 'Ignoring component [' . $n . '] due to an error during registration!', $e->getMessage()); //$c->disable(); $this->_componentsDisabled[$n] = $c; unset($list[$n]); continue; } unset($list[$n]); continue; } // Allow for on-the-fly package upgrading regardless of DEV mode or not. // Guess this is needed for the loadFiles part... if ($c->isInstalled() && $c->needsUpdated() && $c->isLoadable()) { // Lock the site first! // This is because some upgrade procedures take a long time to upgrade. file_put_contents(TMP_DIR . 'lock.message', 'Core Plus is being upgraded, please try again in a minute. '); $c->upgrade(); $c->loadFiles(); $this->_components[$n] = $c; $this->_registerComponent($c); unlink(TMP_DIR . 'lock.message'); unset($list[$n]); continue; } // Allow packages to be auto-installed if in DEV mode. // If DEV mode is not enabled, just install the new component, do not enable it. if (!$c->isInstalled() && $c->isLoadable()) { // Load this component's classes in case an install operation requires one. // This allows a component to be loaded partially without completely being loaded. $this->_tmpclasses = $c->getClassList(); // w00t $c->install(); // BLAH, until I fix the disabled-packages-not-viewable bug... $c->enable(); $c->loadFiles(); $this->_components[$n] = $c; $this->_registerComponent($c); /* if(!DEVELOPMENT_MODE){ $c->disable(); } else{ $c->enable(); $c->loadFiles(); $this->_components[$n] = $c; $this->_registerComponent($c); } */ unset($list[$n]); continue; } } } while ($size > 0 && ($size != sizeof($list))); // If dev mode is enabled, display a list of components installed but not loadable. foreach ($list as $n => $c) { //$this->_components[$n] = $c; $this->_componentsDisabled[$n] = $c; // Ignore anything with the execmode different, those should be minor notices for debugging if anything. if ($c->error & Component_2_1::ERROR_WRONGEXECMODE) continue; if (DEVELOPMENT_MODE) { SystemLogModel::LogErrorEvent('/core/component/missingrequirement', 'Could not load installed component ' . $n . ' due to requirement failed.', $c->getErrors()); } } // Don't forget to load the themes too! if(class_exists('ThemeHandler')){ foreach(ThemeHandler::GetAllThemes() as $theme){ /** @var $theme Theme */ $theme->load(); } } // Lastly, make sure that the template path cache is updated! if(class_exists('\\Core\\Templates\\Template')){ \Core\Templates\Template::RequeryPaths(); } }
/** * Page to test the UI of various Core elements */ public function testui(){ $view = $this->getView(); $request = $this->getPageRequest(); if(!\Core\user()->checkAccess('g:admin')){ // This test page is an admin-only utility. return View::ERROR_ACCESSDENIED; } $lorem = new BaconIpsumGenerator(); $skins = []; $admindefault = null; foreach(ThemeHandler::GetTheme()->getSkins() as $dat){ $skins[ $dat['file'] ] = $dat['title']; if($dat['admindefault']) $admindefault = $dat['file']; } if($request->getParameter('skin')){ $skin = $request->getParameter('skin'); } else{ $skin = $admindefault; } $view->mastertemplate = $skin; $view->title = 'Test General UI/UX'; $view->assign('lorem_p', $lorem->getParagraphsAsMarkup(3)); $view->assign( 'lis', [ $lorem->getWord(3), $lorem->getWord(3), $lorem->getWord(3), $lorem->getWord(3), $lorem->getWord(3), ] ); $view->assign('skins', $skins); $view->assign('skin', $skin); }
} else{ $change = $c->reinstall($verbosity); } if($change !== false){ $changes = array_merge($changes, $change); } } } // And the current theme if it's different. $theme = ConfigHandler::Get('/theme/selected'); if($theme != 'default'){ $t = \ThemeHandler::GetTheme($theme); if( $onlyTheme && ($t->getKeyName() == $onlyTheme || $t->getName() == $onlyTheme) || ($onlyTheme === null && $onlyComponent === null && $onlyCore === null) ){ if($verbosity == 1){ CLI::PrintLine(''); CLI::PrintLine('Reinstalling Theme ' . $theme); } elseif($verbosity == 2){ CLI::PrintHeader('Reinstalling Theme ' . $theme); } if($assets){ $change = $t->_parseAssets(true, $verbosity);
/** * Display a listing of all widgets registered in the system. */ public function admin(){ $view = $this->getView(); $request = $this->getPageRequest(); $viewer = \Core\user()->checkAccess('p:/core/widgets/manage'); $manager = \Core\user()->checkAccess('p:/core/widgets/manage'); if(!($viewer || $manager)){ return View::ERROR_ACCESSDENIED; } // Build a list of create pages for all registered components. $components = Core::GetComponents(); $pages = []; $skins = []; $selected = null; $selectedtype = null; $baseurl = null; $selectoptions = []; $links = []; $theme = ThemeHandler::GetTheme(); $formtheme = null; $formskin = null; $formtemplate = null; foreach($components as $c){ /** @var Component_2_1 $c */ $viewdir = $c->getViewSearchDir(); if($viewdir){ $dirlen = strlen($viewdir); $component = $c->getName(); $dh = \Core\Filestore\Factory::Directory($viewdir); //$pagetplfiles = $dh->ls('tpl', true); $pagetplfiles = $dh->ls(null, true); // not sure why getFilename(path) isn't working as expected, but this works too. foreach($pagetplfiles as $obj){ // I don't want directories. if($obj instanceof \Core\Filestore\Directory) continue; /** @var $obj \Core\Filestore\File */ $file = substr($obj->getFilename(), $dirlen); // Since this is a template, it may actually be in a different location than where the package maintainer put it. // ie: user template user/templates/pages/user/view.tpl may be installed to themes/myawesometheme/pages/user/view.tpl instead. $tpl = Core\Templates\Template::Factory($file); if($tpl->hasWidgetAreas()){ $pagetitle = $file; if(strpos($pagetitle, 'pages/') === 0){ $pagetitle = substr($pagetitle, 6); } // Replace directory slashes with a space $pagetitle = str_replace(['/', '-'], ' ', $pagetitle); // Capitalize them $pagetitle = ucwords($pagetitle); // And trim off the ".tpl" suffix. $pagetitle = substr($pagetitle, 0, -4); $pages[$file] = $pagetitle; } } } foreach($c->getXML()->getElements('/widgets/widgetcreate') as $node){ /** @var DOMElement $node */ if($node->getAttribute('baseurl')){ $nodebaseurl = $node->getAttribute('baseurl'); $image = ''; } elseif($node->getAttribute('class')){ /** @var Widget_2_1 $obj */ $obj = Widget_2_1::Factory($node->getAttribute('class')); $nodebaseurl = '/widget/create?class=' . $node->getAttribute('class'); if($obj){ $image = $obj->getPreviewImage(); } else{ \Core\set_message('Invalid "widgetcreate" found in ' .$node->getAttribute('class') . ', ' . $node->getAttribute('title'), 'error'); $image = ''; } } else{ \Core\set_message('Invalid "widgetcreate" found in ' . $c->getName() . ', ' . $node->getAttribute('title'), 'error'); continue; } $links[] = [ 'baseurl' => $nodebaseurl, 'title' => $node->getAttribute('title'), 'preview' => $image, ]; } } // Build the array of skins for the current theme $themeskins = $theme->getSkins(); $defaultskin = null; foreach($themeskins as $dat){ $skins[ 'skins/' . $dat['file'] ] = $dat['title']; if($dat['default']){ $defaultskin = 'skins/' . $dat['file']; } } // Now that the various templates have been loaded into a flat array, I need to sort them. asort($pages); asort($skins); foreach($skins as $k => $v){ $selectoptions[ $k ] = 'Skin: ' . $v; } foreach($pages as $k => $v){ $selectoptions[ $k ] = 'Page: ' . $v; } if($request->getParameter('baseurl')){ // It's a URL-specific request, lookup which template that page used last. $baseurl = $request->getParameter('baseurl'); $page = PageModel::Construct($baseurl); if(!isset($pages[ $page->get('last_template') ])){ \Core\set_message('Requested page template does not seem to contain any widget areas.', 'error'); \Core\go_back(); } $selected = $page->get('last_template'); $selectedtype = 'url'; $formtemplate = $selected; } elseif($request->getParameter('template')){ $selected = $request->getParameter('template'); if(isset($pages[ $selected ])){ $selectedtype = 'page'; $formtemplate = $selected; } else{ $selectedtype = 'skin'; $formtheme = $theme->getKeyName(); $formskin = $selected; } } else{ // Just use the default theme skin. $selected = $defaultskin; $selectedtype = 'skin';$formtheme = $theme->getKeyName(); $formskin = $selected; } $template = \Core\Templates\Template::Factory($selected); $areas = $template->getWidgetAreas(); $installables = [0 => '']; foreach($areas as $k => $dat){ // Ensure that each area has a widgets array, (even if it's empty) $areas[$k]['widgets'] = []; $installables[] = $dat['installable']; } $installables = array_unique($installables); $factory = new ModelFactory('WidgetInstanceModel'); $factory->order('weight'); if(Core::IsComponentAvailable('multisite') && MultiSiteHelper::IsEnabled()){ $factory->whereGroup('or', ['site = -1', 'site = ' . MultiSiteHelper::GetCurrentSiteID()]); } if($selectedtype == 'skin'){ // First, the skin-level where clause. $skinwhere = new Core\Datamodel\DatasetWhereClause(); $skinwhere->setSeparator('AND'); //$skinwhere->addWhere('theme = ' . $theme->getKeyName()); $skinwhere->addWhere('template = ' . $selected); $factory->where($skinwhere); } elseif($selectedtype == 'page'){ $factory->where('template = ' . $selected); } elseif($selectedtype == 'url'){ $factory->where('page_baseurl = ' . $baseurl); } else{ \Core\set_message('Invalid/unknown template type', 'error'); \Core\go_back(); } foreach($factory->get() as $wi){ /** @var $wi WidgetInstanceModel */ $a = $wi->get('widgetarea'); $areas[$a]['widgets'][] = $wi; } $available = WidgetModel::Find(['installable IN ' . implode(', ', $installables)]); /* $table = new Core\ListingTable\Table(); $table->setName('/admin/widgets'); $table->setModelName('WidgetModel'); // Add in all the columns for this listing table. $table->addColumn('Title', 'title'); if(Core::IsComponentAvailable('enterprise') && MultiSiteHelper::IsEnabled() && \Core\user()->checkAccess('g:admin')){ $table->addColumn('Site', 'site', false); $ms = true; } else{ $ms = false; } $table->getModelFactory()->where('installable IN ' . implode(', ', $installables)); $table->addColumn('Base URL', 'baseurl'); $table->addColumn('Installable', 'installable'); $table->addColumn('Created', 'created'); $table->loadFiltersFromRequest(); */ $view->mastertemplate = 'admin'; $view->title = 'All Widgets'; //$view->assign('table', $table); $view->assign('available_widgets', $available); $view->assign('links', $links); $view->assign('manager', $manager); $view->assign('theme', $formtheme); $view->assign('skin', $formskin); $view->assign('template', $selected); $view->assign('page_template', $formtemplate); $view->assign('page_baseurl', $baseurl); $view->assign('options', $selectoptions); $view->assign('selected', $selected); $view->assign('areas', $areas); //$view->assign('multisite', $ms); }
/** * Check if this package is already installed and current (at least as new version installed) * * @return boolean */ public function isCurrent() { switch($this->getType()){ case 'core': case 'component': $c = Core::GetComponent($this->getName()); if (!$c) return false; // Not installed? Not current. return version_compare($c->getVersion(), $this->getVersion(), 'ge'); case 'theme': $t = ThemeHandler::GetTheme($this->getName()); if (!$t) return false; // Not installed? Not current. return version_compare($t->getVersion(), $this->getVersion(), 'ge'); } }
echo 'Installing default theme...'; $change = \ThemeHandler::GetTheme('default')->install(); if($change === false){ echo ' No changes' . "\n"; } else{ echo "\n" . implode("\n", $change) . "\n"; } */ // And the current theme if it's different. $theme = ConfigHandler::Get('/theme/selected'); if($theme != 'default'){ CLI::PrintHeader('Reinstalling Theme ' . $theme); $change = \ThemeHandler::GetTheme($theme)->install(2); if($change !== false){ $changes = array_merge($changes, $change); } } if(CDN_TYPE != 'local'){ CLI::PrintHeader('Synchronizing Public Files'); // Check to see if any public files need to be deployed to the CDN. // This behaves the same as asset deployment, but is a utility-only function that is beyond the normal reinstallation procedure. // However, seeing as this is a utility script... :) $public = new \Core\Filestore\Backends\DirectoryLocal(CDN_LOCAL_PUBLICDIR); $dirname = $public->getPath(); $dirlen = strlen($dirname);
/** * Get the Core object for this package, be it a Component or Theme. * * @return \Component|\Theme\Theme */ private function _getObject(){ switch($this->_type){ case 'core': return \Core::GetComponent('core'); case 'component': return \Core::GetComponent($this->_keyname); case 'theme': return \ThemeHandler::GetTheme($this->_keyname); } }
'component' => $c, 'dir' => ROOT_PDIR . $file . '/', ]; } closedir($dh); unset($file, $version, $title, $c, $dh); // Load in all themes currently on the system $dir = ROOT_PDIR . 'themes'; $dh = opendir($dir); while(($file = readdir($dh)) !== false){ if($file{0} == '.') continue; if(!is_dir($dir . '/' . $file)) continue; if(!is_readable($dir . '/' . $file . '/' . 'theme.xml')) continue; $t = ThemeHandler::GetTheme($file); // What's this file's version? $xml = new XMLLoader(); $xml->setRootName('theme'); if(!$xml->loadFromFile($dir . '/' . $file . '/theme.xml')){ CLI::PrintLine('Skipping theme ' . $file . ', unable to load XML file'); continue; } // Get the current version, this will be used to autocomplete for the next version. //$version = $xml->getRootDOM()->getAttribute("version"); $version = $t->getVersion(); // If display versions is requested, tack on the version number too! if($opts['listversions']){
/** * Perform a lookup on any repository sites installed and get a list of provided pacakges. * * @return array */ public static function GetUpdates(){ // Allow this to be cached for x amount of time. This will save the number of remote requests. //if(false && isset($_SESSION['updaterhelper_getupdates']) && $_SESSION['updaterhelper_getupdates']['expire'] <= time()){ // return $_SESSION['updaterhelper_getupdates']['data']; //} // Build a list of components currently installed, this will act as a base. $components = array(); $core = array(); $themes = array(); $sitecount = 0; $pkgcount = 0; $current = Core::GetComponents(); $froze = \ConfigHandler::Get('/core/updater/versionfreeze'); // If Core isn't installed yet, GetComponents will yield null. if($current === null) $current = array(); /** @var string $backportVersion Add support for "~bpoXYZ" version strings for backported packages. */ $coreVersion = Core::GetVersion(); $coreVersionParts = Core::VersionSplit($coreVersion); $backportVersion = '~bpo' . $coreVersionParts['major'] . $coreVersionParts['minor'] . $coreVersionParts['point']; foreach($current as $c){ /** @var $c Component_2_1 */ $n = $c->getKeyName(); $parts = Core::VersionSplit($c->getVersion()); if($n == 'core'){ $core = array( 'name' => $n, 'title' => $c->getName(), 'version' => $c->getVersion(), 'feature' => $parts['major'] . '.' . $parts['minor'], 'source' => 'installed', 'description' => $c->getDescription(), 'provides' => $c->getProvides(), 'requires' => $c->getRequires(), 'location' => null, 'status' => 'installed', 'type' => 'core', 'typetitle' => 'Core', 'key' => null, 'destdir' => $c->getBaseDir(), ); } else{ $components[$n] = array( 'name' => $n, 'title' => $c->getName(), 'version' => $c->getVersion(), 'feature' => $parts['major'] . '.' . $parts['minor'], 'source' => 'installed', 'description' => $c->getDescription(), 'provides' => $c->getProvides(), 'requires' => $c->getRequires(), 'location' => null, 'status' => 'installed', 'type' => 'components', 'typetitle' => 'Component ' . $c->getName(), 'key' => null, 'destdir' => $c->getBaseDir(), ); } } foreach(Core::GetDisabledComponents() as $c){ /** @var $c Component_2_1 */ $n = $c->getKeyName(); $parts = Core::VersionSplit($c->getVersion()); $components[$n] = array( 'name' => $n, 'title' => $c->getName(), 'version' => $c->getVersion(), 'feature' => $parts['major'] . '.' . $parts['minor'], 'source' => 'installed', 'description' => $c->getDescription(), 'provides' => $c->getProvides(), 'requires' => $c->getRequires(), 'location' => null, 'status' => 'disabled', 'type' => 'components', 'typetitle' => 'Component ' . $c->getName(), 'key' => null, 'destdir' => $c->getBaseDir(), ); } // And repeat for the themes. // I need to do a check if they exist because if called from the installer, it may not. if(class_exists('ThemeHandler')){ $currentthemes = ThemeHandler::GetAllThemes(); if($currentthemes === null) $currentthemes = array(); } else{ $currentthemes = array(); } foreach($currentthemes as $t){ /** @var $t Theme */ $n = $t->getKeyName(); $parts = Core::VersionSplit($t->getVersion()); $themes[$n] = array( 'name' => $n, 'title' => $t->getName(), 'version' => $t->getVersion(), 'feature' => $parts['major'] . '.' . $parts['minor'], 'source' => 'installed', 'description' => $t->getDescription(), 'location' => null, 'status' => 'installed', 'type' => 'themes', 'typetitle' => 'Theme ' . $t->getName(), 'key' => null, 'destdir' => $t->getBaseDir(), ); } // Now, look up components from all the updates sites. // If the system isn't installed yet, then this will not be found. Just use a blank array. if(class_exists('UpdateSiteModel')){ $updatesites = UpdateSiteModel::Find(); } else{ $updatesites = array(); } foreach($updatesites as $site){ if(!$site->isValid()) continue; ++$sitecount; $file = $site->getFile(); $repoxml = new RepoXML(); $repoxml->loadFromFile($file); $rootpath = dirname($file->getFilename()) . '/'; foreach($repoxml->getPackages() as $pkg){ /** @var $pkg PackageXML */ // Already installed and is up to date, don't do anything. //if($pkg->isCurrent()) continue; $n = str_replace(' ', '-', strtolower($pkg->getName())); $type = $pkg->getType(); if($n == 'core') $type = 'core'; // Override the core, even though it is a component... ++$pkgcount; switch($type){ case 'core': $vers = $pkg->getVersion(); // Only display the newest version available. if(!Core::VersionCompare($vers, $core['version'], 'gt')) continue; // Only display new feature versions if it's not frozen. $parts = Core::VersionSplit($pkg->getVersion()); if($froze && $core['feature'] != $parts['major'] . '.' . $parts['minor']) continue; $core = array( 'name' => $n, 'title' => $pkg->getName(), 'version' => $vers, 'feature' => $parts['major'] . '.' . $parts['minor'], 'source' => 'repo-' . $site->get('id'), 'sourceurl' => $site->get('url'), 'description' => $pkg->getDescription(), 'provides' => $pkg->getProvides(), 'requires' => $pkg->getRequires(), 'location' => $pkg->getFileLocation(), 'status' =>'update', 'type' => 'core', 'typetitle' => 'Core ', 'key' => $pkg->getKey(), 'destdir' => ROOT_PDIR, ); break; case 'component': $vers = $pkg->getVersion(); $parts = Core::VersionSplit($pkg->getVersion()); $packagedWithVersion = $pkg->getRootDOM()->getAttribute('packager'); if($packagedWithVersion && Core::VersionCompare($packagedWithVersion, $coreVersion, '>')){ // Skip any package created with a newer version of Core than what is currently installed! continue; } // Is it already loaded in the list? if(isset($components[$n])){ if(strpos($vers, '~bpo') !== false && strpos($vers, $backportVersion) === false){ // Skip back ported versions not specifically for this version of Core. // This will check and see if the string ~bpo is present, // and when it is, enforce that it matches exactly this version of Core. continue; } // I only want the newest version. if(!Core::VersionCompare($vers, $components[$n]['version'], 'gt')){ continue; } // Only display new feature versions if it's not frozen. if( $froze && $components[$n]['status'] == 'installed' && $components[$n]['feature'] != $parts['major'] . '.' . $parts['minor'] ){ continue; } } // If it's available in the core, it's an update... otherwise it's new. $status = Core::GetComponent($n) ? 'update' : 'new'; $components[$n] = array( 'name' => $n, 'title' => $pkg->getName(), 'version' => $vers, 'feature' => $parts['major'] . '.' . $parts['minor'], 'source' => 'repo-' . $site->get('id'), 'sourceurl' => $site->get('url'), 'description' => $pkg->getDescription(), 'provides' => $pkg->getProvides(), 'requires' => $pkg->getRequires(), 'location' => $pkg->getFileLocation(), 'status' => $status, 'type' => 'components', 'typetitle' => 'Component ' . $pkg->getName(), 'key' => $pkg->getKey(), 'destdir' => ROOT_PDIR . 'components/' . $n . '/', ); break; case 'theme': $vers = $pkg->getVersion(); $parts = Core::VersionSplit($pkg->getVersion()); // Is it already loaded in the list? if(isset($themes[$n])){ // I only want the newest version. if(!Core::VersionCompare($vers, $themes[$n]['version'], 'gt')) continue; // Only display new feature versions if it's not frozen. if( $froze && $themes[$n]['status'] == 'installed' && $themes[$n]['feature'] != $parts['major'] . '.' . $parts['minor'] ){ continue; } } $status = ThemeHandler::GetTheme($n) ? 'update' : 'new'; $themes[$n] = array( 'name' => $n, 'title' => $pkg->getName(), 'version' => $vers, 'feature' => $parts['major'] . '.' . $parts['minor'], 'source' => 'repo-' . $site->get('id'), 'sourceurl' => $site->get('url'), 'description' => $pkg->getDescription(), 'location' => $pkg->getFileLocation(), 'status' => $status, 'type' => 'themes', 'typetitle' => 'Theme ' . $pkg->getName(), 'key' => $pkg->getKey(), 'destdir' => ROOT_PDIR . 'themes/' . $n . '/', ); } //var_dump($pkg->asPrettyXML()); die(); } } // Give me the components in alphabetical order. ksort($components); ksort($themes); // Cache this for next pass. //$_SESSION['updaterhelper_getupdates'] = array(); //$_SESSION['updaterhelper_getupdates']['data'] = array('core' => $core, 'components' => $components, 'themes' => $themes); //$_SESSION['updaterhelper_getupdates']['expire'] = time() + 60; return [ 'core' => $core, 'components' => $components, 'themes' => $themes, 'sitecount' => $sitecount, 'pkgcount' => $pkgcount, ]; }
public function __construct($atts = null) { error_log(__CLASS__ . ' is candidate for immediate removal, please change this code!', E_USER_DEPRECATED); // Defaults $this->_attributes['name'] = 'page'; if ($atts instanceof PageModel) { parent::__construct(array('name' => 'page')); $page = $atts; } else { if(isset($atts['model']) && $atts['model'] instanceof PageModel){ // Everything is based off the page. $page = $atts['model']; unset($atts['model']); parent::__construct($atts); } else{ parent::__construct($atts); // BaseURL needs to be set for this to work. //if(!$this->get('baseurl')) return null; // Everything is based off the page. $page = new PageModel($this->get('baseurl')); } } $this->_attributes['baseurl'] = $page->get('baseurl'); $name = $this->_attributes['name']; // I need to get a list of pages to offer as a dropdown for selecting the "parent" page. $f = new ModelFactory('PageModel'); if ($this->get('baseurl')) $f->where('baseurl != ' . $this->get('baseurl')); $opts = PageModel::GetPagesAsOptions($f, '-- No Parent Page --'); $this->addElement( 'pageparentselect', array( 'name' => $name . "[parenturl]", 'title' => 'Parent Page', 'value' => strtolower($page->get('parenturl')), 'options' => $opts ) ); // Title $this->addElement( 'text', array( 'name' => $name . "[title]", 'title' => 'Title', 'value' => $page->get('title'), 'description' => 'Every page needs a title to accompany it, this should be short but meaningful.', 'required' => true ) ); // Rewrite url. $this->addElement( 'pagerewriteurl', array( 'name' => $name . "[rewriteurl]", 'title' => 'Page URL', 'value' => $page->get('rewriteurl'), 'description' => 'Starts with a "/", omit ' . ROOT_URL, 'required' => true ) ); $this->addElement( 'access', array( 'name' => $name . "[access]", 'title' => 'Access Permissions', 'value' => $page->get('access') ) ); $this->addElement( 'pagemetas', array( 'name' => $name . '_meta', 'model' => $page, ) ); // Give me all the skins available on the current theme. $skins = array('' => '-- Site Default Skin --'); foreach(ThemeHandler::GetTheme(null)->getSkins() as $s){ $n = ($s['title']) ? $s['title'] : $s['file']; if($s['default']) $n .= ' (default)'; $skins[$s['file']] = $n; } if(sizeof($skins) > 2){ $this->addElement( 'select', array( 'name' => $name . "[theme_template]", 'title' => 'Theme Skin', 'value' => $page->get('theme_template'), 'options' => $skins ) ); } }
} if($onlyTheme){ if(ThemeHandler::GetTheme($onlyTheme) === false){ // Run through and try to find it by keyname or regular name. foreach(ThemeHandler::GetAllThemes() as $t){ /** @var \Theme\Theme $t */ if($t->getKeyName() == $onlyTheme || $t->getName() == $onlyTheme){ $onlyTheme = $c->getKeyName(); break; } } unset($t); } if(ThemeHandler::GetTheme($onlyTheme) === false){ \Core\CLI\CLI::PrintError('Unable to locate theme ' . $onlyTheme); exit; } } // Can we compile SCSS files too? if(($compileSCSSFull || $compileSCSSDev) && exec('which sass') == ''){ echo "Skipping compiling of SASS resources, you do not have the sass compiler installed!\n"; } elseif(($compileSCSSFull || $compileSCSSDev)){ $sassversion = exec("sass --version | sed 's:^Sass \\([0-9\\.]*\\).*:\\1:'"); echo "Using SASS version " . $sassversion . "\n"; echo "Compiling SASS/SCSS resources...\n\n";
/** * Execute the controller and method this page request points to. */ public function execute() { \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Starting PageRequest->execute()'); if($this->isCacheable()){ $uakey = \Core\UserAgent::Construct()->getPseudoIdentifier(); $urlkey = $this->host . $this->uri; $expires = $this->getPageModel()->get('expires'); $key = 'page-cache-' . md5($urlkey . '-' . $uakey); $cached = \Core\Cache::Get($key, $expires); if($cached && $cached instanceof View){ $this->_pageview = $cached; $this->_cached = true; return; } } // Anything that needs to fire off *before* the page is rendered. // This includes widgets, script addons, and anything else that needs a CurrentPage. HookHandler::DispatchHook('/core/page/preexecute'); // Load the underlying controller. $pagedat = $this->splitParts(); /** @var View $view The valid view object for this page */ $view = $this->getView(); // The controller must exist first! // (note, the SplitParts logic already takes care of the "Is this a valid controller" logic) if (!(isset($pagedat['controller']) && $pagedat['controller'])) { $view->error = View::ERROR_NOTFOUND; return; } $component = Core::GetComponentByController($pagedat['controller']); ////////////////////////////////////////////////////////////////////////////// /// In this block of logic, either the page is executed and a view returned, /// or a view is generated with an error. ////////////////////////////////////////////////////////////////////////////// if (!$component) { // Not found $view->error = View::ERROR_NOTFOUND; return; } elseif(!is_a($component, 'Component_2_1')) { $view->error = View::ERROR_NOTFOUND; return; } // Any method that starts with a "_" is an internal-only method! if ($pagedat['method']{0} == '_') { $view->error = View::ERROR_NOTFOUND; return; } // It also must be a part of the class... obviously if (!method_exists($pagedat['controller'], $pagedat['method'])) { $view->error = View::ERROR_NOTFOUND; return; } /** @var $controller Controller_2_1 This will be a Controller object. */ $controller = Controller_2_1::Factory($pagedat['controller']); $view->baseurl = $this->getBaseURL(); $controller->setView($view); // Make sure that the controller can access this object. $controller->setPageRequest($this); // The main page object. $page = $this->getPageModel(); // Check the access string first, (if there is one) if ($controller->accessstring !== null) { // Update the page's access string, (just in case it's saved at the end of execution) $page->set('access', $controller->accessstring); // And if the user doesn't have access to it... if (!\Core\user()->checkAccess($controller->accessstring)) { $view->error = View::ERROR_ACCESSDENIED; return; } } if($page->get('password_protected')) { if(\Core\Session::Get('page-password-protected/' . $page->get('baseurl')) !== $page->get('password_protected')){ $view->templatename = '/pages/page/passwordprotected.tpl'; $form = new Form(); $form->set('callsmethod', 'PageRequest::PasswordProtectHandler'); $form->addElement( 'system', [ 'name' => 'page', 'value' => $page ] ); $form->addElement( 'password', [ 'name' => 'passinput', 'title' => 'Password', 'required' => 'required', 'maxlength' => 128 ] ); $form->addElement( 'submit', [ 'value' => 'Submit' ] ); $view->assign('form', $form); return; } } // If the parent Controller object has a method named $pagedat['method'], assume it's a security error! // This is because if the parent Controller object has a method, it's most likely a utility method // that shouldn't be called from the public web! foreach(get_class_methods('Controller_2_1') as $parentmethod){ $parentmethod = strtolower($parentmethod); if($parentmethod == $pagedat['method']){ $view->error = View::ERROR_BADREQUEST; return; } } // Additional security logic for existing pages in multi-site mode. // If this exact URL is registered to another site, then // don't allow this site to display it. if(!$page->exists() && Core::IsComponentAvailable('multisite') && MultiSiteHelper::IsEnabled()){ $site = MultiSiteHelper::GetCurrentSiteID(); $anypage = PageModel::Find(['baseurl = ' . $page->get('baseurl')], 1); if($anypage){ if($anypage->get('site') == -1){ // If this is a global page.... that's ok. // Just remap the page variable to this one! $page = $anypage; } elseif($anypage->get('site') == $site){ // Strange... it should have located this page... // Anyway, it's allowed, the site matches up. $page = $anypage; } else{ \Core\redirect($anypage->getResolvedURL()); } } } $return = call_user_func(array($controller, $pagedat['method'])); if (is_int($return)) { // A generic error code was returned. Create a View with that code and return that instead. $view->error = $return; //return; } elseif(is_a($return, 'View') && $return != $view){ // The controller method changed the view, (which is allowed), // but this needs to be remapped to this object so render knows about it. $this->_pageview = $view = $return; } elseif ($return === null) { // Hopefully it's setup! $return = $controller->getView(); if($return != $view){ $this->_pageview = $view = $return; } } elseif(!is_a($return, 'View')){ if(DEVELOPMENT_MODE){ var_dump('Controller method returned', $return); die('Sorry, but this controller did not return a valid object. Please ensure that your method returns either an integer, null, or a View object!'); } else{ $view->error = View::ERROR_SERVERERROR; return; } } // No else needed, else it's a valid object. // You may be asking why $view is one object, but $return is the return from page execution. // GREAT QUESTION, The $view is the original view object created from the page request. That is passed into // the controller and exposed via $this->getView(). The return can be a view, int, or other status indicator. // However since the controller can return a different view, that view should be used instead! ///** @var $return View */ // Allow the controller to assign controls via a shortcut function. if($view->error == View::ERROR_NOERROR){ $controls = $controller->getControls(); // This method may do absolutely nothing, add the controls to the view itself, or return an array of them. if(is_array($controls)){ foreach($controls as $control){ $view->addControl($control); } } } // For some of the options, there may be some that can be used for a fuzzy page, ie: a page's non-fuzzy template, // title, or meta information. if($view->error == View::ERROR_NOERROR){ if ($page->exists()) { $defaultpage = $page; } else { $defaultpage = null; $url = $view->baseurl; while ($url != '') { $url = substr($url, 0, strrpos($url, '/')); $p = PageModel::Find(array('baseurl' => $url, 'fuzzy' => 1), 1); if ($p === null) continue; if ($p->exists()) { $defaultpage = $p; break; } } if ($defaultpage === null) { // Fine.... $defaultpage = $page; } } $defaultmetas = $defaultpage->getLink('PageMeta'); // Make a list of the existing ones so I know which ones not to overwrite! // Just the key will suffice quite nicely. $currentmetas = array(); foreach($view->meta as $k => $meta){ $currentmetas[] = $k; } // Load some of the page information into the view now! foreach($defaultmetas as $meta){ /** @var $meta PageMetaModel */ $key = $meta->get('meta_key'); $viewmeta = $meta->getViewMetaObject(); // again, allow the executed controller have the final say on meta information. if ($meta->get('meta_value_title') && !in_array($key, $currentmetas)) { $view->meta[$key] = $viewmeta; } } // Since the controller already ran, do not overwrite the title. if ($view->title === null){ $view->title = $defaultpage->get('title'); } // Tracker to see if this page, (or a parent's page), is an admin-level page. // This is required because "admin" pages may have a different skin and should always have the dashboard as the top-level breadcrumb. /** @var boolean $isadmin */ $isadmin = ($page->get('admin') == '1'); $parents = array(); $parenttree = $page->getParentTree(); foreach ($parenttree as $parent) { /** @var PageModel $parent */ $parents[] = array( 'title' => $parent->get('title'), 'link' => $parent->getResolvedURL() ); // Since I'm here, check if this page is an admin page. if($parent->get('admin')){ $isadmin = true; } } $view->breadcrumbs = array_merge($parents, $view->breadcrumbs); if($isadmin && $view->baseurl != '/admin'){ // Make sure that admin is the top breadcrumb. // This block doesn't need to apply for the actual admin page itself, as that doesn't need its own breadcrumb :/ $adminlink = \Core\resolve_link('/admin'); if(!isset($view->breadcrumbs[0])){ // Nothing is even set! $view->breadcrumbs[] = ['title' => 'Administration', 'link' => $adminlink]; } elseif($view->breadcrumbs[0]['link'] != $adminlink){ // It's set, but not to admin. $view->breadcrumbs = array_merge([['title' => 'Administration', 'link' => $adminlink]], $view->breadcrumbs); } } } else{ $defaultpage = null; $isadmin = false; } if( $view->mode == View::MODE_PAGEORAJAX && $this->isAjax() && $view->jsondata !== null && $view->templatename === null ){ // Allow the content type to be overridden for ajax pages that have JSON data embedded in them. $view->contenttype = View::CTYPE_JSON; } if($view->mode == View::MODE_NOOUTPUT){ $view->mastertemplate = false; $view->templatename = null; } elseif( $view->error == View::ERROR_NOERROR && $view->contenttype == View::CTYPE_HTML && $view->templatename === null ){ // Try to guess the templatename if it wasn't set. // This $cnameshort = (strpos($pagedat['controller'], 'Controller') == strlen($pagedat['controller']) - 10) ? substr($pagedat['controller'], 0, -10) : $pagedat['controller']; $view->templatename = strtolower('/pages/' . $cnameshort . '/' . $pagedat['method'] . '.tpl'); } elseif( $view->error == View::ERROR_NOERROR && $view->contenttype == View::CTYPE_XML && $view->templatename === null ){ $cnameshort = (strpos($pagedat['controller'], 'Controller') == strlen($pagedat['controller']) - 10) ? substr($pagedat['controller'], 0, -10) : $pagedat['controller']; $view->templatename = Template::ResolveFile(strtolower('pages/' . $cnameshort . '/' . $pagedat['method'] . '.xml.tpl')); } // In addition to the autogeneration, also support the page_template from the datastore. if($defaultpage && $defaultpage->get('page_template')){ // Switch the template over to that custom one. // Some legacy data will have the fully resolved path for this template. // This has been switched to just the basename of the custom template, // but legacy data be legacy, 'yo. 0.o $base = substr($view->templatename, 0, -4); $override = $defaultpage->get('page_template'); if($base && strpos($override, $base) === 0){ $view->templatename = $override; } elseif($base){ $view->templatename = $base . '/' . $override; } } // Guess which theme skin (mastertemplate) should be used if one wasn't specified. if($view->mastertemplate == 'admin'){ // If the master template is set explictly to be the admin skin, then transpose that to the set admin skin. // This is useful for the pages that may not be under the "/admin" umbrella, but still rendered with the admin UI. $view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template'); } elseif($view->mastertemplate){ // No change needed, just skip the below cases. } elseif($view->mastertemplate === false){ // If the master template is explictly set to false, the page wanted no master template! } elseif($isadmin){ // This page doesn't have a master template set, but it or a parent is set as an admin-level page. $view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template'); } elseif ($defaultpage && $defaultpage->get('theme_template')) { // Master template set in the database? $view->mastertemplate = $defaultpage->get('theme_template'); } elseif($defaultpage && $defaultpage->exists() && $defaultpage->get('admin')){ // Or an admin level page? $view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template'); } elseif(sizeof($view->breadcrumbs) && $view->breadcrumbs[0]['title'] == 'Administration'){ // Whatever, close e-damn-nough! // This happens for pages that don't actually exist, like "edit".... $view->mastertemplate = ConfigHandler::Get('/theme/default_admin_template'); } else{ $view->mastertemplate = ConfigHandler::Get('/theme/default_template'); } // First of all, if the current theme is not available, reset back to the first theme available! if(!($theme = ThemeHandler::GetTheme())){ /** @var \Theme\Theme $theme */ $theme = ThemeHandler::GetTheme('base-v2'); $view->mastertemplate = 'basic.tpl'; \Core\set_message('t:MESSAGE_ERROR_INVALID_THEME_SELECTED'); } // Make sure the selected mastertemplate actually exists! if($view->mastertemplate !== false){ $themeskins = $theme->getSkins(); $mastertplgood = false; foreach($themeskins as $skin){ if($skin['file'] == $view->mastertemplate){ // It's located! $mastertplgood =true; break; } } // A few special cases. if($view->mastertemplate == 'blank.tpl'){ // This is acceptable as a default one. $mastertplgood =true; } if(!$mastertplgood){ // Just use the first one instead! trigger_error('Invalid skin [' . $view->mastertemplate . '] selected for this page, skin is not located within the selected theme! Using first available instead.', E_USER_NOTICE); $view->mastertemplate = $themeskins[0]['file']; } } // Handle some of the new automatic meta data associated with Pages and the resulting View. if(\ConfigHandler::Get('/core/page/indexable') == 'deny'){ // Administratively set to noindex on all pages. $view->addMetaName('robots', 'noindex'); } elseif(!$page->get('indexable')){ // Bots have no business indexing user-action pages. $view->addMetaName('robots', 'noindex'); } if(!isset($view->meta['title'])){ $view->meta['title'] = $page->getSEOTitle(); } HookHandler::DispatchHook('/core/page/postexecute'); \Core\Utilities\Profiler\Profiler::GetDefaultProfiler()->record('Completed PageRequest->execute()'); }