/**
  * 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';
 }
Example #5
0
			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";
Example #6
0
	/**
	 * 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);
	}
Example #8
0
		}
		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');
		}
	}
Example #11
0
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);
Example #12
0
	/**
	 * 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);
		}
	}
Example #13
0
			'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,
		];
	}
Example #15
0
	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
				        )
			);
		}
	}
Example #16
0
}

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()');
	}