1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-09 16:26:59 +02:00

Add PR #215 to enable additional markup customization options in AdminThemeUikit via @BernhardBaumrock

Co-authored-by: BernhardBaumrock <office@baumrock.com>
This commit is contained in:
Ryan Cramer
2022-03-08 11:42:35 -05:00
parent 8b46cb6fd0
commit d978eccbc9
18 changed files with 412 additions and 119 deletions

View File

@@ -9,7 +9,7 @@
* This file is licensed under the MIT license.
* https://processwire.com/about/license/mit/
*
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
* https://processwire.com
*
* @property bool $isSuperuser
@@ -19,6 +19,7 @@
* @property bool|int $useAsLogin
* @method array getUserNavArray()
* @method array getPrimaryNavArray()
* @method string renderFile($basename, array $vars = array())
*
*/
abstract class AdminThemeFramework extends AdminTheme {
@@ -61,6 +62,30 @@ abstract class AdminThemeFramework extends AdminTheme {
*/
protected $sanitizer;
/**
* 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;
/**
* Construct
*
@@ -766,6 +791,88 @@ abstract class AdminThemeFramework extends AdminTheme {
if(empty($extras)) $extras = $this->getExtraMarkup();
return isset($extras[$for]) ? $extras[$for] : '';
}
/**
* 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)) $this->warning($file);
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;
}
/**
* Module Configuration

View File

@@ -1,11 +1,96 @@
# AdminThemeUikit
This document currently covers customization of Uikit styles and instructions on
how to upgrade the core Uikit version.
This document currently covers customization of the Uikit styles, overriding admin theme
template files and markup, and instructions on how to upgrade the core Uikit version.
## Customization
## Customizing Markup
### Short version
### Overriding markup files
You can overwrite any of the markup files located in `wire/modules/AdminTheme/AdminThemeUikit/`
by placing a file with the same name in `/site/templates/AdminThemeUikit/`. You could for example
overwrite the footer by adding the file `/site/templates/AdminThemeUikit/_footer.php` to your
installation:
```html
<div>My custom footer</div>
```
The files you can replace include:
- `_head.php*` - Document `<head>`.
- `_masthead.php` - Masthead and primary navigation.
- `_search-form.php` - Search form that appears in the masthead.
- `_content.php` - Main content area.
- `_content-head.php` - Main content header, including breadcrumbs, headline, etc.
- `_content-body.php` - Main content body where most output goes.
- `_footer.php` - Footer area.
- `_offcanvas.php` - Offcanvas navigation bar.
- `_body-scripts.php` - Scripts that appear before `</body>`.
- `_main.php` - The main markup file that includes all the others above.
For example, let's say you wanted to replace the main content `#pw-content-body`
with "Hello World", add file `/site/templates/AdminThemeUikit/_content-body.php`
and place the following in it:
```html
<p>Hello World</p>
```
This replaces all the content of every admin page with your Hello World message. That's not
very useful so let's instead copy the contents of the default `_content-body.php` and use
that as our starting point, and append our Hello World message within it:
```php
<?php namespace ProcessWire;
if(!defined("PROCESSWIRE")) die(); ?>
<div id='pw-content-body'>
<?php echo $page->get('body') . $content; ?>
<p>Hello World</p>
</div>
```
### Customizing markup with hooks
You can hook into rendering of the admin theme partials:
```php
$wire->addHookAfter('AdminThemeUikit::renderFile', function($event) {
$file = $event->arguments(0); // full path/file being rendered
$vars = $event->arguments(1); // assoc array of vars sent to file
if(basename($file) === '_footer.php') {
$event->return = str_replace(
"ProcessWire",
"ProcessWire is the best CMS",
$event->return
);
}
});
```
### Additional recognized extra markup regions
You can use `$adminTheme->addExtraMarkup($name, $value)` to add additional markup to
several recognized regions.
```php
$adminTheme->addExtraMarkup("head", "<script>alert('test!');</script>");
```
The `$value` can be any additional markup that you want to insert and the `$name` can be
any of the following (in order of appearance):
- `head` - Inserted before `</head>`.
- `masthead` - Inserted at the end of `div#pw-mastheads`.
- `notices` - Inserted after notifications `ul#notices`.
- `content` - Inserted at end of `div#pw-content-body`.
- `footer` - Inserted at end of `footer#pw-footer`.
- `body` - Inserted before `</body>`.
---
## Customizing CSS
### Summary
You can easily customize AdminThemeUikit in 3 simple steps:
@@ -15,9 +100,7 @@ You can easily customize AdminThemeUikit in 3 simple steps:
Either step 2 or 3 can be optional too, more details below.
---
### Long version
### Full instructions
Now that you know what to do, lets run through 3 steps above again, but with more details:

View File

@@ -0,0 +1,31 @@
<?php namespace ProcessWire;
/**
* Scripts that are inserted before </body>
*
*/
if(!defined("PROCESSWIRE")) die();
/** @var string $layout */
/** @var Process $process */
/** @var WireInput $input */
?>
<script>
<?php
if(strpos($layout, 'sidenav-tree') === 0) {
echo "if(typeof parent.isPresent != 'undefined'){";
if(strpos("$process", 'ProcessPageList') === 0) {
echo "parent.hideTreePane();";
} else {
echo "if(!parent.isMobileWidth() && parent.treePaneHidden()) parent.showTreePane();";
}
if($process == 'ProcessPageEdit' && ($input->get('s') || $input->get('new'))) {
echo "parent.refreshTreePane(" . ((int) $input->get('id')) . ");";
}
echo "}";
}
?>
ProcessWireAdminTheme.init();
</script>

View File

@@ -0,0 +1,19 @@
<?php namespace ProcessWire;
/**
* Primary content head (#main > #content > #pw-content-head)
*
*/
if(!defined("PROCESSWIRE")) die();
/** @var AdminThemeUikit $adminTheme */
/** @var string $content */
/** @var Page $page */
?>
<div id='pw-content-body'>
<?php echo $page->get('body') . $content; ?>
</div>

View File

@@ -0,0 +1,32 @@
<?php namespace ProcessWire;
/**
* Primary content head (#main > #content > #pw-content-head)
*
*/
if(!defined("PROCESSWIRE")) die();
/** @var string $layout */
/** @var AdminThemeUikit $adminTheme */
/** @var string $headline */
/** @var Page $page */
?>
<header id='pw-content-head'>
<?php if($layout != 'sidenav' && $layout != 'modal') echo $adminTheme->renderBreadcrumbs(); ?>
<div id='pw-content-head-buttons' class='uk-float-right uk-visible@s'>
<?php echo $adminTheme->renderAddNewButton(); ?>
</div>
<?php
if($headline !== '' && !$adminTheme->isModal) {
echo "<h1 id='pw-content-title' class='uk-margin-remove-top'>$headline</h1>";
}
?>
</header>

View File

@@ -0,0 +1,26 @@
<?php namespace ProcessWire;
/**
* Primary content (#main > #content)
*
*/
if(!defined("PROCESSWIRE")) die();
/** @var string $layout */
/** @var AdminThemeUikit $adminTheme */
/** @var string $content */
/** @var string $headline */
/** @var Page $page */
?>
<main id='main' class='pw-container uk-container uk-container-expand uk-margin uk-margin-large-bottom'>
<div class='pw-content' id='content'>
<?php
$adminTheme->includeFile('_content-head.php', array('layout' => $layout, 'headline' => $headline));
$adminTheme->includeFile('_content-body.php', array('content' => &$content));
?>
</div>
</main>

View File

@@ -9,7 +9,7 @@ if(!defined("PROCESSWIRE")) die();
/** @var array $extras */
?>
<!-- FOOTER -->
<footer id='pw-footer' class='uk-margin'>
<div class='pw-container uk-container uk-container-expand'>
<div class='uk-grid' uk-grid>

View File

@@ -55,4 +55,3 @@ $scripts->append($themeUrl . "scripts/main.js?v=$version");
foreach($scripts as $file) {
echo "\n\t<script type='text/javascript' src='$file'></script>";
}
?>

View File

@@ -7,21 +7,21 @@
*
*/
if(!defined("PROCESSWIRE")) die();
/** @var Config $config */
/** @var AdminThemeUikit $adminTheme */
/** @var User $user */
/** @var Modules $modules */
/** @var Notices $notices */
/** @var Page $page */
/** @var Process $proc;ess */
/** @var Process $process */
/** @var Sanitizer $sanitizer */
/** @var WireInput $input */
/** @var Paths $urls */
/** @var string $layout */
/** @var Process $process */
if(!defined("PROCESSWIRE")) die();
$adminTheme->renderExtraMarkup('x'); // forces it to cache
if(!isset($content)) $content = '';
@@ -30,7 +30,7 @@ if(!isset($content)) $content = '';
/* this intentionally on a separate line */ ?>">
<head>
<?php
include(__DIR__ . '/_head.php');
$adminTheme->includeFile('_head.php', array('layout' => $layout));
echo $adminTheme->renderExtraMarkup('head');
?>
</head>
@@ -38,7 +38,7 @@ if(!isset($content)) $content = '';
<?php
if($layout == 'sidenav') {
include(__DIR__ . "/_sidenav-masthead.php");
$adminTheme->includeFile('_sidenav-masthead.php');
} else if($layout == 'sidenav-tree' || $layout == 'sidenav-tree-alt') {
// masthead not rendered in this frame
@@ -50,68 +50,30 @@ if(!isset($content)) $content = '';
echo $adminTheme->renderNotices($notices);
} else {
include(__DIR__ . "/_masthead.php");
$adminTheme->includeFile('_masthead.php');
}
?>
<!-- MAIN CONTENT -->
<main id='main' class='pw-container uk-container uk-container-expand uk-margin uk-margin-large-bottom'>
<div class='pw-content' id='content'>
<header id='pw-content-head'>
<?php if($layout != 'sidenav' && $layout != 'modal') echo $adminTheme->renderBreadcrumbs(); ?>
<div id='pw-content-head-buttons' class='uk-float-right uk-visible@s'>
<?php echo $adminTheme->renderAddNewButton(); ?>
</div>
<?php
$headline = $adminTheme->getHeadline();
$headlinePos = strpos($content, ">$headline</h1>");
if(!$adminTheme->isModal && ($headlinePos === false || $headlinePos < 500)) {
echo "<h1 id='pw-content-title' class='uk-margin-remove-top'>$headline</h1>";
}
?>
</header>
<div id='pw-content-body'>
<?php
echo $page->get('body');
echo $content;
echo $adminTheme->renderExtraMarkup('content');
?>
</div>
</div>
</main>
<?php
$headline = $adminTheme->getHeadline();
$headlinePos = strpos($content, "$headline</h1>");
if($headlinePos && $headlinePos > 500) $headline = '';
$adminTheme->includeFile('_content.php', array(
'headline' => $headline,
'content' => &$content,
'layout' => $layout
));
if(!$adminTheme->isModal) {
include(__DIR__ . '/_footer.php');
if($adminTheme->isLoggedIn && strpos($layout, 'sidenav') !== 0) include(__DIR__ . '/_offcanvas.php');
$adminTheme->includeFile('_footer.php');
if($adminTheme->isLoggedIn && strpos($layout, 'sidenav') !== 0) {
$adminTheme->includeFile('_offcanvas.php');
}
}
echo $adminTheme->renderExtraMarkup('body');
$adminTheme->includeFile('_body-scripts.php', array('layout' => $layout));
?>
<script>
<?php
if(strpos($layout, 'sidenav-tree') === 0) {
echo "if(typeof parent.isPresent != 'undefined'){";
if(strpos($process, 'ProcessPageList') === 0) {
echo "parent.hideTreePane();";
} else {
echo "if(!parent.isMobileWidth() && parent.treePaneHidden()) parent.showTreePane();";
}
if($process == 'ProcessPageEdit' && ($input->get('s') || $input->get('new'))) {
echo "parent.refreshTreePane(" . ((int) $input->get('id')) . ");";
}
echo "}";
}
?>
ProcessWireAdminTheme.init();
</script>
</body>
</html>
</html><?php

View File

@@ -53,7 +53,7 @@ $logoOptions = array('height' => '40px');
</li>
</ul>
<?php include(__DIR__ . '/_search-form.php'); ?>
<?php $adminTheme->includeFile('_search-form.php'); ?>
</div>
<?php endif; // loggedin ?>

View File

@@ -22,7 +22,7 @@ if(!defined("PROCESSWIRE")) die();
</a>
<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'); ?>
<?php $adminTheme->includeFile('_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;'>
<?php echo $adminTheme->renderSidebarNavItems(); ?>
</ul>

View File

@@ -5,24 +5,24 @@ if(!defined("PROCESSWIRE")) die();
/** @var Paths $urls */
/** @var AdminThemeUikit $adminTheme */
$searchURL = $urls->admin . 'page/search/live/';
$helpTerm = $adminTheme->getLabel('search-help'); // Localized term to type for help (3+ chars)
$helpNote = $adminTheme->getLabel('search-tip');
if($adminTheme->isEditor): ?>
<form class='pw-search-form' data-action='<?php echo $searchURL; ?>' action='<?php echo $searchURL; ?>' method='get'>
<div class='uk-inline'>
<span class='uk-form-icon'>
<span class='pw-search-icon'>
<?php echo $adminTheme->renderIcon('search'); ?>
if($adminTheme->isEditor):
$searchURL = $urls->admin . 'page/search/live/';
$helpTerm = $adminTheme->getLabel('search-help'); // Localized term to type for help (3+ chars)
$helpNote = $adminTheme->getLabel('search-tip');
?>
<form class='pw-search-form' data-action='<?php echo $searchURL; ?>' action='<?php echo $searchURL; ?>' method='get'>
<div class='uk-inline'>
<span class='uk-form-icon'>
<span class='pw-search-icon'>
<?php echo $adminTheme->renderIcon('search'); ?>
</span>
<span class='pw-spinner-icon uk-hidden'>
<?php echo $adminTheme->renderIcon('spinner fa-spin'); ?>
</span>
</span>
<span class='pw-spinner-icon uk-hidden'>
<?php echo $adminTheme->renderIcon('spinner fa-spin'); ?>
</span>
</span>
<input type='text' class='pw-search-input uk-input uk-form-width-medium' name='q' data-help-term='<?php echo $helpTerm;?>' data-help-note='<?php echo $helpNote;?>'>
</div>
<input class='uk-hidden' type='submit' name='search' value='Search' />
<input type='hidden' name='show_options' value='1' />
</form>
<input type='text' class='pw-search-input uk-input uk-form-width-medium' name='q' data-help-term='<?php echo $helpTerm;?>' data-help-note='<?php echo $helpNote;?>'>
</div>
<input class='uk-hidden' type='submit' name='search' value='Search' />
<input type='hidden' name='show_options' value='1' />
</form>
<?php endif; ?>

View File

@@ -8,6 +8,7 @@ if(!defined("PROCESSWIRE")) die();
/** @var WireInput $input */
/** @var Sanitizer $sanitizer */
/** @var Page $page */
/** @var string $layout */
// whether or not page tree should be used for left sidebar
$treePaneLeft = $adminTheme->layout == 'sidenav-tree';
@@ -52,7 +53,7 @@ $panes = array(
<link rel="stylesheet" href="<?php echo $themeURL; ?>layout/source/stable/layout-default.css">
<?php require(__DIR__ . '/_head.php'); ?>
<?php $adminTheme->includeFile('_head.php', array('layout' => $layout)); ?>
<style type='text/css'>
html, body {
@@ -85,7 +86,7 @@ $panes = array(
<?php
if($treePane) {
echo "<div id='pw-admin-head'>";
include(__DIR__ . '/_masthead.php');
$adminTheme->includeFile('_masthead.php');
echo "</div>";
}
?>
@@ -94,7 +95,9 @@ $panes = array(
<?php
echo $panes['main'];
echo $treePane ? $panes['tree'] : $panes['side'] . $panes['tree'];
if($adminTheme->isLoggedIn) include(__DIR__ . '/_offcanvas.php');
if($adminTheme->isLoggedIn) {
$adminTheme->includeFile('_offcanvas.php');
}
?>
</div>

View File

@@ -69,7 +69,7 @@ $breadcrumbs = $adminTheme->renderBreadcrumbs();
</li>
</ul>
<?php include(__DIR__ . '/_search-form.php'); ?>
<?php $adminTheme->includeFile('_search-form.php'); ?>
</div>
<?php endif; // loggedin ?>

View File

@@ -24,7 +24,7 @@ if(!defined("PROCESSWIRE")) die();
<html class="pw pw-sidebar-frame" lang="<?php echo $adminTheme->_('en');
/* this intentionally on a separate line */ ?>">
<head>
<?php include(__DIR__ . '/_head.php'); ?>
<?php $adminTheme->includeFile('_head.php'); ?>
<style type='text/css'>
#pw-sidenav-bar .pw-search-form .uk-inline,
#pw-sidenav-bar .pw-search-input {

View File

@@ -8,6 +8,7 @@
/** @var Config $config */
/** @var AdminThemeUikit $adminTheme */
/** @var User $user */
/** @var string $layout */
if(!defined("PROCESSWIRE")) die();
@@ -17,7 +18,7 @@ if(!isset($content)) $content = '';
<html class="pw pw-sidebar-frame" lang="<?php echo $adminTheme->_('en');
/* this intentionally on a separate line */ ?>">
<head>
<?php include(__DIR__ . '/_head.php'); ?>
<?php $adminTheme->includeFile('_head.php', array('layout' => $layout)); ?>
<script>
var pageListRefresh = {
refreshPage: function(id) {

View File

@@ -0,0 +1,38 @@
<?php namespace ProcessWire;
/**
* default.php: Main control file for AdminThemeUikit
*
* FileCompiler=0
*
*/
/** @var Config $config */
/** @var AdminThemeUikit $adminTheme */
/** @var User $user */
/** @var Modules $modules */
/** @var Notices $notices */
/** @var Page $page */
/** @var Process $process */
/** @var Sanitizer $sanitizer */
/** @var WireInput $input */
/** @var Paths $urls */
/** @var string $content */
/** @var string $layout */
if(!defined("PROCESSWIRE")) die();
if($layout === 'sidenav-init' || $layout === 'sidenav-tree-init') {
// sidenav main loader
include(__DIR__ . '/_sidenav-init.php');
} else if($layout === 'sidenav-side') {
// sidenav sidebar pane
$adminTheme->addBodyClass("pw-layout-sidenav-side");
include(__DIR__ . '/_sidenav-side.php');
} else if($layout === 'sidenav-tree') {
// sidenav tree pane
$adminTheme->addBodyClass("pw-layout-sidenav-tree");
include(__DIR__ . '/_sidenav-tree.php');
}

View File

@@ -7,6 +7,8 @@
*
*/
if(!defined("PROCESSWIRE")) die();
/** @var Config $config */
/** @var AdminThemeUikit $adminTheme */
/** @var User $user */
@@ -17,8 +19,7 @@
/** @var Sanitizer $sanitizer */
/** @var WireInput $input */
/** @var Paths $urls */
if(!defined("PROCESSWIRE")) die();
/** @var string $content */
if($adminTheme->isModal) {
$layout = 'modal';
@@ -28,28 +29,19 @@ if($adminTheme->isModal) {
$layout = '';
}
if($layout === 'sidenav-init' || $layout === 'sidenav-tree-init') {
// sidenav main loader
include(__DIR__ . "/_sidenav-init.php");
} else if($layout === 'sidenav-side') {
// sidenav sidebar pane
$adminTheme->addBodyClass("pw-layout-sidenav-side");
include(__DIR__ . "/_sidenav-side.php");
$content .= $adminTheme->renderExtraMarkup('content');
$vars = array('layout' => $layout, 'content' => &$content);
} else if($layout === 'sidenav-tree') {
// sidenav tree pane
$adminTheme->addBodyClass("pw-layout-sidenav-tree");
include(__DIR__ . "/_sidenav-tree.php");
if(strpos($layout, 'sidenav') === 0 && $layout != 'sidenav-main') {
include(__DIR__ . '/_sidenav/default.php');
} else {
// main markup file
if($user->isLoggedin() && $adminTheme->layout && !$adminTheme->isModal) {
$layout = $adminTheme->layout;
$adminTheme->addBodyClass("pw-layout-$layout");
$vars['layout'] = $adminTheme->layout;
$adminTheme->addBodyClass("pw-layout-$vars[layout]");
} else if($layout != 'modal') {
$layout = '';
$vars['layout'] = '';
}
include(__DIR__ . "/_main.php");
$adminTheme->includeFile('_main.php', $vars);
}