1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-08 15:57:01 +02:00

PR #189 - Update AdminThemeUikit to support custom LESS files. Authored by @BernhardBaumrock with some additions by @ryancramerdesign

Co-authored-by: BernhardBaumrock <office@baumrock.com>
This commit is contained in:
Ryan Cramer
2021-05-27 13:17:56 -04:00
parent 58ac07e9a9
commit 3522b89414
7 changed files with 330 additions and 21 deletions

View File

@@ -20,6 +20,7 @@
* @property string $inputSize Size for input/select elements. One of "s" for small, "m" for medium (default), or "l" for large.
* @property bool|int $ukGrid When true, use uk-width classes for Inputfields (rather than CSS percentages).
* @property int $toggleBehavior (0=Standard, 1=Consistent)
* property string $configPhpHash Hash used internally to detect changes to $config->AdminThemeUikit settings.
*
* @method string getUikitCSS()
*
@@ -30,10 +31,9 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
public static function getModuleInfo() {
return array(
'title' => 'Uikit',
'version' => 31,
'version' => 32,
'summary' => 'Uikit v3 admin theme',
'autoload' => 'template=admin',
'requires' => 'ProcessWire>=3.0.100'
);
}
@@ -45,11 +45,17 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
*/
const dev = false;
/**
* Set to true when upgrading Uikit version
*
*/
const upgrade = false;
/**
* Default logo image file (relative to this dir)
*
*/
const logo = 'uikit/custom/images/pw-mark.png';
const logo = 'uikit-pw/images/pw-mark.png';
/**
* sidenavType: primary navigation on left sidebar
@@ -86,6 +92,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
$this->set('groupNotices', true);
$this->set('inputSize', 'm'); // m=medium (default), s=small, l=large
$this->set('ukGrid', false);
$this->set('configPhpHash', '');
$this->setClasses(array(
'input' => 'uk-input',
'input-small' => 'uk-input uk-form-small',
@@ -104,7 +111,7 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
public function wired() {
parent::wired();
$this->addHookAfter('InputfieldSelector::ajaxReady', $this, 'hookInputfieldSelectorAjax');
$this->addHookAfter('InputfieldSelector::ajaxReady', $this, 'hookInputfieldSelectorAjax');
}
/**
@@ -1065,25 +1072,31 @@ class AdminThemeUikit extends AdminThemeFramework implements Module, Configurabl
}
/**
* Get the primary Uikit CSS file to use
* Get the primary Uikit CSS URL to use
*
* @return string
* @since 3.0.178 Was not hookable in prior versions
*
*/
public function ___getUikitCSS() {
$config = $this->wire('config');
$cssURL = $this->get('cssURL');
$moduleInfo = self::getModuleInfo();
$version = $moduleInfo['version'];
if($cssURL) {
if(strpos($cssURL, '//') === false) $cssURL = $config->urls->root . ltrim($cssURL, '/');
return $this->wire('sanitizer')->entities($cssURL);
} else if(self::dev && strpos(__FILE__, '/wire/modules/') === false) {
return $this->url() . 'uikit/custom/pw.css?v=' . $version;
} else {
return $this->url() . 'uikit/dist/css/uikit.pw.min.css?v=' . $version;
$config = $this->wire()->config;
$cssUrl = $this->get('cssURL');
if($cssUrl) { // a custom css URL was set in the theme config
if(strpos($cssUrl, '//') === false) $cssUrl = $config->urls->root . ltrim($cssUrl, '/');
return $this->wire()->sanitizer->entities($cssUrl);
}
require_once(__DIR__ . '/AdminThemeUikitCss.php');
$settings = $config->AdminThemeUikit;
if(!is_array($settings)) $settings = array();
if(self::upgrade) $settings['upgrade'] = true;
$css = new AdminThemeUikitCss($this, $settings);
return $css->getCssFile();
}
/**

View File

@@ -0,0 +1,241 @@
<?php namespace ProcessWire;
/**
* AdminThemeUikit CSS
*
* Manages selection of CSS file and determines when CSS file to be recompiled from LESS
* source files.
*
* @property bool $upgrade Set to true when upgrading core Uikit version. (default=false)
* @property array $baseStyles Base style options (default=[ 'reno', 'rock' ])
* @property string $defaultStyle Default style (default='reno')
* @property string $defaultCssFile Core CSS file to create when upgrading (relative to module root)
* @property string $styleDir Directory where base .less files are located (relative to module root)
*
* @property string $configPhpHash Hash used internally to detect changes to $config->AdminThemeUikit settings.
* @property string $configPhpName Name of property in $config that holds custom settings (default='AdminThemeUikit').
*
* Settings that may be specified in $config->AdminThemeUikit array:
*
* @property string $style Configured style name to use, one of blank (for default), 'reno' or 'rock'.
* @property bool $recompile Recompile all LESS to CSS now? (set to true for 1 request only)
* @property bool $compress Compress compiled CSS? (default=true)
* @property array $customLessFiles Custom .less file(s) to include, relative to PW root.
* @property string $customCssFile Custom target .css file to compile custom .less file(s) to, relative to PW root.
*
* @since 3.0.179
*
*/
class AdminThemeUikitCss extends WireData {
/**
* @var AdminTheme
*
*/
protected $adminTheme;
/**
* Construct
*
* @param AdminTheme $adminTheme
* @param array $options
*
*/
public function __construct(AdminTheme $adminTheme, array $options = array()) {
$this->adminTheme = $adminTheme;
$adminTheme->wire($this);
$this->setArray(array_merge($this->getDefaults(), $options));
parent::__construct();
}
/**
* @return array
*
*/
public function getDefaults() {
return array(
'baseStyles' => array('reno', 'rock'),
'defaultStyle' => 'reno',
'defaultCssFile' => 'uikit-pw/pw.min.css',
'styleDir' => 'uikit-pw/styles/',
'style' => '',
'upgrade' => false,
'recompile' => false,
'compress' => true,
'customLessFiles' => array('/site/templates/admin.less'),
'customCssFile' => '/site/assets/admin.css',
'configPhpName' => $this->adminTheme->className(),
'configPhpHash' => $this->adminTheme->get('configPhpHash'),
);
}
/**
* Get the primary Uikit CSS file URL to use (whether default or custom)
*
* @param bool $getPath Get disk path rather than URL?
* @return string
*
*/
public function getCssFile($getPath = false) {
$modules = $this->wire()->modules;
if(!$modules->isInstalled('Less')) return $this->getDefaultCssFile($getPath);
if($this->upgrade) {
$cssFile = $this->getDefaultCssFile(true);
$cssTime = filemtime($cssFile);
$lessFiles = array();
$recompile = true;
} else {
$lessFiles = array();
$lessTime = 0;
foreach($this->customLessFiles as $file) {
$file = $this->customFile($file, 'less');
if(!$file || !is_file($file)) continue;
$lessFiles[] = $file;
$mtime = filemtime($file);
if($mtime > $lessTime) $lessTime = $mtime;
}
if(!count($lessFiles)) return $this->getDefaultCssFile($getPath);
$cssFile = $this->customFile($this->customCssFile, 'css');
if(!$cssFile) return $this->getDefaultCssFile();
$cssTime = is_file($cssFile) ? (int) filemtime($cssFile) : 0;
$recompile = $lessTime > $cssTime || $this->configPhpSettingsChanged();
}
if($recompile) try {
/** @var AdminThemeUikitLessInterface $less */
$less = $modules->get('Less');
$less->setOption('compress', $this->compress);
$less->addFile($this->getAdminLessFile());
$less->addFiles($lessFiles);
if(!$less->saveCss($cssFile)) throw new WireException("Compile error: $cssFile");
$this->message(sprintf($this->_('Compiled: %s'), $cssFile), Notice::noGroup);
$cssTime = filemtime($cssFile);
} catch(\Exception $e) {
$this->error('LESS - ' . $e->getMessage(), Notice::noGroup);
}
return $getPath ? $cssFile : $this->fileToUrl($cssFile) . "?v=$cssTime";
}
/**
* Get URL for given full path/file
*
* @param string $file
* @return string
*
*/
protected function fileToUrl($file) {
$config = $this->wire()->config;
return $config->urls->root . substr($file, strlen($config->paths->root));
}
/**
* Get default Uikit CSS file URL or disk path
*
* @param bool $getPath
* @return string
*
*/
public function getDefaultCssFile($getPath = false) {
$config = $this->wire()->config;
$file = $this->defaultCssFile;
$path = $config->paths($this->adminTheme) . $file;
if($getPath) return $path;
$v = filemtime($path);
$url = $config->urls($this->adminTheme) . "$file?v=$v" ;
return $url;
}
/**
* Have the $config->AdminThemeUikit settings changed?
*
* @return bool
* @throws WireException
*
*/
public function configPhpSettingsChanged() {
$settings = $this->wire()->config->get($this->configPhpName);
unset($settings['recompile']); // recompile is runtime only setting
$hashNow = md5(print_r($settings, true));
$hashThen = $this->get('configPhpHash');
if($hashNow === $hashThen) return false;
$this->wire()->modules->saveConfig($this->adminTheme, 'configPhpHash', $hashNow);
return true;
}
/**
* Apply custom file/path replacements
*
* @param string $file
* @param string $requireExtension Extension to require on given file
* @return string
*
*/
protected function customFile($file, $requireExtension = '') {
$paths = $this->wire()->config->paths;
$file = $this->wire()->files->unixFileName($file);
$replacements = array(
'/site/assets/' => $paths->assets,
'/site/templates/' => $paths->templates,
'/site/modules/' => $paths->siteModules,
);
if($requireExtension) {
$ext = pathinfo($file, PATHINFO_EXTENSION);
if(strtolower($ext) !== strtolower($requireExtension)) return '';
}
foreach($replacements as $find => $replace) {
if(strpos($file, $find) === 0) $file = str_replace($find, $replace, $file);
}
if($file && strpos($file, $paths->root) !== 0) {
$file = $paths->root . ltrim($file, '/');
}
return $file;
}
/**
* Get admin base less file to use
*
* @return string
*
*/
public function getAdminLessFile() {
$config = $this->wire()->config;
$files = $this->wire()->files;
$path = $config->paths($this->adminTheme) . $this->styleDir;
$defaultFile = $path . $this->defaultStyle . '.less';
$baseStyle = $this->upgrade ? $this->defaultStyle : $this->style;
if(empty($baseStyle) || $baseStyle === $this->defaultStyle) return $defaultFile;
if(stripos($baseStyle, '.')) {
// style is file name relative to installation root path
$file = $this->customFile($baseStyle, 'less');
if($file && is_file($file) && $files->allowPath($file, $config->paths->root)) return $file;
}
$file = $path . basename($baseStyle) . '.less';
if(in_array($baseStyle, $this->baseStyles) || is_file($file)) return $file;
$this->warning(
"config.{$this->configPhpName}[style]: " .
sprintf($this->_('Admin base style - file not found: %s'), $file),
Notice::debug
);
return $defaultFile;
}
}

View File

@@ -20,7 +20,7 @@ $logoOptions = array('height' => '40px');
</a>
</div>
</header>
<header id='pw-masthead' class='pw-masthead uk-background-muted' data-pw-height='73'>
<header id='pw-masthead' class='pw-masthead uk-background-muted' data-pw-height='80'> <?php /* data-pw-height='73' */ ?>
<div class='pw-container uk-container uk-container-expand'>
<nav class='uk-navbar uk-navbar-container uk-navbar-transparent' uk-navbar>
<div class='uk-navbar-left'>

View File

@@ -20,7 +20,7 @@ if(!defined("PROCESSWIRE")) die();
<a id="offcanvas-nav-close" href='#offcanvas-nav' class='uk-text-muted' onclick='return false;' data-uk-toggle>
<i class='fa fa-times uk-float-right uk-margin-small-top'></i>
</a>
<img class='pw-logo' width='200' style='margin-left:-5px' src='<?php echo $adminTheme->url(); ?>uikit/custom/images/logo.png' />
<img class='pw-logo' width='200' style='margin-left:-5px' src='<?php echo $adminTheme->url(); ?>uikit-pw/images/logo.png' />
</p>
<?php include(__DIR__ . '/_search-form.php'); ?>
<ul class='pw-sidebar-nav uk-nav uk-nav-parent-icon uk-margin-small-top' data-uk-nav='animation: false; multiple: true;'>

View File

@@ -219,6 +219,9 @@ class AdminThemeUikitConfigHelper extends Wire {
$fieldset2 = $modules->get('InputfieldFieldset');
$fieldset2->label = $this->_('Advanced');
$fieldset2->collapsed = Inputfield::collapsedBlank;
$fieldset2->description =
$this->_('Most advanced settings are available from the `$config->AdminThemeUikit` settings array.') . ' ' .
$this->_('You can find it in /wire/config.php. Copy to your /site/config.php file to modify it.');
$fieldset->add($fieldset2);
/** @var InputfieldText $f */
@@ -227,10 +230,12 @@ class AdminThemeUikitConfigHelper extends Wire {
$f->attr('value', $adminTheme->get('cssURL'));
$f->label = $this->_('Primary CSS file');
$f->description = $defaultFileDesc . ' ' .
$this->_('We do not recommend changing this unless you are an admin theme developer.');
$this->_('We do not recommend changing this unless you are an admin theme developer.') . ' ' .
$this->_('Warning: this will override custom `$config->AdminThemeUikit` settings, base style and custom styles.');
$f->notes = $defaultFileNote . " " .
"[uikit.pw.css](" . $modules->wire('config')->urls('AdminThemeUikit') . "uikit/dist/css/uikit.pw.css)";
$f->icon = 'file-code-o';
$f->collapsed = Inputfield::collapsedBlank;
$fieldset2->add($f);
/** @var InputfieldFieldset $fieldset */

View File

@@ -21,7 +21,7 @@ $formAction = htmlentities($formAction, ENT_QUOTES, "UTF-8");
var config = ProcessWire.config;
</script>
<link type='text/css' href='wire/modules/AdminTheme/AdminThemeUikit/uikit/dist/css/uikit.pw.min.css' rel='stylesheet' />
<link type='text/css' href='wire/modules/AdminTheme/AdminThemeUikit/uikit-pw/pw.min.css' rel='stylesheet' />
<link type='text/css' href='wire/templates-admin/styles/AdminTheme.css' rel='stylesheet' />
<link type='text/css' href='wire/templates-admin/styles/font-awesome/css/font-awesome.min.css' rel='stylesheet' />
@@ -50,7 +50,7 @@ $formAction = htmlentities($formAction, ENT_QUOTES, "UTF-8");
<header id='pw-masthead-mobile' class='pw-masthead uk-background-muted'>
<div class='pw-container uk-container uk-container-center'>
<a href='https://processwire.com' target='_blank' class='pw-logo-link'>
<img class='pw-logo pw-logo-native' src='wire/modules/AdminTheme/AdminThemeUikit/uikit/custom/images/pw-mark.png' alt='' />
<img class='pw-logo pw-logo-native' src='wire/modules/AdminTheme/AdminThemeUikit/uikit-pw/images/pw-mark.png' alt='' />
</a>
</div>
</header>

View File

@@ -0,0 +1,50 @@
<?php namespace ProcessWire;
/**
* Less parser interface, for documentation purposes only
*
*/
interface AdminThemeUikitLessInterface {
/**
* @param string $name
* @param mixed $value
* @return self
*
*/
public function setOption($name, $value);
/**
* @param array $options
* @return object instance of \Less_Parser
*
*/
public function parser($options = array());
/**
* @param string $file
* @return self
*
*/
public function addFile($file);
/**
* @param array $files
* @return self
*
*/
public function addFiles($files);
/**
* @param string $file
* @return bool
*
*/
public function saveCss($file);
/**
* @return string
*
*/
public function getCss();
}