From b5f94df3d6b3ddd84a158fcbf903938f23824fe8 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Thu, 1 May 2025 13:35:10 -0400 Subject: [PATCH] Updates to AdminThemeUikit in preparation for updated design --- wire/core/AdminThemeFramework.php | 14 ++- .../AdminThemeUikit/AdminThemeUikit.module | 113 +++++++++++------- .../AdminTheme/AdminThemeUikit/_main.php | 7 +- .../AdminTheme/AdminThemeUikit/config.php | 44 ++++--- .../AdminThemeUikit/themes/README.txt | 2 + 5 files changed, 116 insertions(+), 64 deletions(-) create mode 100644 wire/modules/AdminTheme/AdminThemeUikit/themes/README.txt diff --git a/wire/core/AdminThemeFramework.php b/wire/core/AdminThemeFramework.php index 3d27b7fe..80aef809 100644 --- a/wire/core/AdminThemeFramework.php +++ b/wire/core/AdminThemeFramework.php @@ -543,7 +543,19 @@ abstract class AdminThemeFramework extends AdminTheme { * * This is hookable so that something else could add stuff to it. * See the method body for details on format used. - * + * + * Supported properties/attributes as of 3.0.248: + * + * - url (href) + * - title (label text) + * - target (html attr) + * - icon (name of icon) + * - permission (required permission) + * - id (html attr) + * - class (html attr) + * - onclick (html attr) + * - data-* (html attr) + * * @return array * */ diff --git a/wire/modules/AdminTheme/AdminThemeUikit/AdminThemeUikit.module b/wire/modules/AdminTheme/AdminThemeUikit/AdminThemeUikit.module index 6ac2e4d3..63831b81 100644 --- a/wire/modules/AdminTheme/AdminThemeUikit/AdminThemeUikit.module +++ b/wire/modules/AdminTheme/AdminThemeUikit/AdminThemeUikit.module @@ -35,7 +35,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl public static function getModuleInfo() { return array( 'title' => 'Uikit', - 'version' => 34, + 'version' => 35, 'summary' => 'Uikit v3 admin theme', 'autoload' => 'template=admin', ); @@ -106,7 +106,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl $this->set('ukGrid', false); $this->set('configPhpHash', ''); $this->set('cssVersion', 0); - // $this->set('themeName', ''); // @todo + $this->set('themeName', ''); // @todo default $this->set('themeInfos', array('z' => 'z')); // z=sleeping $this->setClasses(array( 'input' => 'uk-input', @@ -139,14 +139,21 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl // if this is not the current admin theme, exit now so no hooks are attached if(!$this->isCurrent()) return; - /** @var Page $page */ - $page = $this->wire('page'); - /** @var Modules $modules */ - $modules = $this->wire('modules'); - /** @var Modules $modules */ - $session = $this->wire('session'); - - $sidenav = strpos($this->layout, 'sidenav') === 0; + $page = $this->wire()->page; + $pages = $this->wire()->pages; + $modules = $this->wire()->modules; + $session = $this->wire()->session; + $config = $this->wire()->config; + $input = $this->wire()->input; + + $themeName = $this->themeName; + + if($themeName) { + $sidenav = false; + $this->layout = ''; + } else { + $sidenav = strpos($this->layout, 'sidenav') === 0; + } // disable sidebar layout if SystemNotifications is active if($sidenav && $modules->isInstalled('SystemNotifications')) { @@ -158,7 +165,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl } } - if(!$page || $page->template != 'admin') { + if(!$page || $page->template->name !== 'admin') { // front-end if($sidenav) { // ensure that page edit links on front-end load the sidenav-init @@ -184,6 +191,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl } $session->removeFor('Page', 'appendEditUrl'); + /** @var JqueryUI $jqueryUI */ $jqueryUI = $modules->get('JqueryUI'); $jqueryUI->use('panel'); @@ -200,13 +208,22 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl $this->addHookAfter('ProcessLogin::afterLoginURL', $this, 'hookAfterLoginURL'); if(strpos($this->layout, 'sidenav-tree') === 0) { // page-edit breadcrumbs go to page editor when page tree is always in sidebar - $this->wire('config')->pageEdit('editCrumbs', true); + $config->pageEdit('editCrumbs', true); } } // add cache clearing hooks - $this->wire('pages')->addHookAfter('saved', $this, 'hookClearCaches'); + $pages->addHookAfter('saved', $this, 'hookClearCaches'); $modules->addHookAfter('refresh', $this, 'hookClearCaches'); + + if($themeName) { + $themeInfo = $this->getThemeInfo($themeName); + $user = $this->wire()->user; + if($themeInfo && $themeInfo['path']) { + $adminTheme = $this; + include($themeInfo['path'] . 'init.php'); + } + } } /** @@ -551,19 +568,15 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl */ public function hookClearCaches(HookEvent $event) { - /** @var Page|User|null $page */ - $page = $event->arguments(0); - /** @var array $changes */ - $changes = $event->arguments(1); - /** @var User $user */ - $user = $this->wire('user'); + $page = $event->arguments(0); /** @var Page|User|null $page */ + $changes = $event->arguments(1); /** @var array $changes */ + $user = $this->wire()->user; if($page !== null && !($page instanceof Page)) return; if(!is_array($changes)) $changes = array(); - if($page === null || $page->template == 'admin' || ($page->id === $user->id && in_array('language', $changes))) { - /** @var Session $session */ - $session = $this->wire('session'); + if($page === null || $page->template->name === 'admin' || ($page->id === $user->id && in_array('language', $changes))) { + $session = $this->wire()->session; $session->removeFor($this, 'prnav'); $session->removeFor($this, 'sidenav'); $session->message("Cleared the admin theme navigation cache (primary nav)", Notice::debug); @@ -573,6 +586,8 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl /** * Hook to ProcessLogin::afterLoginURL() * + * Used by sidenav layouts only + * * @param HookEvent $event * */ @@ -599,7 +614,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl public function ___renderBreadcrumbs() { if(!$this->isLoggedIn || $this->isModal) return ''; - $process = $this->wire('page')->process; + $process = $this->wire()->page->process; if($process == 'ProcessPageList') return ''; $breadcrumbs = $this->wire('breadcrumbs'); $out = ''; @@ -610,10 +625,12 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl if(strpos($this->layout, 'sidenav') === false) { $out = "
  • " . $this->renderQuickTreeLink() . "
  • "; } + + $sanitizer = $this->wire()->sanitizer; foreach($breadcrumbs as $breadcrumb) { $title = $breadcrumb->get('titleMarkup'); - if(!$title) $title = $this->wire('sanitizer')->entities1($this->_($breadcrumb->title)); + if(!$title) $title = $sanitizer->entities1($this->_($breadcrumb->title)); $out .= "
  • $title
  • "; } @@ -729,6 +746,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl * */ protected function renderPrimaryNavItemChildren(array $items) { + $sanitizer = $this->wire()->sanitizer; $out = ''; foreach($items as $item) { @@ -743,7 +761,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl ""; } else if(!empty($item['navJSON'])) { - $item['navJSON'] = $this->wire('sanitizer')->entities($item['navJSON']); + $item['navJSON'] = $sanitizer->entities($item['navJSON']); $out .= "wire('session')->getFor($this, 'prnav'); + $session = $this->wire()->session; + + $cache = self::dev ? '' : $session->getFor($this, 'prnav'); if($cache) { $this->markCurrentNavItems($cache); return $cache; @@ -781,7 +801,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl $out .= $this->renderPrimaryNavItem($item); } - if(!self::dev) $this->wire('session')->setFor($this, 'prnav', $out); + if(!self::dev) $session->setFor($this, 'prnav', $out); $this->markCurrentNavItems($out); return $out; @@ -797,13 +817,15 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl * */ public function renderSidebarNavItems() { + + $session = $this->wire()->session; // see if we can get it from the cache - $out = self::dev ? '' : $this->wire('session')->getFor($this, 'sidenav'); + $out = self::dev ? '' : $session->getFor($this, 'sidenav'); if(empty($out)) { $out = $this->renderSidebarNavCache(); - $this->wire('session')->setFor($this, 'sidenav', $out); + $session->setFor($this, 'sidenav', $out); } $out = str_replace('', $this->renderUserNavLabel(), $out); @@ -820,6 +842,8 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl */ protected function renderSidebarNavCache() { + $sanitizer = $this->wire()->sanitizer; + $out = ''; $items = $this->getPrimaryNavArray(); $ulAttrs = "class='uk-nav-sub uk-nav-default uk-nav-parent-icon' data-uk-nav='animation: false; multiple: true;'"; @@ -844,7 +868,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl $childNavList . ""; } else if($child['navJSON']) { - $child['navJSON'] = $this->wire('sanitizer')->entities($child['navJSON']); + $child['navJSON'] = $sanitizer->entities($child['navJSON']); $childClass .= ' uk-parent'; $childAttr = " class='pw-has-items pw-has-ajax-items' data-json='$child[navJSON]'"; $childNav = ""; @@ -889,7 +913,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl * */ protected function markCurrentNavItems(&$out) { - $page = $this->wire('page'); + $page = $this->wire()->page; foreach($page->parents()->and($page) as $p) { $out = str_replace("page-$p-", "page-$p- uk-active", $out); } @@ -902,8 +926,9 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl * */ public function renderUserNavLabel() { - /** @var User $user */ - $user = $this->wire('user'); + $sanitizer = $this->wire()->sanitizer; + $fields = $this->wire()->fields; + $user = $this->wire()->user; $userLabel = $this->get('userLabel'); $userAvatar = $this->get('userAvatar'); $defaultIcon = 'user-circle'; @@ -918,7 +943,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl $userLabel = $user->getText($userLabel, true, true); } } else { - $userLabel = $this->wire('sanitizer')->entities($userLabel); + $userLabel = $sanitizer->entities($userLabel); } if($userAvatar) { @@ -934,9 +959,9 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl $userAvatar = $this->renderNavIcon("$icon fa-lg"); } else if(strpos($userAvatar, ':')) { list($fieldID, $fieldName) = explode(':', $userAvatar); - $field = $this->wire('fields')->get($fieldName); + $field = $fields->get($fieldName); if(!$field || !$field->type instanceof FieldtypeImage) { - $field = $this->wire('fields')->get((int) $fieldID); + $field = $fields->get((int) $fieldID); } if($field && $field->type instanceof FieldtypeImage) { $value = $user->get($field->name); @@ -966,14 +991,22 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl */ public function renderUserNavItems() { + $sanitizer = $this->wire()->sanitizer; $items = $this->getUserNavArray(); + $allowAttrs = [ 'href', 'target', 'class', 'id' ]; $out = ''; foreach($items as $item) { - $label = $this->wire('sanitizer')->entities($item['title']); + if(isset($item['url'])) $item['href'] = $item['url']; + $label = $sanitizer->entities($item['title']); $icon = isset($item['icon']) ? $this->renderNavIcon($item['icon']) : ' '; - $target = isset($item['target']) ? " target='$item[target]'" : ''; - $out .= "
  • $icon$label
  • "; + $attrs = ''; + foreach($item as $name => $value) { + if(in_array($name, $allowAttrs) || strpos($name, 'data-') === 0 || strpos($name, 'on') === 0) { + $attrs .= " $name='" . $sanitizer->entities($value) . "'"; + } + } + $out .= "
  • $icon$label
  • "; } return $out; @@ -990,7 +1023,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl */ public function renderQuickTreeLink($icon = 'tree', $text = '') { $tree = $this->_('Tree'); - $url = $this->wire('urls')->admin . 'page/'; + $url = $this->wire()->urls->admin . 'page/'; return "" . $this->renderNavIcon($icon) . $text . diff --git a/wire/modules/AdminTheme/AdminThemeUikit/_main.php b/wire/modules/AdminTheme/AdminThemeUikit/_main.php index 65788952..88a812a2 100644 --- a/wire/modules/AdminTheme/AdminThemeUikit/_main.php +++ b/wire/modules/AdminTheme/AdminThemeUikit/_main.php @@ -22,10 +22,9 @@ if(!defined("PROCESSWIRE")) die(); /** @var string $layout */ /** @var Process $process */ -$themeInfo = $adminTheme->getThemeInfo(); -if(!empty($themeInfo)) { - $themePhpFile = "$themeInfo[path]$themeInfo[name].php"; - if(file_exists($themePhpFile)) include($themePhpFile); +if($adminTheme->themeName && $adminTheme->themeName != 'original') { + $themeInfo = $adminTheme->getThemeInfo(); + if(!empty($themeInfo)) include("$themeInfo[path]ready.php"); } $adminTheme->renderExtraMarkup('x'); // forces it to cache diff --git a/wire/modules/AdminTheme/AdminThemeUikit/config.php b/wire/modules/AdminTheme/AdminThemeUikit/config.php index d405f647..cab2d18d 100644 --- a/wire/modules/AdminTheme/AdminThemeUikit/config.php +++ b/wire/modules/AdminTheme/AdminThemeUikit/config.php @@ -37,13 +37,12 @@ class AdminThemeUikitConfigHelper extends Wire { $experimentalLabel = $this->_('(EXPERIMENTAL)'); $exampleLabel = $this->_('example'); - /** @var modules $modules */ - $modules = $this->wire('modules'); + $modules = $this->wire()->modules; + $session = $this->wire()->session; + $config = $this->wire()->config; - /** @var Session $session */ - $session = $this->wire('session'); $layout = $adminTheme->layout; - $userTemplateURL = $this->wire('config')->urls->admin . 'setup/template/edit?id=3'; + $userTemplateURL = $config->urls->admin . 'setup/template/edit?id=3'; $adminTheme->getThemeInfo(); // init $themeInfos = $adminTheme->themeInfos; @@ -52,11 +51,13 @@ class AdminThemeUikitConfigHelper extends Wire { $configFiles = []; $f = $inputfields->InputfieldRadios; $f->attr('id+name', 'themeName'); - $f->label = $this->_('Theme style'); + $f->label = $this->_('Theme name'); + $f->notes = + $this->_('After changing the theme, please submit/save before configuring it.') . ' ' . + $this->_('When using `admin.less` customization, you should use the “Original” theme.'); $f->icon = 'photo'; - // $default = '[span.detail] ' . __('(default)') . ' [/span]'; foreach($themeInfos as $name => $info) { - $f->addOption($name, ucfirst($name)); + $f->addOption($name, ucfirst($name), [ 'data-url' => $info['url'] ]); $configFile = $info['path'] . 'config.php'; if(is_file($configFile)) $configFiles[$name] = $configFile; } @@ -161,16 +162,18 @@ class AdminThemeUikitConfigHelper extends Wire { $f->optionColumns = 1; $fieldset->add($f); + /** @var InputfieldFieldset $fieldset */ $fieldset = $modules->get('InputfieldFieldset'); $fieldset->label = $this->_('Layout + interface'); $fieldset->icon = 'newspaper-o'; $fieldset->collapsed = Inputfield::collapsedYes; $fieldset->set('themeOffset', true); $inputfields->add($fieldset); - + /** @var InputfieldRadios $f */ $f = $modules->get('InputfieldRadios'); $f->attr('id+name', 'layout'); + if(empty($layout)) $f->showIf = "themeName=''"; $f->label = $this->_('Layout type'); $f->addOption('', $this->_('Traditional with masthead navigation') . ' [span.detail] ' . $recommendedLabel . ' [/span]'); @@ -421,14 +424,13 @@ class AdminThemeUikitConfigHelper extends Wire { */ public function configInputfield(Inputfield $inputfield, InputfieldWrapper $inputfields) { - /** @var Inputfield $inputfield */ if($inputfield instanceof InputfieldWrapper) return; if(!$inputfield->hasFieldtype || !$inputfield->hasField) return; $field = $inputfield->hasField; - /** @var Modules $modules */ - $modules = $this->wire('modules'); + $modules = $this->wire()->modules; + $config = $this->wire()->config; $autoLabel = $this->_('Auto'); $noneLabel = $this->_('None'); @@ -575,6 +577,8 @@ class AdminThemeUikitConfigHelper extends Wire { } else { $exampleType = 'InputfieldMarkup'; } + + /** @var Inputfield $f */ $f = $modules->get($exampleType); $f->attr('id+name', '_adminThemeExample'); $f->label = $this->_('Example'); @@ -594,7 +598,8 @@ class AdminThemeUikitConfigHelper extends Wire { } $f->icon = 'snowflake-o'; $fieldset->add($f); - + + /** @var InputfieldMarkup $f */ $f = $modules->get('InputfieldMarkup'); $f->attr('id+name', '_adminThemeExample2'); $f->label = $this->_('Another field'); @@ -606,8 +611,6 @@ class AdminThemeUikitConfigHelper extends Wire { $this->_('Open the “%s” field above for a live example of column width.'), $fieldset->label ). ' ' . $f->notes; - /** @var Config $config */ - $config = $this->wire('config'); $config->scripts->add($config->urls($this->adminTheme) . 'config-field.js'); } @@ -622,15 +625,14 @@ class AdminThemeUikitConfigHelper extends Wire { $form = $inputfields->getForm(); if($form) { $form->action .= '&tests=1'; - $this->wire('session')->addHookBefore('redirect', function(HookEvent $event) { + $this->wire()->session->addHookBefore('redirect', function(HookEvent $event) { $url = $event->arguments(0); $url .= '&tests=1'; $event->arguments(0, $url); }); } - /** @var Modules $modules */ - $modules = $this->wire('modules'); + $modules = $this->wire()->modules; // TEST 1 ---------------------------------- /** @var InputfieldFieldset $fieldset */ @@ -725,6 +727,7 @@ class AdminThemeUikitConfigHelper extends Wire { ); foreach($columns as $n => $col) { + /** @var InputfieldText $f */ $f = $modules->get('InputfieldText'); $f->attr('name', "_test_text$n"); $f->label = $col['label']; @@ -738,11 +741,14 @@ class AdminThemeUikitConfigHelper extends Wire { } // TEST 3 ----------------------------------------------- - + + + /** @var InputfieldFieldset $fieldset */ $fieldset = $modules->get('InputfieldFieldset'); $fieldset->label = '33% widths tests w/show-if'; $inputfields->add($fieldset); + /** @var InputfieldText $f */ $f = $modules->get('InputfieldText'); $f->attr('name', '_t1'); $f->label = 'Col 1/3'; diff --git a/wire/modules/AdminTheme/AdminThemeUikit/themes/README.txt b/wire/modules/AdminTheme/AdminThemeUikit/themes/README.txt new file mode 100644 index 00000000..8268f28e --- /dev/null +++ b/wire/modules/AdminTheme/AdminThemeUikit/themes/README.txt @@ -0,0 +1,2 @@ +This is a placeholder file that can be deleted +once there is a theme directory within this. \ No newline at end of file