/** * Page to display the currently installed themes and shortcuts to various operations therein. */ public function index() { $view = $this->getView(); $selected = ConfigHandler::Get('/theme/selected'); $themes = ThemeHandler::GetAllThemes(); $current = ThemeHandler::GetTheme($selected); // Set to true if multisite is enabled AND the page is currently on a child site. $multisite = Core::IsLibraryAvailable('multisite') && MultiSiteHelper::IsEnabled() && MultiSiteHelper::GetCurrentSiteID() != 0; $configDefault = ConfigHandler::GetConfig('/theme/default_template'); $configSelected = ConfigHandler::GetConfig('/theme/selected'); $configEmailDefault = ConfigHandler::GetConfig('/theme/default_email_template'); // Only allow changing the theme if it's on the root site OR both config options are overrideable. $themeSelectionEnabled = !$multisite || $configDefault->get('overrideable') && $configSelected->get('overrideable'); $emailSelectionEnabled = !$multisite || $configEmailDefault->get('overrideable'); $configOptions = $current->getConfigs(); if (!sizeof($configOptions)) { $optionForm = null; } else { $optionForm = new Form(); $optionForm->set('callsmethod', 'AdminController::_ConfigSubmit'); foreach ($configOptions as $c) { /** @var $c ConfigModel */ if ($multisite) { // Only pull the config options that are enabled for this specific site. if ($c->get('overrideable')) { $optionForm->addElement($c->getAsFormElement()); } } else { // Sites that either // do NOT have multisite installed // nor have multisite enabled // or on the root site, get all options. $optionForm->addElement($c->getAsFormElement()); } } if (sizeof($optionForm->getElements()) > 0) { // There is at least one element in the option forms! $optionForm->addElement('submit', ['value' => 'Save Configurable Options']); } else { // Reset the form back to null so that the section doesn't display. $optionForm = null; } } // The source objects to look for assets in. // Set initially to all the installed components. $assetsources = Core::GetComponents(); // And add on the current theme. $assetsources[] = $current; // Load in all asset files available from the installed components and current theme. // these are assembled into a virtual directory listing. $assets = array(); // Give me the current theme! foreach ($assetsources as $source) { /** @var Component_2_1 $source */ $dir = $source->getAssetDir(); if (!$dir) { continue; } $dirlen = strlen($dir); $name = $source->getName(); $dh = \Core\Filestore\Factory::Directory($dir); $ls = $dh->ls(null, true); foreach ($ls as $obj) { // Skip directories. if (!$obj instanceof \Core\Filestore\File) { continue; } /** @var $obj \Core\Filestore\File */ $file = 'assets/' . 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. $newobj = \Core\Filestore\Factory::File($file); $assets[$file] = array('file' => $file, 'obj' => $newobj, 'component' => $name); } } // Now that the asset files have been loaded into a flat array, I need to convert that to the properly nested version. ksort($assets); $nestedassets = array(); foreach ($assets as $k => $obj) { $parts = explode('/', $k); $lastkey = sizeof($parts) - 1; $thistarget =& $nestedassets; foreach ($parts as $i => $bit) { if ($i == $lastkey) { $thistarget[$bit] = $obj; } else { if (!isset($thistarget[$bit])) { $thistarget[$bit] = []; } $thistarget =& $thistarget[$bit]; } } } // Get the templates throughout the site. These can include pages, emails, form elements, etc. $components = Core::GetComponents(); $templates = array(); foreach ($components as $c) { /** @var $c Component_2_1 */ $dir = $c->getViewSearchDir(); if (!$dir) { continue; } $dirlen = strlen($dir); $component = $c->getName(); $dh = \Core\Filestore\Factory::Directory($dir); //$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); $resolved = Core\Templates\Template::ResolveFile($file); $newobj = \Core\Filestore\Factory::File($resolved); $templates[$file] = array('file' => $file, 'resolved' => $resolved, 'obj' => $newobj, 'haswidgets' => $tpl->hasWidgetAreas(), 'component' => $component, 'has_stylesheets' => $tpl->hasOptionalStylesheets()); } } // Now that the template files have been loaded into a flat array, I need to convert that to the properly nested version. ksort($templates); $nestedtemplates = array(); foreach ($templates as $k => $obj) { $parts = explode('/', $k); $lastkey = sizeof($parts) - 1; $thistarget =& $nestedtemplates; foreach ($parts as $i => $bit) { if ($i == $lastkey) { $thistarget[$bit] = $obj; } else { if (!isset($thistarget[$bit])) { $thistarget[$bit] = []; } $thistarget =& $thistarget[$bit]; } } } $siteskinform = new Form(); $siteskinform->set('callsmethod', 'ThemeController::SaveSiteSkins'); $opts = ['' => '-- Public Default --']; foreach ($current->getSkins() as $skin) { $opts[$skin['file']] = $skin['title']; } foreach (ConfigHandler::FindConfigs('/theme/siteskin/') as $k => $config) { $siteskinform->addElement('select', ['name' => 'config[' . $k . ']', 'title' => $config->get('description'), 'value' => $config->getValue(), 'options' => $opts]); } $siteskinform->addElement('submit', ['value' => t('STRING_SAVE')]); $customdest = \Core\directory('themes/custom'); $cssform = false; $cssprintform = false; if ($customdest->isWritable()) { $sets = [['file' => 'css/custom.css', 'form' => null], ['file' => 'css/custom_print.css', 'form' => null]]; foreach ($sets as $k => $set) { // Load the editor for the custom CSS file, as this is a very common thing to do! $file = $set['file']; // And try to look up and find this damn file... $srcdirs = array(); $srcdirs[] = ROOT_PDIR . 'themes/custom/assets/'; $srcdirs[] = ROOT_PDIR . 'themes/' . ConfigHandler::Get('/theme/selected') . '/assets/'; foreach (Core::GetComponents() as $c) { if ($c->getAssetDir()) { $srcdirs[] = $c->getAssetDir(); } } foreach ($srcdirs as $dir) { if (file_exists($dir . $file)) { $file = $dir . $file; break; } } $fh = \Core\Filestore\Factory::File($file); $content = $fh->getContents(); $m = new ThemeTemplateChangeModel(); $m->set('content', $content); $m->set('filename', 'assets/css/custom.css'); $form = Form::BuildFromModel($m); $form->set('callsmethod', 'ThemeController::_SaveEditorHandler'); // I need to add the file as a system element so core doesn't try to reuse the same forms on concurrent edits. //$form->addElement('system', array('name' => 'revision', 'value' => $revision)); $form->addElement('system', array('name' => 'file', 'value' => 'assets/' . $set['file'])); $form->addElement('system', array('name' => 'filetype', 'value' => 'file')); // No one uses this anyways! $form->switchElementType('model[comment]', 'hidden'); $form->getElement('model[content]')->set('id', 'custom_content_' . $k); $form->addElement('submit', array('value' => 'Save Custom CSS')); // Save it back down to the original array $sets[$k]['form'] = $form; } $cssform = $sets[0]['form']; $cssprintform = $sets[1]['form']; } $view->title = 'Theme Manager'; $view->assign('themes', $themes); $view->assign('current', $current); $view->assign('options_form', $optionForm); $view->assign('assets', $nestedassets); $view->assign('templates', $nestedtemplates); $view->assign('url_themeeditor', \Core\resolve_link('/theme/editor')); $view->assign('url_themewidgets', \Core\resolve_link('/theme/widgets')); $view->assign('url_themestylesheets', \Core\resolve_link('/theme/selectstylesheets')); $view->assign('site_skins_form', $siteskinform); $view->assign('cssform', $cssform); $view->assign('cssprintform', $cssprintform); $view->assign('multisite', $multisite); $view->assign('theme_selection_enabled', $themeSelectionEnabled); $view->assign('email_selection_enabled', $emailSelectionEnabled); }