From fb650408362f0da6fe7c42c21e14111c68f43f63 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Thu, 28 Jun 2018 12:35:18 -0400 Subject: [PATCH] Improvements to ProcessPageType and some phpdoc improvements to ProcessRole and ProcessPageLister --- .../ProcessPageLister.module | 5 + .../ProcessPageType/ProcessPageType.module | 212 +++++++++++++++--- .../Process/ProcessRole/ProcessRole.module | 26 ++- 3 files changed, 213 insertions(+), 30 deletions(-) diff --git a/wire/modules/Process/ProcessPageLister/ProcessPageLister.module b/wire/modules/Process/ProcessPageLister/ProcessPageLister.module index 986c85f1..9fff7f79 100644 --- a/wire/modules/Process/ProcessPageLister/ProcessPageLister.module +++ b/wire/modules/Process/ProcessPageLister/ProcessPageLister.module @@ -67,6 +67,11 @@ * @method string getSelector($limit = null) * @method PageArray findResults($selector) * @method string executeReset() + * @method string executeEditBookmark() + * @method string executeViewport() ListerPro + * @method string executeConfig() ListerPro + * @method string executeActions() ListerPro + * @method string executeSave() ListerPro * * * @todo make system fields hookable for output like markupValue is for custom fields diff --git a/wire/modules/Process/ProcessPageType/ProcessPageType.module b/wire/modules/Process/ProcessPageType/ProcessPageType.module index 8bc6fe0d..a67c12be 100644 --- a/wire/modules/Process/ProcessPageType/ProcessPageType.module +++ b/wire/modules/Process/ProcessPageType/ProcessPageType.module @@ -8,8 +8,14 @@ * For more details about how Process modules work, please see: * /wire/core/Process.php * - * ProcessWire 3.x, Copyright 2016 by Ryan Cramer + * ProcessWire 3.x, Copyright 2018 by Ryan Cramer * https://processwire.com + * + * @property array $showFields Names of fields to show in the main list table (default=['name']) + * @property string $addLabel Translated "Add New" label + * @property string $jsonListLabel What to use for 'label' property in JSON nav data (default='name') + * + * @method string executeList() * */ @@ -31,13 +37,19 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi * */ protected $pages; - + + /** + * Predefined template for page type represented by this Process + * + * @var null|Template + * + */ protected $template = null; /** * ProcessPageEdit or ProcessPageAdd * - * @var Process|null + * @var WirePageEditor|ProcessPageEdit|WirePageEditor|null * */ protected $editor = null; @@ -45,7 +57,7 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi /** * Instance of ProcessPageLister * - * @var null|ProcessPageLister|ProcessPageListerPro + * @var null|ProcessPageLister or ProcessPageListerPro * */ protected $lister = null; @@ -58,6 +70,7 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi $this->set('showFields', array('name')); $this->set('addLabel', $this->_('Add New')); $this->set('jsonListLabel', 'name'); // what to use for 'label' property in JSON nav data + parent::__construct(); } /** @@ -126,7 +139,7 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi } } - // Lister-specific methods + // Lister-specific methods, all mapped directly to Lister or ListerPro public function ___executeConfig() { return $this->getLister()->executeConfig(); } public function ___executeViewport() { return $this->getLister()->executeViewport(); } public function ___executeReset() { return $this->getLister()->executeReset(); } @@ -134,10 +147,22 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi public function ___executeSave() { return $this->getLister()->executeSave(); } public function ___executeEditBookmark() { return $this->getLister()->executeEditBookmark(); } + /** + * Main execution method, delegated to listing items in this page type + * + * @return string + * + */ public function ___execute() { return $this->executeList(); } + /** + * List items in this page type + * + * @return string + * + */ public function ___executeList() { $templateID = (int) $this->wire('input')->get('templates_id'); if(!$templateID) $templateID = (int) $this->wire('session')->get($this->className() . 'TemplatesID'); @@ -147,6 +172,9 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi /** * Output JSON list of navigation items for this (intended to for ajax use) + * + * @param array $options + * @return string|array * */ public function ___executeNavJSON(array $options = array()) { @@ -177,7 +205,7 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi * Get an instanceof ProcessPageLister or null if not applicable * * @param string $selector - * @return ProcessPageLister|ProcessPageListerPro|null + * @return ProcessPageLister|null * */ public function getLister($selector = '') { @@ -242,34 +270,68 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi return $settings; } - + + /** + * Get the page editor + * + * @param string $moduleName One of 'ProcessPageEdit' or 'ProcessPageAdd' (or other that extends) + * @return ProcessPageEdit|ProcessPageAdd|WirePageEditor + * @throws WireException If requested editor moduleName not found + * + */ protected function getEditor($moduleName) { - if($this->editor && $this->editor->className() == $moduleName) return $this->editor; + if($this->editor && $this->editor->className() == $moduleName) { + return $this->editor; + } $this->editor = $this->modules->get($moduleName); - $this->editor->setEditor($this); // set us as the parent editor - if($this->pages instanceof PagesType) { - $templates = $this->pages->getTemplates(); - $parents = $this->pages->getParentIDs(); - $this->editor->setPredefinedTemplates($templates); - $this->editor->setPredefinedParents($this->wire('pages')->getById($parents)); + if(!$this->editor) { + throw new WireException("Unable to load editor: $moduleName"); + } + if(wireInstanceOf($this->editor, array('ProcessPageEdit', 'ProcessPageAdd'))) { + $this->editor->setEditor($this); // set us as the parent editor + if($this->pages instanceof PagesType) { + $templates = $this->pages->getTemplates(); + $parents = $this->pages->getParentIDs(); + $this->editor->setPredefinedTemplates($templates); + $this->editor->setPredefinedParents($this->wire('pages')->getById($parents)); + } } return $this->editor; } - + /** + * Edit item of this page type + * + * @return string + * + */ public function ___executeEdit() { - $this->wire('breadcrumbs')->add(new Breadcrumb('../', $this->page->get('title|name'))); + + $pageTitle = $this->page->get('title|name'); + $this->breadcrumb('../', $pageTitle); $editor = $this->getEditor('ProcessPageEdit'); $urlSegment = ucfirst($this->wire('input')->urlSegment2); - if(method_exists($editor, "___execute$urlSegment") || method_exists($editor, "execute$urlSegment")) { + $editPage = $this->getPage(); + $this->browserTitle("$pageTitle > " . $editPage->name); + + if($urlSegment && (method_exists($editor, "___execute$urlSegment") || method_exists($editor, "execute$urlSegment"))) { // i.e. executeTemplate() and executeSaveTemplate() return $editor->{"execute$urlSegment"}(); + } else { + // regular edit + return $editor->execute(); } - return $editor->execute(); } + /** + * Add item of this page type + * + * @return string + * + */ public function ___executeAdd() { - $this->wire('breadcrumbs')->add(new Breadcrumb('../', $this->page->get('title|name'))); + $pageTitle = $this->page->get('title|name'); + $this->breadcrumb('../', $pageTitle); $editor = $this->getEditor("ProcessPageAdd"); $editor->template = $this->template; try { @@ -278,28 +340,69 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi $out = ''; $this->error($e->getMessage()); } + $this->browserTitle("$pageTitle > $this->addLabel"); return $out; } - + + /** + * Execute the "change template" action delegated to ProcessPageEdit + * + * @return string + * + */ public function ___executeTemplate() { $editor = $this->getEditor('ProcessPageEdit'); return $editor->executeTemplate(); } - + + /** + * Execute saving changes of the "change template" action delegated to ProcessPageEdit + * + * @return string + * + */ public function ___executeSaveTemplate() { $editor = $this->getEditor('ProcessPageEdit'); return $editor->executeSaveTemplate(); } + /** + * Render Lister output of pages + * + * This is used as an alternative to the built-in item list when Lister/ListerPro is available. + * + * @param string $selector Selector string for pages + * @param array $pagerOptions Not currently used by Lister + * @return string + * @throws WireException + * + */ protected function renderLister($selector = '', $pagerOptions = array()) { + if($pagerOptions) {} // ignore $lister = $this->getLister($selector); if(!$lister) throw new WireException("Lister not available"); return $lister->execute(); } + /** + * Render page list + * + * When Lister/ListerPro is available, this will delegate to the renderLister() method instead. + * When not available, it will render the list itself. + * + * @param string $selector Selector string for pages + * @param array $pagerOptions + * + * @return string + * + */ protected function renderList($selector = '', $pagerOptions = array()) { - if($this->lister && $this->useLister()) return $this->renderLister($selector, $pagerOptions); + if($this->lister && $this->useLister()) { + // delegate to Lister/ListerPro when available + return $this->renderLister($selector, $pagerOptions); + } + $out = ''; if(!$this->pages instanceof PagesType || count($this->pages->getTemplates()) != 1) { @@ -307,6 +410,7 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi $out = $form->render(); } + /** @var MarkupAdminDataTable $table */ $table = $this->modules->get("MarkupAdminDataTable"); $table->setEncodeEntities(false); $fieldNames = $this->showFields; @@ -352,6 +456,7 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi if($this->wire('page')->addable()) $table->action(array($this->addLabel => 'add/')); if($pages->getTotal() > count($pages)) { + /** @var MarkupPagerNav $pager */ $pager = $this->modules->get("MarkupPagerNav"); $out .= $pager->render($pages, $pagerOptions); } @@ -363,18 +468,45 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi return $out; } + /** + * Render an empty page list + * + * @param PageArray $pages + * @return string + * + */ protected function renderEmptyList(PageArray $pages) { + if($pages) {} // ignore $out = "

" . $this->_('No items to display yet.') . "

"; return $out; } + /** + * Return a value for output in list table + * + * Only used if Lister/ListerPro is not available. + * + * @param string $name Name of property + * @param mixed $value Value of property + * @return string + * + */ protected function renderListFieldValue($name, $value) { - + if($name) {} // ignore if(is_string($value) || is_int($value)) return htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); if(is_array($value)) return htmlspecialchars(print_r($value, true), ENT_QUOTES, 'UTF-8'); if(is_object($value)) { - - if($value instanceof WireArray) { + if($value instanceof PageArray) { + $item = $value->first(); + if($item && $item->title) { + $out = $value->implode("\n", '{title} (~{name}~)'); + $out = nl2br($this->wire('sanitizer')->entities1($out)); + $out = str_replace(array('(~', '~)'), array('(', ')'), $out); + } else { + $out = $value->implode("\n", 'name'); + } + return $out; + } else if($value instanceof WireArray) { $out = ''; foreach($value as $k => $v) { $out .= $v->name . ", "; @@ -386,17 +518,26 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi return (string) $value; } } - return ''; } + /** + * Get the filter-by-template form + * + * Only used if Lister/ListerPro is not available. + * + * @return InputfieldForm + * + */ protected function getTemplateFilterForm() { + /** @var InputfieldForm $form */ $form = $this->modules->get("InputfieldForm"); $form->attr('id', 'template_filter_form'); $form->attr('method', 'get'); $form->attr('action', './list'); + /** @var InputfieldSelect $field */ $field = $this->modules->get("InputfieldSelect"); $field->attr('id+name', 'templates_id'); $field->label = $this->_('Filter by Template'); @@ -425,13 +566,22 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi return $form; } + /** + * Module config + * + * @param array $data + * @return InputfieldWrapper + * + */ public function getModuleConfigInputfields(array $data) { $showFields = isset($data['showFields']) ? $data['showFields'] : array(); $fields = array('name'); foreach($this->wire('fields') as $field) $fields[] = $field->name; - + + /** @var InputfieldWrapper $inputfields */ $inputfields = $this->wire(new InputfieldWrapper()); + /** @var InputfieldAsmSelect $f */ $f = $this->wire('modules')->get('InputfieldAsmSelect'); $f->label = $this->_("What fields should be displayed in the page listing?"); $f->attr('id+name', 'showFields'); @@ -441,7 +591,13 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi return $inputfields; } - + + /** + * Get page being edited (for WirePageEditor interface) + * + * @return NullPage|Page + * + */ public function getPage() { if($this->editor) return $this->editor->getPage(); return $this->wire('pages')->newNullPage(); diff --git a/wire/modules/Process/ProcessRole/ProcessRole.module b/wire/modules/Process/ProcessRole/ProcessRole.module index b3acbdc9..aee8e7c9 100644 --- a/wire/modules/Process/ProcessRole/ProcessRole.module +++ b/wire/modules/Process/ProcessRole/ProcessRole.module @@ -6,7 +6,7 @@ * For more details about how Process modules work, please see: * /wire/core/Process.php * - * ProcessWire 3.x, Copyright 2016 by Ryan Cramer + * ProcessWire 3.x, Copyright 2018 by Ryan Cramer * https://processwire.com * */ @@ -24,12 +24,34 @@ class ProcessRole extends ProcessPageType { 'useNavJSON' => true, ); } - + + /** + * Array of [ 'icon-name' => 'icon markup' ] + * + * @var array + * + */ protected $icons = array(); + + /** + * Array of [ 'permission-name' => 'Additional notes for permission' ] + * + * @var array + * + */ protected $templatePermissionNotes = array(); + + /** + * Array of [ 'permission-name' => 'Description of permission' ] + * + * @var array + * + */ protected $templatePermissionDescriptions = array(); /** + * Role object for guest role + * * @var Role * */