/**
  * 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);
 }