Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
334 lines (265 sloc) 11.8 KB
<?php
/**
* ProcessWire PrevNextTabs
*
* Add Previous and Next Page Links
*
* Portions of this module based on Page References Tab written by Niklas Lakanen
*
*/
class PrevNextTabs extends WireData implements Module, ConfigurableModule {
/**
* @var Page Page being edited
*
*/
private $editedPage;
/**
* Return information about this module (required)
*
* @return array
*
*/
static public function getModuleInfo() {
return array(
'title' => 'Prev/Next Tabs',
'summary' => 'Adds prev/next links (tabs) to page editor.',
'version' => '014',
'author' => 'Macrura',
'autoload' => true
);
}
protected static $configDefaults = array(
'enabledTemplates' => [],
'uikit_location' => 'tabs',
'reno_location' => 'tabs',
);
/**
* Data as used by the get/set functions
*
*/
protected $data = array();
/**
* __construct() is the right place to init config vars before they'll get populated
*
*/
public function __construct() {
$configDefaults = self::$configDefaults;
foreach($configDefaults as $key => $value) {
$this->set($key, $value);
}
}
/**
* ready() is called when both PW's API is ready and $page object is initialized (for autoload modules!)
* Add the hook here to be able to skip it based on the template of the edited page.
*
*/
public function ready() {
// we're interested in page editor only
if(wire('page')->process != 'ProcessPageEdit') return;
// skip changing templates (only target the actual edit form)
$id = (int)$this->input->get('id');
if(!$id) return;
// wire('page') would be the page with ProcessPageEdit
// GET parameter id tells the page that's being edited
$this->editedPage = wire('pages')->get($id);
// don't even consider system templates
if($this->editedPage->template->flags & Template::flagSystem) return;
// if there's only the default admin theme, $user->admin_theme is not available
$this->adminTheme = $this->user->admin_theme ? $this->user->admin_theme : $this->config->defaultAdminTheme;
// hook only if
// 1) no templates have been chosen (=all enabled) OR
// 2) the template of the edited page has been chosen
if(count($this->enabledTemplates) == 0 or
in_array($this->editedPage->template->name, $this->enabledTemplates)) {
$hookTabs = true;
if($this->adminTheme == 'AdminThemeUikit' && $this->uikit_location == 'top') {
$hookTabs = false;
$this->addAssets();
$this->addHookAfter('AdminThemeUikit::renderBreadcrumbs', $this, 'hookAddPrevNextBC');
}
if($this->adminTheme == 'AdminThemeReno' && $this->reno_location == 'top') {
$hookTabs = false;
$this->addAssets();
$this->addHookAfter('Page::render', $this, 'hookAddPrevNextBCReno', array('priority'=>1000));
}
if($hookTabs) {
$this->addHookAfter('ProcessPageEdit::getTabs', $this, 'hookAddPrevNext');
}
}
}
public function addAssets() {
$this->config->styles->add($this->config->urls->siteModules . __CLASS__ . '/' . __CLASS__ . ".css?v=" . time());
$this->config->scripts->add($this->config->urls->siteModules . __CLASS__ . '/' . __CLASS__ . ".js?v=" . time());
}
/**
* Standard Addition of Prev/Next Links to the WireTabs
* @param HookEvent $event [The array of tabs for the page]
* @return [array] [Tabs with the added links]
*/
public function hookAddPrevNext(HookEvent $event) {
$query = 'include=all, sort=' . $this->editedPage->parent->sortfield . ', parent='.$this->editedPage->parent;
$next = $this->editedPage->next($query);
$prev = $this->editedPage->prev($query);
if (!$next->id && !$prev->id) return;
// add styles & init tooltip only if the links are to show
$this->config->styles->add($this->config->urls->siteModules . __CLASS__ . '/' . __CLASS__ . ".css?v=" . time());
$this->config->scripts->add($this->config->urls->siteModules . __CLASS__ . '/' . __CLASS__ . ".js?v=" . time());
$tabs = $event->return;
$event->replace = true;
$pnTabs = array();
if ($next->id) {
$label = $this->_('Next');
$id = $this->className() . 'Next';
$url = $next->editUrl;
$title = wire('sanitizer')->entities($next->title);
$a = "<a id='_ProcessPageEditNext' target='_top' href='$url' title='$title' data-action='this'>$label <i class='fa fa-angle-double-right'></i></a>";
$pnTabs[$id] = $a;
}
if ($prev->id) {
$label = $this->_('Prev');
$id = $this->className() . 'Prev';
$url = $prev->editUrl;
$title = wire('sanitizer')->entities($prev->title);
$class = $next->id ? ' class="space-right"' : '';
$a = "<a id='_ProcessPageEditPrev' target='_top' href='$url' title='$title' data-action='this'{$class}><i class='fa fa-angle-double-left'></i> $label</a>";
$pnTabs[$id] = $a;
}
if($this->wire('user')->admin_theme == 'AdminThemeUikit') {
$pnTabs = array_reverse($pnTabs);
}
$tabs = array_merge($tabs,$pnTabs);
$event->return = $tabs;
}
/**
* Add Prev/Next Links (Pagination) for Ui Kit
* This hooks into the breadcrumbs, sets up a 4/4 grid and places the breadcrumbs in the
* left 3/4 and the pagination links in the right 1/4
* @param HookEvent $event [UiKit Breadcrumbs]
* @return [string] [Markup for the breadcrumbs and prev/next pagination]
*/
public function hookAddPrevNextBC(HookEvent $event) {
$query = 'include=all, sort=' . $this->editedPage->parent->sortfield . ', parent='.$this->editedPage->parent;
$next = $this->editedPage->next($query);
$prev = $this->editedPage->prev($query);
$first = $this->editedPage->parent->children('include=all')->first();
$last = $this->editedPage->parent->children('include=all')->last();
if (!$next->id && !$prev->id) return;
$pnLinks = array();
if ($prev->id) {
$label = $this->_('Prev');
$url = $prev->editUrl;
$title = wire('sanitizer')->entities($prev->title);
$a = "<li class='uk-pagination-previous'><a href='$url' title='$title' accesskey='<'><i class='fa fa-angle-left'></i> <span>$label</span></a></li>";
$pnLinks[0] = $a;
} else {
$label = $this->_('Last');
$url = $last->editUrl;
$title = wire('sanitizer')->entities($last->title);
$a = "<li class='uk-pagination-previous'><a href='$url' title='$title' accesskey='<'><i class='fa fa-angle-left'></i> <span>$label</span></a></li>";
$pnLinks[0] = $a;
}
if ($next->id) {
$label = $this->_('Next');
$url = $next->editUrl;
$title = wire('sanitizer')->entities($next->title);
$a = "<li class='uk-pagination-next'><a href='$url' title='$title' accesskey='>'><span>$label</span> <i class='fa fa-angle-right'></i></a></li>";
$pnLinks[1] = $a;
} else {
$label = $this->_('First');
$url = $first->editUrl;
$title = wire('sanitizer')->entities($first->title);
$a = "<li class='uk-pagination-next'><a href='$url' title='$title' accesskey='>'><span>$label</span> <i class='fa fa-angle-right'></i></a></li>";
$pnLinks[1] = $a;
}
$links = '<div class="uk-width-1-4 prev-next-links"><ul class="uk-pagination uk-float-right">' . implode($pnLinks) . '</ul></div>'; //
$event->return = '<div class="uk-grid uk-margin-bottom"><div class="uk-width-3-4">' . str_replace('</ul>', '</ul></div>' . $links, $event->return) . '</div>';
}
/**
* Add Prev/Next Links (Pagination) for Reno
* @param HookEvent $event [Page Render]
* @return [string] [Markup for the breadcrumbs and prev/next pagination]
*/
public function hookAddPrevNextBCReno(HookEvent $event) {
$query = 'include=all, sort=' . $this->editedPage->parent->sortfield . ', parent='.$this->editedPage->parent;
$next = $this->editedPage->next($query);
$prev = $this->editedPage->prev($query);
$first = $this->editedPage->parent->children('include=all')->first();
$last = $this->editedPage->parent->children('include=all')->last();
if (!$next->id && !$prev->id) return;
$pnLinks = array();
if ($prev->id) {
$label = $this->_('Prev');
$url = $prev->editUrl;
$title = wire('sanitizer')->entities($prev->title);
$a = "<li class='pagination-previous'><a href='$url' title='$title' accesskey='<'><i class='fa fa-angle-left'></i> <span>$label</span></a></li>";
$pnLinks[0] = $a;
} else {
$label = $this->_('Last');
$url = $last->editUrl;
$title = wire('sanitizer')->entities($last->title);
$a = "<li class='pagination-previous'><a href='$url' title='$title' accesskey='<'><i class='fa fa-angle-left'></i> <span>$label</span></a></li>";
$pnLinks[0] = $a;
}
if ($next->id) {
$label = $this->_('Next');
$url = $next->editUrl;
$title = wire('sanitizer')->entities($next->title);
$a = "<li class='pagination-next'><a href='$url' title='$title' accesskey='>'><span>$label</span> <i class='fa fa-angle-right'></i></a></li>";
$pnLinks[1] = $a;
} else {
$label = $this->_('First');
$url = $first->editUrl;
$title = wire('sanitizer')->entities($first->title);
$a = "<li class='pagination-next'><a href='$url' title='$title' accesskey='>'><span>$label</span> <i class='fa fa-angle-right'></i></a></li>";
$pnLinks[1] = $a;
}
$links = '<div class="prev-next-links"><ul class="pagination">' . implode($pnLinks) . '</ul></div>'; //
$event->return = str_replace('<div id="breadcrumbs">', $links . '<div id="breadcrumbs">', $event->return);
}
/**
* Return an InputfieldsWrapper of Inputfields used to configure the class
*
* @param array $data Array of config values indexed by field name
* @return InputfieldsWrapper
*
*/
public static function getModuleConfigInputfields(array $data) {
// not sure if this is needed...
// foreach(self::$configDefaults as $key => $value) {
// if(!isset($data[$key])||$data[$key]=="") $data[$key] = $value;
// }
$wrapper = new InputfieldWrapper();
$fieldEnabledTemplates = wire('modules')->get('InputfieldAsmSelect');
$fieldEnabledTemplates->attr('name+id', 'enabledTemplates');
$fieldEnabledTemplates->label = __('Enabled templates', __FILE__);
$fieldEnabledTemplates->description = __('"Prev/Next" tabs will only be shown for chosen templates. If no template is chosen, Prev/Next tabs will be shown for all templates.', __FILE__);
$fieldEnabledTemplates->attr('title', __('Enable template', __FILE__));
$fieldEnabledTemplates->setAsmSelectOption('sortable', false);
// populate with all available templates
foreach(wire('templates') as $t) {
// filter out system templates
if(!($t->flags & Template::flagSystem)) $fieldEnabledTemplates->addOption($t->name);
}
if(isset($data['enabledTemplates'])) $fieldEnabledTemplates->value = $data['enabledTemplates'];
$wrapper->add($fieldEnabledTemplates);
//--- UiKit Placement Preference ---//
$f = wire('modules')->get('InputfieldRadios');
$f->attr('name', __('uikit_location'));
$f->label = __('UiKit Placement');
if(!isset($data['uikit_location'])) $data['uikit_location'] = 'tabs';
$f->description = __('For users who are on the UiKit admin theme, you can have the pagination at the top instead of in the tabs.');
$f->addOption('top', __('Top – Right of Breadcrumbs'), ($data['uikit_location'] == 'top') ? array('selected'=>'selected') : null);
$f->addOption('tabs',__('In Page Tabs, Right Side (old skool)'), ($data['uikit_location'] == 'tabs') ? array('selected'=>'selected') : null );
$wrapper->add($f);
//--- Reno Placement Preference ---//
$f = wire('modules')->get('InputfieldRadios');
$f->attr('name', __('reno_location'));
$f->label = __('Reno Placement');
$f->description = __('For users who are on the Reno admin theme, you can have the pagination at the top instead of in the tabs.');
if(!isset($data['reno_location'])) $data['reno_location'] = 'tabs';
$f->addOption('top', __('Top – Right of Breadcrumbs'), ($data['reno_location'] == 'top') ? array('selected'=>'selected') : null);
$f->addOption('tabs',__('In Page Tabs, Right Side (old skool)'), ($data['reno_location'] == 'tabs') ? array('selected'=>'selected') : null);
$wrapper->add($f);
return $wrapper;
}
}