2022-03-08 15:55:41 +01:00
|
|
|
|
<?php namespace ProcessWire;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* AdminTheme Framework
|
|
|
|
|
*
|
|
|
|
|
* The methods in this class may eventually be merged to AdminTheme.php,
|
|
|
|
|
* but are isolated to this class during development.
|
|
|
|
|
*
|
|
|
|
|
* This file is licensed under the MIT license.
|
|
|
|
|
* https://processwire.com/about/license/mit/
|
|
|
|
|
*
|
2022-11-05 18:32:48 +01:00
|
|
|
|
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
|
2022-03-08 15:55:41 +01:00
|
|
|
|
* https://processwire.com
|
|
|
|
|
*
|
|
|
|
|
* @property bool $isSuperuser
|
|
|
|
|
* @property bool $isEditor
|
|
|
|
|
* @property bool $isLoggedIn
|
|
|
|
|
* @property bool|string $isModal
|
|
|
|
|
* @property bool|int $useAsLogin
|
|
|
|
|
* @method array getUserNavArray()
|
|
|
|
|
* @method array getPrimaryNavArray()
|
2022-11-05 18:32:48 +01:00
|
|
|
|
* @method string renderFile($basename, array $vars = [])
|
2022-03-08 15:55:41 +01:00
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
abstract class AdminThemeFramework extends AdminTheme {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Is there currently a logged in user?
|
|
|
|
|
*
|
|
|
|
|
* @var bool
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected $isLoggedIn = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Is user logged in with page-edit permission?
|
|
|
|
|
*
|
|
|
|
|
* @var bool
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected $isEditor = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Is current user a superuser?
|
|
|
|
|
*
|
|
|
|
|
* @var bool
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected $isSuperuser = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Is the current request a modal request?
|
|
|
|
|
*
|
|
|
|
|
* @var bool|string Either false, true, or "inline"
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected $isModal = false;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @var Sanitizer
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected $sanitizer;
|
|
|
|
|
|
2022-11-05 18:32:48 +01:00
|
|
|
|
/**
|
|
|
|
|
* Custom template path when it exists, i.e. /site/templates/AdminThemeUikit/
|
|
|
|
|
*
|
|
|
|
|
* @var string|null Null when not yet known, blank '' when it does not exist, populated when it exists
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected $customTemplatePath = null;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Default template path
|
|
|
|
|
*
|
|
|
|
|
* @var string|null
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected $defaultTemplatePath = null;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Is the renderFile() method hooked? Null when not known, bool when known
|
|
|
|
|
*
|
|
|
|
|
* @var bool|null
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected $renderFileHooked = null;
|
|
|
|
|
|
2022-03-08 15:55:41 +01:00
|
|
|
|
/**
|
|
|
|
|
* Construct
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function __construct() {
|
|
|
|
|
parent::__construct();
|
|
|
|
|
$this->set('useAsLogin', false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function wired() {
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$this->sanitizer = $this->wire()->sanitizer;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$user = $this->wire()->user;
|
|
|
|
|
$this->isLoggedIn = $user && $user->isLoggedin();
|
|
|
|
|
parent::wired();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Override get() method from WireData to support additional properties
|
|
|
|
|
*
|
|
|
|
|
* @param string $key
|
|
|
|
|
* @return bool|int|mixed|null|string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function get($key) {
|
|
|
|
|
switch($key) {
|
|
|
|
|
case 'isSuperuser': $value = $this->isSuperuser; break;
|
|
|
|
|
case 'isEditor': $value = $this->isEditor; break;
|
|
|
|
|
case 'isLoggedIn': $value = $this->isLoggedIn; break;
|
|
|
|
|
case 'isModal': $value = $this->isModal; break;
|
|
|
|
|
default: $value = parent::get($key);
|
|
|
|
|
}
|
|
|
|
|
return $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialize and attach hooks
|
|
|
|
|
*
|
|
|
|
|
* Note: descending classes should call this after API ready
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function init() {
|
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$user = $this->wire()->user;
|
|
|
|
|
$input = $this->wire()->input;
|
|
|
|
|
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if(!$this->isLoggedIn && $this->useAsLogin) $this->setCurrent();
|
|
|
|
|
parent::init();
|
|
|
|
|
|
|
|
|
|
// if this is not the current admin theme, exit now so no hooks are attached
|
|
|
|
|
if(!$this->isCurrent()) return;
|
|
|
|
|
|
|
|
|
|
$this->isSuperuser = $this->isLoggedIn && $user->isSuperuser();
|
|
|
|
|
$this->isEditor = $this->isLoggedIn && ($this->isSuperuser || $user->hasPermission('page-edit'));
|
|
|
|
|
$this->includeInitFile();
|
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$modal = $input->get('modal');
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if($modal) $this->isModal = $modal == 'inline' ? 'inline' : true;
|
|
|
|
|
|
|
|
|
|
// test notices when requested
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if($input->get('test_notices') && $this->isLoggedIn) $this->testNotices();
|
2022-03-08 15:55:41 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Include the admin theme init file
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function includeInitFile() {
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$config = $this->wire()->config;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$initFile = $this->path() . 'init.php';
|
|
|
|
|
if(file_exists($initFile)) {
|
|
|
|
|
if(strpos($initFile, $config->paths->site) === 0) {
|
|
|
|
|
// admin themes in /site/modules/ may be compiled
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$initFile = $this->wire()->files->compile($initFile);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
}
|
|
|
|
|
/** @noinspection PhpIncludeInspection */
|
|
|
|
|
include_once($initFile);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Perform a translation, based on text from shared admin file: /wire/templates-admin/default.php
|
|
|
|
|
*
|
|
|
|
|
* @param string $text
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function _($text) {
|
|
|
|
|
static $translate = null;
|
2023-03-10 19:41:40 +01:00
|
|
|
|
static $context = null;
|
|
|
|
|
if($translate === null) $translate = $this->wire()->languages !== null;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if($translate === false) return $text;
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if($context === null) $context = $this->wire()->config->paths->root . 'wire/templates-admin/default.php';
|
|
|
|
|
$value = __($text, $context);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if($value === $text) $value = parent::_($text);
|
|
|
|
|
return $value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the current page headline
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getHeadline() {
|
|
|
|
|
$headline = $this->wire('processHeadline');
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if(!$headline) $headline = $this->wire()->page->get('title|name');
|
|
|
|
|
if($headline !== 'en' && $this->wire()->languages) $headline = $this->_($headline);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
return $this->sanitizer->entities1($headline);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get navigation title for the given page, return blank if page should not be shown
|
|
|
|
|
*
|
|
|
|
|
* @param Page $p
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getPageTitle(Page $p) {
|
|
|
|
|
|
|
|
|
|
if($p->name == 'add' && $p->parent->name == 'page') {
|
|
|
|
|
|
|
|
|
|
$title = $this->getAddNewLabel();
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
$title = $this->_($p->title);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$title = $this->sanitizer->entities1($title);
|
|
|
|
|
|
|
|
|
|
return $title;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get icon used by the given page
|
|
|
|
|
*
|
|
|
|
|
* @param Page $p
|
|
|
|
|
* @return mixed|null|string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getPageIcon(Page $p) {
|
|
|
|
|
$icon = '';
|
|
|
|
|
if($p->template == 'admin') {
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$info = $this->wire()->modules->getModuleInfo($p->process);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if(!empty($info['icon'])) $icon = $info['icon'];
|
|
|
|
|
}
|
|
|
|
|
// allow for option of an admin field overriding the module icon
|
|
|
|
|
$pageIcon = $p->get('page_icon');
|
|
|
|
|
if($pageIcon) $icon = $pageIcon;
|
|
|
|
|
if(!$icon) switch($p->id) {
|
|
|
|
|
case 22: $icon = 'gears'; break; // Setup
|
|
|
|
|
case 21: $icon = 'plug'; break; // Modules
|
|
|
|
|
case 28: $icon = 'key'; break; // Access
|
|
|
|
|
}
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if(!$icon && $p->parent->id != $this->wire()->config->adminRootPageID) {
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$icon = 'file-o ui-priority-secondary';
|
|
|
|
|
}
|
|
|
|
|
return $icon;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get “Add New” button actions
|
|
|
|
|
*
|
|
|
|
|
* - Returns array of arrays, each with 'url', 'label' and 'icon' properties.
|
|
|
|
|
* - Returns empty array if Add New button should not be displayed.
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getAddNewActions() {
|
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$page = $this->wire()->page;
|
|
|
|
|
$process = $this->wire()->process;
|
|
|
|
|
$input = $this->wire()->input;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
|
|
|
|
if(!$this->isEditor) return array();
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if($page->name != 'page' || $input->urlSegment1 || $input->get('modal')) return array();
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if(strpos($process, 'ProcessPageList') !== 0) return array();
|
|
|
|
|
|
|
|
|
|
/** @var ProcessPageAdd $module */
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$module = $this->wire()->modules->getModule('ProcessPageAdd', array('noInit' => true));
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$data = $module->executeNavJSON(array('getArray' => true));
|
|
|
|
|
$actions = array();
|
|
|
|
|
|
|
|
|
|
foreach($data['list'] as $item) {
|
|
|
|
|
$item['url'] = $data['url'] . $item['url'];
|
|
|
|
|
$actions[] = $item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $actions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the translated “Add New” label that’s used in a couple spots
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getAddNewLabel() {
|
|
|
|
|
return $this->_('Add New');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the classes that will be used in the <body class=''> tag
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getBodyClass() {
|
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$page = $this->wire()->page;
|
|
|
|
|
$process = $this->wire()->process;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
|
|
|
|
$classes = array(
|
|
|
|
|
"id-{$page->id}",
|
|
|
|
|
"template-{$page->template->name}",
|
|
|
|
|
"pw-init",
|
|
|
|
|
parent::getBodyClass(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if($this->isModal) $classes[] = 'modal';
|
|
|
|
|
if($this->isModal === 'inline') $classes[] = 'modal-inline';
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if($this->wire()->input->urlSegment1) $classes[] = 'hasUrlSegments';
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if($process) $classes[] = $process->className();
|
|
|
|
|
if(!$this->isLoggedIn) $classes[] = 'pw-guest';
|
|
|
|
|
|
|
|
|
|
return implode(' ', $classes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Javascript that must be present in the document <head>
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getHeadJS() {
|
|
|
|
|
$config = $this->wire()->config;
|
|
|
|
|
return
|
|
|
|
|
"var ProcessWire = { config: " . wireEncodeJSON($config->js(), true, $config->debug) . " }; " .
|
|
|
|
|
"var config = ProcessWire.config;\n"; // legacy support
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Allow the given Page to appear in admin theme navigation?
|
|
|
|
|
*
|
|
|
|
|
* @param Page $p Page to test
|
|
|
|
|
* @param PageArray|array $children Children of page, if applicable (optional)
|
|
|
|
|
* @param string|null $permission Specify required permission (optional)
|
|
|
|
|
* @return bool
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function allowPageInNav(Page $p, $children = array(), $permission = null) {
|
|
|
|
|
|
|
|
|
|
if($this->isSuperuser) return true;
|
|
|
|
|
|
|
|
|
|
$pageViewable = $p->viewable();
|
|
|
|
|
if(!$pageViewable) return false;
|
|
|
|
|
|
|
|
|
|
$allow = false;
|
|
|
|
|
$numChildren = count($children);
|
|
|
|
|
|
|
|
|
|
if($p->process == 'ProcessPageAdd') {
|
|
|
|
|
// ProcessPageAdd: avoid showing this menu item if there are no predefined family settings to use
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$session = $this->wire()->session;
|
|
|
|
|
$numAddable = $session->getFor('ProcessPageAdd', 'numAddable');
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if($numAddable === null) {
|
|
|
|
|
/** @var ProcessPageAdd $processPageAdd */
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$processPageAdd = $this->wire()->modules->getModule('ProcessPageAdd', array('noInit' => true));
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if($processPageAdd) {
|
|
|
|
|
$addData = $processPageAdd->executeNavJSON(array('getArray' => true));
|
|
|
|
|
$numAddable = $addData['list'];
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$session->setFor('ProcessPageAdd', 'numAddable', $numAddable);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// no addable options, so do not show the "Add New" item
|
|
|
|
|
if(!$numAddable) return false;
|
|
|
|
|
|
|
|
|
|
} else if(empty($permission)) {
|
|
|
|
|
// no permission specified
|
|
|
|
|
|
|
|
|
|
if(!$p->process) {
|
|
|
|
|
// no process module present, so we delegate to just the page viewable state if no children to check
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if(!$numChildren) return true;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
|
|
|
|
} else if($p->process == 'ProcessList') {
|
|
|
|
|
// page just serves as a list for children
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// determine permission from Process module, if present
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$moduleInfo = $this->wire()->modules->getModuleInfo($p->process);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if(!empty($moduleInfo['permission'])) $permission = $moduleInfo['permission'];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($permission) {
|
|
|
|
|
// specific permission required to determine view access
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$allow = $this->wire()->user->hasPermission($permission);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
} else if($p->parent_id == $this->wire()->config->adminRootPageID) {
|
2022-03-08 15:55:41 +01:00
|
|
|
|
// primary nav page requires that at least one child is viewable
|
|
|
|
|
foreach($children as $child) {
|
|
|
|
|
if($this->allowPageInNav($child)) {
|
|
|
|
|
$allow = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $allow;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return nav array of primary navigation
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function ___getPrimaryNavArray() {
|
|
|
|
|
|
|
|
|
|
$items = array();
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$config = $this->wire()->config;
|
|
|
|
|
$admin = $this->wire()->pages->get($config->adminRootPageID);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
|
|
|
|
foreach($admin->children("check_access=0") as $p) {
|
|
|
|
|
$item = $this->pageToNavArray($p);
|
|
|
|
|
if($item) $items[] = $item;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $items;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get navigation array from a Process module
|
|
|
|
|
*
|
|
|
|
|
* @param array|Module|string $module Module info array or Module object or string
|
|
|
|
|
* @param Page $p Page upon which the Process module is contained
|
|
|
|
|
* @return array
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function moduleToNavArray($module, Page $p) {
|
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$config = $this->wire()->config;
|
|
|
|
|
$modules = $this->wire()->modules;
|
|
|
|
|
$user = $this->wire()->user;
|
|
|
|
|
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$textdomain = str_replace($config->paths->root, '/', $modules->getModuleFile($p->process));
|
|
|
|
|
$navArray = array();
|
|
|
|
|
|
|
|
|
|
if(is_array($module)) {
|
|
|
|
|
$moduleInfo = $module;
|
|
|
|
|
} else {
|
|
|
|
|
$moduleInfo = $modules->getModuleInfo($module);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach($moduleInfo['nav'] as $navItem) {
|
|
|
|
|
|
|
|
|
|
$permission = empty($navItem['permission']) ? '' : $navItem['permission'];
|
|
|
|
|
if($permission && !$user->hasPermission($permission)) continue;
|
|
|
|
|
|
|
|
|
|
$navArray[] = array(
|
|
|
|
|
'id' => 0,
|
|
|
|
|
'parent_id' => $p->id,
|
|
|
|
|
'title' => $this->sanitizer->entities1(__($navItem['label'], $textdomain)), // translate from context of Process module
|
|
|
|
|
'name' => '',
|
|
|
|
|
'url' => $p->url . $navItem['url'],
|
|
|
|
|
'icon' => empty($navItem['icon']) ? '' : $navItem['icon'],
|
|
|
|
|
'children' => array(),
|
|
|
|
|
'navJSON' => empty($navItem['navJSON']) ? '' : $p->url . $navItem['navJSON'],
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $navArray;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get a navigation array the given Page, or null if page not allowed in nav
|
|
|
|
|
*
|
|
|
|
|
* @param Page $p
|
|
|
|
|
* @return array|null
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function pageToNavArray(Page $p) {
|
|
|
|
|
|
|
|
|
|
$children = $p->numChildren ? $p->children("check_access=0") : array();
|
|
|
|
|
|
|
|
|
|
if(!$this->allowPageInNav($p, $children)) return null;
|
|
|
|
|
|
|
|
|
|
$navArray = array(
|
|
|
|
|
'id' => $p->id,
|
|
|
|
|
'parent_id' => $p->parent_id,
|
|
|
|
|
'url' => $p->url,
|
|
|
|
|
'name' => $p->name,
|
|
|
|
|
'title' => $this->getPageTitle($p),
|
|
|
|
|
'icon' => $this->getPageIcon($p),
|
|
|
|
|
'children' => array(),
|
|
|
|
|
'navJSON' => '',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if(!count($children)) {
|
|
|
|
|
// no children available
|
|
|
|
|
if($p->template == 'admin' && $p->process) {
|
|
|
|
|
// see if process module defines its own navigation
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$moduleInfo = $this->wire()->modules->getModuleInfo($p->process);
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if(!empty($moduleInfo['nav'])) {
|
|
|
|
|
$navArray['children'] = $this->moduleToNavArray($moduleInfo, $p);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// The /page/ and /page/list/ are the same process, so just keep them on /page/ instead.
|
|
|
|
|
if(strpos($navArray['url'], '/page/list/') !== false) {
|
|
|
|
|
$navArray['url'] = str_replace('/page/list/', '/page/', $navArray['url']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $navArray;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if we reach this point, then we have a PageArray of children
|
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$modules = $this->wire()->modules;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
|
|
|
|
foreach($children as $c) {
|
|
|
|
|
|
|
|
|
|
if(!$c->process) continue;
|
|
|
|
|
$moduleInfo = $modules->getModuleInfo($c->process);
|
|
|
|
|
$permission = empty($moduleInfo['permission']) ? '' : $moduleInfo['permission'];
|
|
|
|
|
if(!$this->allowPageInNav($c, array(), $permission)) continue;
|
|
|
|
|
|
|
|
|
|
$childItem = array(
|
|
|
|
|
'id' => $c->id,
|
|
|
|
|
'parent_id' => $c->parent_id,
|
|
|
|
|
'title' => $this->getPageTitle($c),
|
|
|
|
|
'name' => $c->name,
|
|
|
|
|
'url' => $c->url,
|
|
|
|
|
'icon' => $this->getPageIcon($c),
|
|
|
|
|
'children' => array(),
|
|
|
|
|
'navJSON' => empty($moduleInfo['useNavJSON']) ? '' : $c->url . 'navJSON/',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if(!empty($moduleInfo['nav'])) {
|
|
|
|
|
$childItem['children'] = $this->moduleToNavArray($moduleInfo, $c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$navArray['children'][] = $childItem;
|
|
|
|
|
|
|
|
|
|
} // foreach
|
|
|
|
|
|
|
|
|
|
return $navArray;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get navigation items for the “user” menu
|
|
|
|
|
*
|
|
|
|
|
* This is hookable so that something else could add stuff to it.
|
|
|
|
|
* See the method body for details on format used.
|
|
|
|
|
*
|
|
|
|
|
* @return array
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function ___getUserNavArray() {
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$urls = $this->wire()->urls;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$navArray = array();
|
|
|
|
|
|
|
|
|
|
$navArray[] = array(
|
|
|
|
|
'url' => $urls->root,
|
|
|
|
|
'title' => $this->_('View site'),
|
|
|
|
|
'target' => '_top',
|
|
|
|
|
'icon' => 'eye',
|
|
|
|
|
);
|
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if($this->wire()->user->hasPermission('profile-edit')) $navArray[] = array(
|
2022-03-08 15:55:41 +01:00
|
|
|
|
'url' => $urls->admin . 'profile/',
|
|
|
|
|
'title' => $this->_('Profile'),
|
|
|
|
|
'icon' => 'user',
|
|
|
|
|
'permission' => 'profile-edit',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$navArray[] = array(
|
|
|
|
|
'url' => $urls->admin . 'login/logout/',
|
|
|
|
|
'title' => $this->_('Logout'),
|
|
|
|
|
'target' => '_top',
|
|
|
|
|
'icon' => 'power-off',
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return $navArray;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the browser <title>
|
|
|
|
|
*
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getBrowserTitle() {
|
|
|
|
|
|
|
|
|
|
$browserTitle = $this->wire('processBrowserTitle');
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$modal = $this->wire()->input->get('modal');
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
|
|
|
|
if(!$browserTitle) {
|
|
|
|
|
if($modal) return $this->wire('processHeadline');
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$browserTitle = $this->_(strip_tags($this->wire()->page->get('title|name'))) . ' • ProcessWire';
|
2022-03-08 15:55:41 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!$modal) {
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$httpHost = $this->wire()->config->httpHost;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
if(strpos($httpHost, 'www.') === 0) $httpHost = substr($httpHost, 4); // remove www
|
|
|
|
|
if(strpos($httpHost, ':')) $httpHost = preg_replace('/:\d+/', '', $httpHost); // remove port
|
|
|
|
|
$browserTitle .= " • $httpHost";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->sanitizer->entities1($browserTitle);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Test all notice types
|
|
|
|
|
*
|
|
|
|
|
* @return bool
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function testNotices() {
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if(!$this->wire()->user->isLoggedin()) return false;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$this->message('Message test');
|
|
|
|
|
$this->message('Message test debug', Notice::debug);
|
|
|
|
|
$this->message('Message test markup <a href="#">example</a>', Notice::allowMarkup);
|
|
|
|
|
$this->warning('Warning test');
|
|
|
|
|
$this->warning('Warning test debug', Notice::debug);
|
|
|
|
|
$this->warning('Warning test markup <a href="#">example</a>', Notice::allowMarkup);
|
|
|
|
|
$this->error('Error test');
|
|
|
|
|
$this->error('Error test debug', Notice::debug);
|
|
|
|
|
$this->error('Error test markup <a href="#">example</a>', Notice::allowMarkup);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render runtime notices div#notices
|
|
|
|
|
*
|
|
|
|
|
* @param Notices|bool $notices Notices object or specify boolean true to return array of all available $options
|
|
|
|
|
* @param array $options See defaults in method
|
|
|
|
|
* @return string|array Returns string unless you specify true for $notices argument, then it returns an array.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function renderNotices($notices, array $options = array()) {
|
|
|
|
|
|
|
|
|
|
$defaults = array(
|
|
|
|
|
'messageClass' => 'NoticeMessage', // class for messages
|
|
|
|
|
'messageIcon' => 'check-square', // default icon to show with notices
|
|
|
|
|
'warningClass' => 'NoticeWarning', // class for warnings
|
|
|
|
|
'warningIcon' => 'exclamation-circle', // icon for warnings
|
|
|
|
|
'errorClass' => 'NoticeError', // class for errors
|
|
|
|
|
'errorIcon' => 'exclamation-triangle', // icon for errors
|
|
|
|
|
'debugClass' => 'NoticeDebug', // class for debug items (appended)
|
|
|
|
|
'debugIcon' => 'bug', // icon for debug notices
|
|
|
|
|
'closeClass' => 'pw-notice-remove notice-remove', // class for close notices link <a>
|
|
|
|
|
'closeIcon' => 'times', // icon for close notices link
|
|
|
|
|
'listMarkup' => "<ul class='pw-notices' id='notices'>{out}</ul><!--/notices-->",
|
|
|
|
|
'itemMarkup' => "<li class='{class}'>{remove}{icon}{text}</li>",
|
|
|
|
|
// the following apply only when groupByType==true
|
|
|
|
|
'groupByType' => true, // Group notices by type
|
|
|
|
|
'groupParentClass' => 'pw-notice-group-parent', // class for parent notices
|
|
|
|
|
'groupChildClass' => 'pw-notice-group-child', // class for children (of parent notices)
|
|
|
|
|
'groupToggleMarkup' => "<a class='pw-notice-group-toggle' href='#'>{label}" .
|
|
|
|
|
"<i class='fa fa-fw fa-bell-o' data-toggle='fa-bell-o fa-bell'></i>" .
|
|
|
|
|
"<i class='fa fa-fw fa-angle-right' data-toggle='fa-angle-right fa-angle-down'></i></a>",
|
|
|
|
|
'groupToggleLabel' => $this->_("+{n-1}"),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$options = array_merge($defaults, $options);
|
|
|
|
|
if($notices === true) return $options;
|
2023-03-10 19:41:40 +01:00
|
|
|
|
$config = $this->wire()->config;
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$noticesArray = array();
|
|
|
|
|
$out = '';
|
|
|
|
|
|
|
|
|
|
$removeIcon = $this->renderIcon($options['closeIcon']);
|
|
|
|
|
$removeLabel = $this->_('Close all');
|
|
|
|
|
$removeLink = "<a class='$options[closeClass]' href='#' title='$removeLabel'>$removeIcon</a>";
|
|
|
|
|
|
2023-03-10 19:41:40 +01:00
|
|
|
|
if($this->isLoggedIn && $this->wire()->modules->isInstalled('SystemNotifications')) {
|
2022-03-08 15:55:41 +01:00
|
|
|
|
$defaults['groupByType'] = false;
|
|
|
|
|
//$systemNotifications = $this->wire('modules')->get('SystemNotifications');
|
|
|
|
|
//if(!$systemNotifications->placement) return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach($notices as $n => $notice) {
|
2023-03-10 19:41:40 +01:00
|
|
|
|
/** @var Notice $notice */
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
|
|
|
|
$text = $notice->text;
|
|
|
|
|
$allowMarkup = $notice->flags & Notice::allowMarkup;
|
|
|
|
|
$groupByType = $options['groupByType'] && !($notice->flags & Notice::noGroup) && !($notice instanceof NoticeError);
|
|
|
|
|
|
|
|
|
|
if($allowMarkup) {
|
|
|
|
|
// leave $text alone
|
|
|
|
|
} else {
|
|
|
|
|
// unencode + re-encode entities, just in case module already entity some or all of output
|
|
|
|
|
if(strpos($text, '&') !== false) $text = $this->sanitizer->unentities($text);
|
|
|
|
|
$text = $this->sanitizer->entities($text);
|
|
|
|
|
$text = nl2br($text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($notice instanceof NoticeError) {
|
|
|
|
|
$class = $options['errorClass'];
|
|
|
|
|
$icon = $options['errorIcon'];
|
|
|
|
|
$noticeType = 'errors';
|
|
|
|
|
|
|
|
|
|
} else if($notice instanceof NoticeWarning) {
|
|
|
|
|
$class = $options['warningClass'];
|
|
|
|
|
$icon = $options['warningIcon'];
|
|
|
|
|
$noticeType = 'warnings';
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
$class = $options['messageClass'];
|
|
|
|
|
$icon = $options['messageIcon'];
|
|
|
|
|
$noticeType = 'messages';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($notice->flags & Notice::debug) {
|
|
|
|
|
$class .= " " . $options['debugClass'];
|
|
|
|
|
$icon = $options['debugIcon'];
|
|
|
|
|
// ensure non-debug version is set as well
|
|
|
|
|
if(!isset($noticesArray[$noticeType])) $noticesArray[$noticeType] = array();
|
|
|
|
|
$noticeType .= "-debug";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// indicate which class the notice originated from in debug mode
|
|
|
|
|
if($notice->class && $config->debug) $text = "{$notice->class}: $text";
|
|
|
|
|
|
|
|
|
|
$replacements = array(
|
|
|
|
|
'{class}' => $class,
|
|
|
|
|
'{remove}' => '',
|
|
|
|
|
'{icon}' => $this->renderNavIcon($notice->icon ? $notice->icon : $icon),
|
|
|
|
|
'{text}' => $text,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if($groupByType) {
|
|
|
|
|
if(!isset($noticesArray[$noticeType])) $noticesArray[$noticeType] = array();
|
|
|
|
|
$noticesArray[$noticeType][] = $replacements;
|
|
|
|
|
} else {
|
|
|
|
|
if($n === 0) $replacements['{remove}'] = $removeLink;
|
|
|
|
|
$out .= str_replace(array_keys($replacements), array_values($replacements), $options['itemMarkup']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($options['groupByType']) {
|
|
|
|
|
$cnt = 0;
|
|
|
|
|
foreach($noticesArray as $noticeType => $noticeReplacements) {
|
|
|
|
|
if(strpos($noticeType, '-debug')) continue;
|
|
|
|
|
if(isset($noticesArray["$noticeType-debug"])) {
|
|
|
|
|
$noticeReplacements = array_merge($noticeReplacements, $noticesArray["$noticeType-debug"]);
|
|
|
|
|
}
|
|
|
|
|
$n = count($noticeReplacements);
|
|
|
|
|
if($n > 1) {
|
|
|
|
|
$notice =& $noticeReplacements[0];
|
|
|
|
|
$label = str_replace(array('{n}', '{n-1}'), array($n, $n-1), $options['groupToggleLabel']);
|
|
|
|
|
$notice['{text}'] .= ' ' . str_replace(array('{label}'), array($label), $options['groupToggleMarkup']);
|
|
|
|
|
$notice['{class}'] .= ' ' . $options['groupParentClass'];
|
|
|
|
|
$childClass = $options['groupChildClass'];
|
|
|
|
|
} else {
|
|
|
|
|
$childClass = '';
|
|
|
|
|
}
|
|
|
|
|
foreach($noticeReplacements as $i => $replacements) {
|
|
|
|
|
if(!$cnt) $replacements['{remove}'] = $removeLink;
|
|
|
|
|
if($childClass && $i > 0) $replacements['{class}'] .= ' ' . $childClass;
|
|
|
|
|
$out .= str_replace(array_keys($replacements), array_values($replacements), $options['itemMarkup']);
|
|
|
|
|
$cnt++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$out = str_replace('{out}', $out, $options['listMarkup']);
|
|
|
|
|
$out .= $this->renderExtraMarkup('notices');
|
|
|
|
|
|
|
|
|
|
return $out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render markup for a font-awesome icon
|
|
|
|
|
*
|
|
|
|
|
* @param string $icon Name of icon to render, excluding the “fa-” prefix
|
|
|
|
|
* @param bool $fw Specify true to make fixed width (default=false).
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function renderIcon($icon, $fw = false) {
|
|
|
|
|
if($fw) $icon .= ' fa-fw';
|
|
|
|
|
return "<i class='fa fa-$icon'></i>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render markup for a font-awesome icon that precedes a navigation label
|
|
|
|
|
*
|
|
|
|
|
* This is the same as renderIcon() except that fixed-width is assumed and a "nav-nav-icon"
|
|
|
|
|
* class is added to it.
|
|
|
|
|
*
|
|
|
|
|
* @param string $icon Name of icon to render, excluding the “fa-” prefix
|
|
|
|
|
* @return string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function renderNavIcon($icon) {
|
|
|
|
|
return $this->renderIcon("$icon pw-nav-icon", true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render an extra markup region
|
|
|
|
|
*
|
|
|
|
|
* @param string $for
|
|
|
|
|
* @return mixed|string
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function renderExtraMarkup($for) {
|
|
|
|
|
static $extras = array();
|
|
|
|
|
if(empty($extras)) $extras = $this->getExtraMarkup();
|
|
|
|
|
return isset($extras[$for]) ? $extras[$for] : '';
|
|
|
|
|
}
|
2022-11-05 18:32:48 +01:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Render a admin theme template file
|
|
|
|
|
*
|
|
|
|
|
* This method is only used if it is hooked
|
|
|
|
|
*
|
|
|
|
|
* #pw-hooker
|
|
|
|
|
*
|
|
|
|
|
* @param string $file Full path and filename
|
|
|
|
|
* @param array $vars Associative array of variables to populate in rendered file
|
|
|
|
|
* @return string Returns blank string when $echo is true
|
|
|
|
|
* @since 3.0.196
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
protected function ___renderFile($file, array $vars = array()) {
|
|
|
|
|
extract($vars);
|
|
|
|
|
ob_start();
|
|
|
|
|
include($file);
|
|
|
|
|
$out = ob_get_contents();
|
|
|
|
|
ob_end_clean();
|
|
|
|
|
return $out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Include an admin theme file
|
|
|
|
|
*
|
|
|
|
|
* @param string $basename
|
|
|
|
|
* @param array $vars
|
|
|
|
|
* @since 3.0.196
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function includeFile($basename, array $vars = array()) {
|
|
|
|
|
|
|
|
|
|
$file = '';
|
|
|
|
|
|
|
|
|
|
if($this->renderFileHooked === null) {
|
|
|
|
|
$this->renderFileHooked = $this->hasHook('renderFile()');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($this->defaultTemplatePath === null) {
|
|
|
|
|
$this->defaultTemplatePath = $this->wire()->config->paths($this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($this->customTemplatePath === null) {
|
|
|
|
|
$path = $this->wire()->config->paths->templates . $this->className() . '/';
|
|
|
|
|
$this->customTemplatePath = is_dir($path) ? $path : '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($this->customTemplatePath) {
|
|
|
|
|
$file = $this->customTemplatePath . $basename;
|
|
|
|
|
if(!file_exists($file)) $file = '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if($file === '') $file = $this->defaultTemplatePath . $basename;
|
|
|
|
|
|
|
|
|
|
$fuel = $this->wire()->fuel;
|
|
|
|
|
$vars['fuel'] = $fuel;
|
|
|
|
|
$vars = array_merge($fuel->getArray(), $vars);
|
|
|
|
|
unset($vars['file'], $vars['vars']); // just in case either was set
|
|
|
|
|
|
|
|
|
|
if($this->renderFileHooked) {
|
|
|
|
|
echo $this->renderFile($file, $vars);
|
|
|
|
|
} else {
|
|
|
|
|
extract($vars);
|
|
|
|
|
include($file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set custom path for admin theme templates
|
|
|
|
|
*
|
|
|
|
|
* This is for modules to optionally set a custom template path. If not set then the default
|
|
|
|
|
* in /site/templates/AdminTheme[Class]/ is used.
|
|
|
|
|
*
|
|
|
|
|
* @param string $path
|
|
|
|
|
* @since 3.0.196
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function setCustomTemplatePath($path) {
|
|
|
|
|
$this->customTemplatePath = $path;
|
|
|
|
|
}
|
2022-03-08 15:55:41 +01:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Module Configuration
|
|
|
|
|
*
|
|
|
|
|
* @param InputfieldWrapper $inputfields
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public function getModuleConfigInputfields(InputfieldWrapper $inputfields) {
|
|
|
|
|
$modules = $this->wire()->modules;
|
|
|
|
|
$input = $this->wire()->input;
|
|
|
|
|
$roles = $this->wire()->roles;
|
|
|
|
|
|
|
|
|
|
/** @var InputfieldCheckbox $f */
|
|
|
|
|
$f = $modules->get('InputfieldCheckbox');
|
|
|
|
|
$f->name = 'useAsLogin';
|
|
|
|
|
$f->label = $this->_('Use this admin theme for login screen?');
|
|
|
|
|
$f->description = $this->_('When checked, this admin theme will be used on the user login screen.');
|
|
|
|
|
$f->icon = 'sign-in';
|
|
|
|
|
$f->columnWidth = 50;
|
|
|
|
|
if($this->get('useAsLogin')) $f->attr('checked', 'checked');
|
|
|
|
|
$inputfields->add($f);
|
|
|
|
|
|
|
|
|
|
if($f->attr('checked') && $input->requestMethod('GET')) {
|
|
|
|
|
$themes = $modules->findByPrefix('AdminTheme');
|
|
|
|
|
$class = $this->className();
|
|
|
|
|
foreach($themes as $name) {
|
|
|
|
|
if($name === $class) continue;
|
|
|
|
|
$cfg = $modules->getConfig($name);
|
|
|
|
|
if(!empty($cfg['useAsLogin'])) {
|
|
|
|
|
unset($cfg['useAsLogin']);
|
|
|
|
|
$modules->saveConfig($name, $cfg);
|
|
|
|
|
$this->message("Removed 'useAsLogin' setting from $name", Notice::debug);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @var InputfieldSelect $f */
|
|
|
|
|
$f = $modules->get('InputfieldSelect');
|
|
|
|
|
$f->name = '_setAdminThemeRoleId';
|
|
|
|
|
$f->label = $this->_('Change users to this admin theme');
|
|
|
|
|
$f->description = $this->_('Select user role to update matching users to this admin theme.');
|
|
|
|
|
$f->columnWidth = 50;
|
|
|
|
|
$f->icon = 'users';
|
|
|
|
|
foreach($roles as $role) {
|
|
|
|
|
if($role->name === 'guest') continue;
|
|
|
|
|
$f->addOption($role->id, sprintf($this->_('Role: %s'), $role->name));
|
|
|
|
|
}
|
|
|
|
|
$inputfields->add($f);
|
|
|
|
|
|
|
|
|
|
$roleId = (int) $input->post('_setAdminThemeRoleId');
|
|
|
|
|
$role = $roleId ? $roles->get($roleId) : null;
|
|
|
|
|
if($role) {
|
|
|
|
|
$n = $this->wire()->users->setAdminThemeByRole($this, $role);
|
|
|
|
|
$this->message(sprintf($this->_('Set %d user(s) to have this admin theme'), $n), Notice::noGroup);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|