diff --git a/wire/modules/Fieldtype/FieldtypePageTable.module b/wire/modules/Fieldtype/FieldtypePageTable.module index fd80290e..49f425f7 100644 --- a/wire/modules/Fieldtype/FieldtypePageTable.module +++ b/wire/modules/Fieldtype/FieldtypePageTable.module @@ -7,7 +7,7 @@ * Code by Ryan Cramer * Sponsored by Avoine * - * ProcessWire 3.x, Copyright 2019 by Ryan Cramer + * ProcessWire 3.x, Copyright 2023 by Ryan Cramer * https://processwire.com * */ @@ -21,7 +21,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { 'summary' => 'A fieldtype containing a group of editable pages.', 'installs' => 'InputfieldPageTable', 'autoload' => true, - ); + ); } /** @@ -29,13 +29,25 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function init() { - $pages = $this->wire('pages'); + $pages = $this->wire()->pages; $pages->addHookAfter('delete', $this, 'hookPagesDelete'); $pages->addHookAfter('deleteReady', $this, 'hookPagesDeleteReady'); $pages->addHookAfter('trashed', $this, 'hookPagesTrashed'); $pages->addHookAfter('unpublished', $this, 'hookPagesUnpublished'); $pages->addHookAfter('published', $this, 'hookPagesPublished'); $pages->addHookAfter('cloned', $this, 'hookPagesCloned'); + parent::init(); + } + + /** + * Get class name to use Field objects of this type (must be class that extends Field class) + * + * @param array $a Field data from DB (if needed) + * @return string Return class name or blank to use default Field class + * + */ + public function getFieldClass(array $a = array()) { + return 'PageTableField'; } /** @@ -47,12 +59,13 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function hookPagesDelete(HookEvent $event) { - $page = $event->arguments(0); - foreach($this->wire('fields') as $field) { + $database = $this->wire()->database; + $page = $event->arguments(0); /** @var Page $page */ + foreach($this->wire()->fields as $field) { if(!$field->type instanceof FieldtypePageTable) continue; - $table = $this->wire('database')->escapeTable($field->table); + $table = $database->escapeTable($field->table); $sql = "DELETE FROM `$table` WHERE pages_id=:pages_id OR data=:data"; - $query = $this->wire('database')->prepare($sql); + $query = $database->prepare($sql); $query->bindValue(':pages_id', (int) $page->id); $query->bindValue(':data', (int) $page->id); $query->execute(); @@ -70,8 +83,12 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function hookPagesDeleteReady(HookEvent $event) { - $page = $event->arguments(0); + + $pages = $this->wire()->pages; + $page = $event->arguments(0); /** @var Page $page */ + foreach($page->template->fieldgroup as $field) { + /** @var PageTableField $field */ if(!$field->type instanceof FieldtypePageTable) continue; if(is_null($field->trashOnDelete) && !is_null($field->autoTrash)) $field->trashOnDelete = $field->autoTrash; if(!$field->parent_id || !$field->trashOnDelete) continue; @@ -81,18 +98,18 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { /** @var Page $item */ $deleted = false; if($field->trashOnDelete == 2) { - $this->wire('pages')->message("Auto Delete PageTable Item: $item->url", Notice::debug); + $pages->message("Auto Delete PageTable Item: $item->url", Notice::debug); try { - $this->wire('pages')->delete($item); + $pages->delete($item); $deleted = true; } catch(\Exception $e) { - $this->wire('pages')->error($e->getMessage(), Notice::debug); + $pages->error($e->getMessage(), Notice::debug); } } if(!$deleted) { if($item->isTrash()) continue; - $this->wire('pages')->message("Auto Trash PageTable Item: $item->url", Notice::debug); - $this->wire('pages')->trash($item); + $pages->message("Auto Trash PageTable Item: $item->url", Notice::debug); + $pages->trash($item); } } } @@ -105,15 +122,19 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function hookPagesTrashed(HookEvent $event) { - $page = $event->arguments(0); + + $pages = $this->wire()->pages; + $page = $event->arguments(0); /** @var Page $page */ + foreach($page->template->fieldgroup as $field) { if(!$field->type instanceof FieldtypePageTable) continue; + /** @var PageTableField $field */ if(!$field->parent_id || !$field->unpubOnTrash) continue; $value = $page->getUnformatted($field->name); if(!wireCount($value)) continue; foreach($value as $item) { /** @var Page $item */ - $this->wire('pages')->message("Auto Unpublish PageTable Item: $item->url", Notice::debug); + $pages->message("Auto Unpublish PageTable Item: $item->url", Notice::debug); $of = $item->of(); $item->of(false); $item->addStatus(Page::statusUnpublished); @@ -130,10 +151,15 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function hookPagesUnpublished(HookEvent $event) { - $page = $event->arguments(0); - if($this->wire('pages')->cloning) return; + + $pages = $this->wire()->pages; + $page = $event->arguments(0); /** @var Page $page */ + + if($pages->cloning) return; + foreach($page->template->fieldgroup as $field) { if(!$field->type instanceof FieldtypePageTable) continue; + /** @var PageTableField $field */ if(!$field->parent_id || !$field->unpubOnUnpub) continue; $value = $page->getUnformatted($field->name); if(!wireCount($value)) continue; @@ -142,10 +168,10 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $of = $item->of(); $item->of(false); if($field->unpubOnUnpub == 2) { - $this->wire('pages')->message("Auto Hide PageTable Item: $item->url", Notice::debug); + $pages->message("Auto Hide PageTable Item: $item->url", Notice::debug); $item->addStatus(Page::statusHidden); } else { - $this->wire('pages')->message("Auto Unpublish PageTable Item: $item->url", Notice::debug); + $pages->message("Auto Unpublish PageTable Item: $item->url", Notice::debug); $item->addStatus(Page::statusUnpublished); } $item->save(); @@ -161,9 +187,13 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function hookPagesPublished(HookEvent $event) { + + $pages = $this->wire()->pages; $page = $event->arguments(0); + foreach($page->template->fieldgroup as $field) { if(!$field->type instanceof FieldtypePageTable) continue; + /** @var PageTableField $field */ if(!$field->parent_id || $field->unpubOnUnpub != 2) continue; $value = $page->getUnformatted($field->name); if(!wireCount($value)) continue; @@ -172,7 +202,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { if(!$item->hasStatus(Page::statusHidden)) continue; $of = $item->of(); $item->of(false); - $this->wire('pages')->message("Auto Un-hide PageTable Item: $item->url", Notice::debug); + $pages->message("Auto Un-hide PageTable Item: $item->url", Notice::debug); $item->removeStatus(Page::statusHidden); $item->save(); $item->of($of); @@ -193,8 +223,9 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { static $clonedIDs = array(); - $page = $event->arguments(0); - $copy = $event->arguments(1); + $pages = $this->wire()->pages; + $page = $event->arguments(0); /** @var Page $page */ + $copy = $event->arguments(1); /** @var Page $copy */ if($page) {} // ignore @@ -203,27 +234,28 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { foreach($copy->template->fieldgroup as $field) { if(!$field->type instanceof FieldtypePageTable) continue; + /** @var PageTableField $field */ //if(!$field->parent_id) continue; // let that be handled manually since recursive clones are already an option - $parent = $field->parent_id ? $this->wire('pages')->get($field->parent_id) : $copy; + $parent = $field->parent_id ? $pages->get($field->parent_id) : $copy; $value = $copy->getUnformatted($field->name); if(!wireCount($value)) continue; - $newValue = $this->wire('pages')->newPageArray(); + $newValue = $pages->newPageArray(); foreach($value as $item) { try { $newItem = null; if(!$field->parent_id && $copy->numChildren) { // value was already cloned by API with recursive option? - $newItem = $this->wire('pages')->get("parent=$copy, name=$item->name, include=all"); + $newItem = $pages->get("parent=$copy, name=$item->name, include=all"); if(!$newItem->id) $newItem = null; } - if(!$newItem) $newItem = $this->wire('pages')->clone($item, $parent); + if(!$newItem) $newItem = $pages->clone($item, $parent); if($newItem->id) { $newValue->add($newItem); - $this->wire('pages')->message("Cloned item $item->path", Notice::debug); + $pages->message("Cloned item $item->path", Notice::debug); } } catch(\Exception $e) { - $this->wire('pages')->error("Error cloning $item->path"); - $this->wire('pages')->error($e->getMessage(), Notice::debug); + $pages->error("Error cloning $item->path"); + $pages->error($e->getMessage(), Notice::debug); } } $copy->set($field->name, $newValue); @@ -238,12 +270,13 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function ready() { - if( $this->wire('config')->ajax && - $this->wire('input')->get('InputfieldPageTableField') && - $this->wire('user')->isLoggedin() && - $this->wire('page')->template == 'admin') { + $config = $this->wire()->config; + if( $config->ajax && + $this->wire()->input->get('InputfieldPageTableField') && + $this->wire()->user->isLoggedin() && + $this->wire()->page->template->name === 'admin') { // handle ajax request to render table - require_once($this->wire('config')->paths->InputfieldPageTable . 'InputfieldPageTableAjax.php'); + require_once($config->paths('InputfieldPageTable') . 'InputfieldPageTableAjax.php'); new InputfieldPageTableAjax(); } } @@ -275,14 +308,14 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function getMatchQuery($query, $table, $subfield, $operator, $value) { - return $this->wire('modules')->get('FieldtypePage')->getMatchQuery($query, $table, $subfield, $operator, $value); + return $this->wire()->fieldtypes->FieldtypePage->getMatchQuery($query, $table, $subfield, $operator, $value); } /** * Get the Inputfield used for input by PageTable * * @param Page $page - * @param Field $field + * @param Field|PageTableField $field * @return Inputfield * */ @@ -307,12 +340,16 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * @param Page $page * @param Field $field * @param int|object|string|WireArray $value - * @return int|object|PageArray|string|WireArray + * @return PageArray * */ public function sanitizeValue(Page $page, Field $field, $value) { - if(is_array($value) && wireCount($value)) $value = $this->wakeupValue($page, $field, $value); - if(!$value instanceof PageArray) return $this->wire('pages')->newPageArray(); + if(is_array($value) && wireCount($value)) { + $value = $this->wakeupValue($page, $field, $value); + } + if(!$value instanceof PageArray) { + return $this->wire()->pages->newPageArray(); + } foreach($value as $item) { if($this->isValidItem($page, $field, $item)) continue; $value->remove($item); @@ -324,13 +361,12 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * Return true or false as to whether the item is valid for this PageTable * * @param Page $page - * @param Field $field + * @param Field|PageTableField $field * @param Page $item * @return bool * */ protected function isValidItem(Page $page, Field $field, Page $item) { - if($page) {} // ignore $template_id = $field->get('template_id'); if(is_array($template_id)) { if(in_array($item->template->id, $template_id)) return true; @@ -350,7 +386,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function getBlankValue(Page $page, Field $field) { - return $this->wire('pages')->newPageArray(); + return $this->wire()->pages->newPageArray(); } /** @@ -363,7 +399,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function ___formatValue(Page $page, Field $field, $value) { - $formatted = $this->wire('pages')->newPageArray(); + $formatted = $this->wire()->pages->newPageArray(); if(!$value instanceof PageArray) return $formatted; foreach($value as $item) { if($item->status >= Page::statusHidden) continue; @@ -377,7 +413,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * Prep a value for storage * * @param Page $page - * @param Field $field + * @param Field|PageTableField $field * @param PageArray $value * @throws WireException * @return array @@ -385,9 +421,15 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { */ public function ___sleepValue(Page $page, Field $field, $value) { $sleepValue = array(); - if(!$value instanceof PageArray) return $sleepValue; - if($field->get('sortfields')) $value->sort($field->get('sortfields')); - if($value->data('notSaveable')) throw new WireException("Field '$field->name' from page $page->id is not saveable because it is a formatted value."); + if(!$value instanceof PageArray) { + return $sleepValue; + } + if($field->get('sortfields')) { + $value->sort($field->get('sortfields')); + } + if($value->data('notSaveable')) { + throw new WireException("Field '$field->name' from page $page->id is not saveable because it is a formatted value."); + } foreach($value as $item) { if(!$item->id) continue; if(!$this->isValidItem($page, $field, $item)) continue; @@ -400,14 +442,16 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * Wake up a stored value * * @param Page $page - * @param Field $field + * @param Field|PageTableField $field * @param array $value * @return PageArray * */ public function ___wakeupValue(Page $page, Field $field, $value) { - if(!is_array($value) || !wireCount($value) || empty($field->template_id)) return $this->getBlankValue($page, $field); + if(!is_array($value) || !wireCount($value) || empty($field->template_id)) { + return $this->getBlankValue($page, $field); + } $template_id = $field->get('template_id'); @@ -416,7 +460,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { } if(wireCount($template_id) == 1) { - $template = $this->wire('templates')->get(reset($template_id)); + $template = $this->wire()->templates->get(reset($template_id)); } else { $template = null; } @@ -424,13 +468,14 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $loadOptions = array('cache' => false); if($template) $loadOptions['template'] = $template; - $items = $this->wire('pages')->getById($value, $loadOptions); + $items = $this->wire()->pages->getById($value, $loadOptions); + $sanitizer = $this->wire()->sanitizer; $sortfields = $field->get('sortfields'); if($sortfields) { $sorts = array(); foreach(explode(',', $sortfields) as $sortfield) { - $sorts[] = $this->wire('sanitizer')->name(trim($sortfield)); + $sorts[] = $sanitizer->name(trim($sortfield)); } if(wireCount($sorts)) $items->sort($sorts); } @@ -452,7 +497,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function ___getSelectorInfo(Field $field, array $data = array()) { - $info = $this->wire('modules')->get('FieldtypePage')->getSelectorInfo($field, $data); + $info = $this->wire()->fieldtypes->FieldtypePage->getSelectorInfo($field, $data); $info['operators'] = array(); // force it to be non selectable, subfields only return $info; } @@ -469,12 +514,13 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function ___exportConfigData(Field $field, array $data) { - $data = $this->wire('fieldtypes')->get('FieldtypePage')->exportConfigData($field, $data); + $data = $this->wire()->fieldtypes->FieldtypePage->exportConfigData($field, $data); if(isset($data['template_id']) && is_array($data['template_id'])) { // convert template IDs to names + $templates = $this->wire()->templates; $names = array(); foreach($data['template_id'] as $id) { - $template = $this->wire('templates')->get((int) $id); + $template = $templates->get((int) $id); if($template) $names[] = $template->name; } $data['template_id'] = $names; @@ -492,12 +538,15 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function ___importConfigData(Field $field, array $data) { + + $templates = $this->wire()->templates; $templateIDs = array(); + if(!empty($data['template_id'])) { if(!is_array($data['template_id'])) $data['template_id'] = array($data['template_id']); $errorTemplates = array(); foreach($data['template_id'] as $name) { - $template = $this->wire('templates')->get($name); + $template = $templates->get($name); if($template) { $templateIDs[] = $template->id; } else { @@ -509,8 +558,10 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $data['errors']['template_id'] = "Unable to find template(s): " . implode(', ', $errorTemplates); } } - $data = $this->wire('fieldtypes')->get('FieldtypePage')->importConfigData($field, $data); + + $data = $this->wire()->fieldtypes->FieldtypePage->importConfigData($field, $data); $data['template_id'] = $templateIDs; + return $data; } @@ -526,29 +577,43 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { * */ public function findOrphans(Page $page, Field $field) { - $orphans = $this->wire('pages')->newPageArray(); + $pages = $this->wire()->pages; + + $orphans = $pages->newPageArray(); if($field->get('parent_id')) return $orphans; + $templateID = $field->get('template_id'); if(!$templateID) return $orphans; // we need at least a template to do this + if(!is_array($templateID)) $templateID = array($templateID); + $value = $page->getUnformatted($field->name); - if(!$value instanceof PageArray) $value = $this->wire('pages')->newPageArray(); + if(!$value instanceof PageArray) $value = $pages->newPageArray(); + if($page->numChildren <= $value->count()) return $orphans; // nothing new + $templateNames = array(); + $templates = $this->wire()->templates; + foreach($templateID as $id) { - $template = $this->wire('templates')->get($id); + $template = $templates->get($id); if($template) $templateNames[] = $template->name; } + $selector = "include=unpublished, template=" . implode('|', $templateNames); if($value->count()) $selector .= ", id!=$value"; - foreach($page->children($selector) as $item) $orphans->add($item); + + foreach($page->children($selector) as $item) { + $orphans->add($item); + } + return $orphans; } /** * Return configuration fields definable for each FieldtypePage * - * @param Field $field + * @param Field|PageTableField $field * @return InputfieldWrapper * */ @@ -563,11 +628,10 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $inputfields = parent::___getConfigInputfields($field); - /** @var InputfieldAsmSelect $f */ - $f = $this->wire('modules')->get('InputfieldAsmSelect'); + $f = $inputfields->InputfieldAsmSelect; $f->attr('name', 'template_id'); $f->label = $this->_('Select one or more templates for items'); - foreach($this->wire('templates') as $template) { + foreach($this->wire()->templates as $template) { if($template->flags & Template::flagSystem) continue; $f->addOption($template->id, $template->name); } @@ -579,8 +643,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $f->notes = $this->_('Please hit Save after selecting a template and the remaining configuration on the Input tab will contain more context.'); // Templates selection notes $inputfields->add($f); - /** @var InputfieldPageListSelect $f */ - $f = $this->wire('modules')->get('InputfieldPageListSelect'); + $f = $inputfields->InputfieldPageListSelect; $f->attr('name', 'parent_id'); $f->label = $this->_('Select a parent for items'); $f->description = $this->_('All items created and managed from this field will live under the parent you select here.'); @@ -589,20 +652,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $f->attr('value', (int) $field->get('parent_id')); $inputfields->add($f); - /* - $f = $this->wire('modules')->get('InputfieldCheckbox'); - $f->attr('name', 'autoTrash'); - $f->attr('value', 1); - if($field->autoTrash) $f->attr('checked', 'checked'); - $f->label = $this->_('Trash items when page is deleted?'); - $f->description = $this->_('When checked, items created/managed by a given page will be automatically trashed when that page is deleted. If not checked, the items will remain under the parent you selected above.'); // autoTrash option description - $f->notes = $this->_('This option applies only if you have selected a parent above.'); - $f->collapsed = Inputfield::collapsedBlank; - $inputfields->add($f); - */ - - /** @var InputfieldFieldset $fieldset */ - $fieldset = $this->wire('modules')->get('InputfieldFieldset'); + $fieldset = $inputfields->InputfieldFieldset; $fieldset->label = $this->_('Page behaviors'); $fieldset->showIf = 'parent_id!=""'; $inputfields->add($fieldset); @@ -613,10 +663,9 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { 'delete' => $this->_('Delete them'), 'unpub' => $this->_('Unpublish them'), 'hide' => $this->_('Hide them'), - ); + ); - /** @var InputfieldRadios $f */ - $f = $this->wire('modules')->get('InputfieldRadios'); + $f = $inputfields->InputfieldRadios; $f->attr('name', 'trashOnDelete'); $f->label = $this->_('Delete'); $f->description = sprintf($this->_('What should happen to "%s" items when the containing page is permanently deleted?'), $field->name); @@ -626,8 +675,9 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $f->attr('value', (int) $field->get('trashOnDelete')); // aka autoTrash $f->columnWidth = 33; $fieldset->add($f); + unset($f); - $f = $this->wire('modules')->get('InputfieldRadios'); + $f = $inputfields->InputfieldRadios; $f->attr('name', 'unpubOnTrash'); $f->label = $this->_('Trash'); $f->description = sprintf($this->_('What should happen to "%s" items when the containing page is trashed?'), $field->name); @@ -636,8 +686,9 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $f->attr('value', (int) $field->get('unpubOnTrash')); $f->columnWidth = 33; $fieldset->add($f); + unset($f); - $f = $this->wire('modules')->get('InputfieldRadios'); + $f = $inputfields->InputfieldRadios; $f->attr('name', 'unpubOnUnpub'); $f->label = $this->_('Unpublish'); $f->description = sprintf($this->_('What should happen to "%s" items when the containing page is unpublished?'), $field->name); @@ -648,8 +699,7 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { $f->columnWidth = 33; $fieldset->add($f); - /** @var InputfieldText $f */ - $f = $this->wire('modules')->get('InputfieldText'); + $f = $inputfields->InputfieldText; $f->attr('name', 'sortfields'); $f->label = $this->_('Sort fields'); $f->description = $this->_('Enter the field name that you want your table to sort by. For a descending sort, precede the field name with a hyphen, i.e. "-date" rather than "date".'); // sort description 1 @@ -661,7 +711,6 @@ class FieldtypePageTable extends FieldtypeMulti implements Module { return $inputfields; } - - } +require_once(__DIR__ . '/PageTableField.php'); diff --git a/wire/modules/Fieldtype/PageTableField.php b/wire/modules/Fieldtype/PageTableField.php new file mode 100644 index 00000000..4ec7ada4 --- /dev/null +++ b/wire/modules/Fieldtype/PageTableField.php @@ -0,0 +1,26 @@ + __('Inputfield to accompany FieldtypePageTable', __FILE__), // Module Summary 'version' => 14, 'requires' => 'FieldtypePageTable' - ); + ); } /** @@ -103,14 +103,15 @@ class InputfieldPageTable extends Inputfield { 'parent' => $this->_x('Parent', 'th'), 'numChildren' => $this->_x('Children', 'th'), 'status' => $this->_x('Status', 'th'), - ); + ); parent::init(); } public function renderReady(Inputfield $parent = null, $renderValueMode = false) { $this->addClass('InputfieldNoFocus', 'wrapClass'); - $this->wire('modules')->get('JqueryUI')->use('modal'); + $jQueryUI = $this->wire()->modules->get('JqueryUI'); /** @var JqueryUI $jQueryUI */ + $jQueryUI->use('modal'); return parent::renderReady($parent, $renderValueMode); } @@ -121,6 +122,12 @@ class InputfieldPageTable extends Inputfield { * */ public function ___render() { + + $sanitizer = $this->wire()->sanitizer; + $modules = $this->wire()->modules; + $process = $this->wire()->process; + $config = $this->wire()->config; + $input = $this->wire()->input; // make sure we've got enough info to generate a table $errors = array(); @@ -131,6 +138,7 @@ class InputfieldPageTable extends Inputfield { // determine what columns we'll show in the table $columnsString = $this->columns ? $this->columns : $this->getConfigDefaultColumns(); $columns = array(); + foreach(explode("\n", $columnsString) as $column) { $width = 0; if(strpos($column, '=') !== false) list($column, $width) = explode('=', $column); @@ -143,38 +151,42 @@ class InputfieldPageTable extends Inputfield { $out = $this->renderTable($columns); if($this->renderValueMode) return $out; - $editID = (int) $this->wire('input')->get('id'); - if(!$editID && $this->wire('process') instanceof WirePageEditor) $editID = $this->wire('process')->getPage()->id; + $editID = (int) $input->get('id'); + if(!$editID && $process instanceof WirePageEditor) $editID = $process->getPage()->id; $parentID = $this->parent_id ? $this->parent_id : $editID; // render the 'Add New' buttons for each template $btn = ''; foreach($this->rowTemplates as $template) { /** @var Template $template */ - $button = $this->wire('modules')->get('InputfieldButton'); + /** @var InputfieldButton $button */ + $button = $modules->get('InputfieldButton'); $button->icon = 'plus-circle'; $button->value = count($this->rowTemplates) == 1 ? $this->_x('Add New', 'button') : $template->getLabel(); - $url = $this->wire('config')->urls->admin . "page/add/?modal=1&template_id=$template->id&parent_id=$parentID&context=PageTable"; - if($this->nameFormat) $url .= "&name_format=" . $this->wire('sanitizer')->entities($this->nameFormat); + $url = $config->urls->admin . "page/add/?modal=1&template_id=$template->id&parent_id=$parentID&context=PageTable"; + if($this->nameFormat) $url .= "&name_format=" . $sanitizer->entities($this->nameFormat); $btn .= "" . $button->render() . ""; } + if(count($this->rowTemplates) > 1) $btn = "$btn"; $out .= "
$btn
"; - if(!$this->wire('input')->get('InputfieldPageTableField')) { + if(!$input->get('InputfieldPageTableField')) { $url = "./?id=$editID&InputfieldPageTableField=$this->name"; $out = "
$out
"; // input for sorting purposes - $value = $this->wire('sanitizer')->entities($this->attr('value')); - $name = $this->wire('sanitizer')->entities($this->attr('name')); + $value = $sanitizer->entities($this->attr('value')); + $name = $sanitizer->entities($this->attr('name')); $out .= ""; $out .= ""; if($this->orphans && count($this->orphans)) { $out .= "

"; $out .= "" . $this->_('Children were found that may be added to this table. Check the box next to any you would like to add.') . " "; - if(count($this->orphans) > 1) $out .= "
" . $this->_('Select all') . " "; + if(count($this->orphans) > 1) { + $out .= "
" . $this->_('Select all') . " "; + } foreach($this->orphans as $item) { $label = $item->title; if(!strlen($label)) $label = $item->name; @@ -208,18 +220,19 @@ class InputfieldPageTable extends Inputfield { * */ protected function ___renderTable(array $columns) { + $fields = $this->wire()->fields; $this->needsEditColumn = false; /** @var PageArray $value */ $value = $this->attr('value'); - $this->wire('modules')->get('MarkupAdminDataTable'); // for styles + $this->wire()->modules->get('MarkupAdminDataTable'); // for styles if(!count($value)) return ''; // if nothing in the value, just return blank // $template = $this->template_id ? $this->wire('templates')->get((int) $this->template_id) : null; $template = count($this->rowTemplates) > 0 ? reset($this->rowTemplates) : null; - $fields = array(); - $labels = array(); + $fieldsByCol = array(); + $labelsByCol = array(); - // populate $fields and $labels + // populate $fieldsByCol and $labelsByCol foreach($columns as $column => $width) { $field = null; @@ -232,7 +245,7 @@ class InputfieldPageTable extends Inputfield { list($parentFieldName, $fieldName) = explode('.', $column); if($template) $parentField = $template->fieldgroup->getFieldContext($parentFieldName); - if(!$parentField) $parentField = $this->wire('fields')->get($parentFieldName); + if(!$parentField) $parentField = $fields->get($parentFieldName); if($parentField) { $label = $parentField->getLabel(); @@ -248,11 +261,11 @@ class InputfieldPageTable extends Inputfield { } if($template) $field = $template->fieldgroup->getFieldContext($fieldName); - if(!$field) $field = $this->wire('fields')->get($fieldName); + if(!$field) $field = $fields->get($fieldName); if($field) { $label .= $field->getLabel(); - $fields[$column] = $field; + $fieldsByCol[$column] = $field; } else if(isset($this->nativeLabels[$fieldName])) { $label .= $this->nativeLabels[$fieldName]; @@ -261,11 +274,11 @@ class InputfieldPageTable extends Inputfield { $label .= $column; } - $labels[$column] = $label; + $labelsByCol[$column] = $label; } - $out = $this->renderTableBody($value, $columns, $fields); // render order intentional - $out = $this->renderTableHead($columns, $labels) . $out; + $out = $this->renderTableBody($value, $columns, $fieldsByCol); // render order intentional + $out = $this->renderTableHead($columns, $labelsByCol) . $out; return $out; } @@ -281,7 +294,8 @@ class InputfieldPageTable extends Inputfield { protected function renderTableHead(array $columns, array $labels) { /** @var MarkupAdminDataTable $module */ - $module = $this->wire('modules')->get('MarkupAdminDataTable'); + $module = $this->wire()->modules->get('MarkupAdminDataTable'); + $sanitizer = $this->wire()->sanitizer; $classes = array(); foreach(array('class', 'addClass', 'responsiveClass', 'responsiveAltClass') as $key) { $value = $module->settings($key); @@ -296,7 +310,7 @@ class InputfieldPageTable extends Inputfield { foreach($columns as $column => $width) { $attr = $width ? " style='width: $width%'" : ''; $label = $labels[$column]; - $out .= "" . $this->wire('sanitizer')->entities($label) . ""; + $out .= "" . $sanitizer->entities($label) . ""; } if(!$this->renderValueMode) $out .= " "; @@ -411,12 +425,14 @@ class InputfieldPageTable extends Inputfield { $fieldName = $column; $subfieldName = ''; - if(strpos($column, '.') !== false) list($fieldName, $subfieldName) = explode('.', $column); + + if(strpos($column, '.') !== false) { + list($fieldName, $subfieldName) = explode('.', $column); + } if(isset($fields[$column])) { // custom - /** @var Field $field */ - $field = $fields[$column]; + $field = $fields[$column]; /** @var Field $field */ $v = $item->getFormatted($fieldName); $value = (string) $field->type->markupValue($item, $field, $v, $subfieldName); @@ -446,7 +462,7 @@ class InputfieldPageTable extends Inputfield { */ protected function renderItemLink(Page $item, $out, $url = '') { if(!$url) $url = $this->getItemEditURL($item); - return "$out"; + return "$out"; } /** @@ -457,7 +473,7 @@ class InputfieldPageTable extends Inputfield { * */ protected function getItemEditURL(Page $item) { - return $this->wire('config')->urls->admin . "page/edit/?id=$item->id&modal=1&context=PageTable"; + return $this->wire()->config->urls->admin . "page/edit/?id=$item->id&modal=1&context=PageTable"; } /** @@ -485,8 +501,9 @@ class InputfieldPageTable extends Inputfield { $value = (string) $object; } - $value = $this->wire('sanitizer')->entities(strip_tags($value)); + $value = $this->wire()->sanitizer->entities(strip_tags($value)); $value = nl2br($value); + return $value; } @@ -498,15 +515,15 @@ class InputfieldPageTable extends Inputfield { * */ public function ___processInput(WireInputData $input) { + + $pages = $this->wire()->pages; $name = $this->attr('name'); $deleteName = $name . '__delete'; - $deleteIDs = explode('|', $input->$deleteName); $ids = explode('|', $input->$name); - /** @var PageArray $value */ - $value = $this->attr('value'); - $sorted = $this->wire('pages')->newPageArray(); + $value = $this->attr('value'); /** @var PageArray $value */ + $sorted = $pages->newPageArray(); $changed = false; // trash items that have been deleted @@ -516,7 +533,7 @@ class InputfieldPageTable extends Inputfield { if($id != $item->id) continue; if(!$item->deleteable()) continue; $value->remove($item); - $this->wire('pages')->trash($item); + $pages->trash($item); $changed = true; } } @@ -536,7 +553,7 @@ class InputfieldPageTable extends Inputfield { // check for orphans that may have been added $orphanInputName = $name . '__add_orphan'; $orphanIDs = $input->$orphanInputName; - if($orphanIDs && count($orphanIDs) && $this->orphans) { + if(is_array($orphanIDs) && count($orphanIDs) && $this->orphans) { $numOrphansAdded = 0; foreach($orphanIDs as $orphanID) { foreach($this->orphans as $orphan) { @@ -560,7 +577,7 @@ class InputfieldPageTable extends Inputfield { // check if we need to setup a name format for any pages foreach($value as $n => $item) { - $name = $this->wire('pages')->setupPageName($item, array('format' => $this->nameFormat)); + $name = $pages->setupPageName($item, array('format' => $this->nameFormat)); if($name) { $this->message("Auto assigned name '$name' to item #" . ($n+1), Notice::debug); $item->save(); @@ -579,11 +596,12 @@ class InputfieldPageTable extends Inputfield { * */ public function set($key, $value) { - if($key == 'template_id' && $value) { + if($key === 'template_id' && $value) { // convert template_id to $this->rowTemplates array + $templates = $this->wire()->templates; if(!is_array($value)) $value = array($value); foreach($value as $id) { - $template = $this->wire('templates')->get($id); + $template = $templates->get($id); if($template) $this->rowTemplates[$id] = $template; } return $this; @@ -605,8 +623,10 @@ class InputfieldPageTable extends Inputfield { */ public function setAttribute($key, $value) { if($key == 'value') { - if($value === null) $value = $this->wire('pages')->newPageArray(); - if(!$value instanceof PageArray) throw new WireException('This Inputfield only accepts a PageArray for its value attribute.'); + if($value === null) $value = $this->wire()->pages->newPageArray(); + if(!$value instanceof PageArray) { + throw new WireException('This Inputfield only accepts a PageArray for its value attribute.'); + } } return parent::setAttribute($key, $value); } @@ -628,8 +648,11 @@ class InputfieldPageTable extends Inputfield { $fieldCounts = array(); foreach($this->rowTemplates as $template) { foreach($template->fieldgroup as $field) { - if(!isset($fieldCounts[$field->name])) $fieldCounts[$field->name] = 1; - else $fieldCounts[$field->name]++; + if(!isset($fieldCounts[$field->name])) { + $fieldCounts[$field->name] = 1; + } else { + $fieldCounts[$field->name]++; + } } } @@ -653,11 +676,16 @@ class InputfieldPageTable extends Inputfield { public function ___getConfigInputfields() { $inputfields = parent::___getConfigInputfields(); - $f = $this->wire('modules')->get('InputfieldTextarea'); + $f = $inputfields->InputfieldTextarea; $f->attr('name', 'columns'); $f->label = $this->_('Table fields to display in admin'); - $f->description = $this->_('Enter the names of the fields (1 per line) that you want to display as columns in the table. To specify a column width for the field, specify "field_name=30" where "30" is the width (in percent) of the column. When specifying widths, make the total of all columns add up to 100.'); // Columns description - $f->notes = $this->_('You may specify any native or custom field. You may also use subfields (field.subfield) with fields that contain multiple properties, like page references.') . ' '; // Columns notes + $f->description = + $this->_('Enter the names of the fields (1 per line) that you want to display as columns in the table.') . ' ' . + $this->_('To specify a column width for the field, specify "field_name=30" where "30" is the width (in percent) of the column.') . ' ' . + $this->_('When specifying widths, make the total of all columns add up to 100.'); + $f->notes = + $this->_('You may specify any native or custom field.') . ' ' . + $this->_('You may also use subfields (field.subfield) with fields that contain multiple properties, like page references.') . ' '; $columns = $this->columns ? $this->columns : $this->getConfigDefaultColumns(); $f->attr('value', $columns); @@ -674,17 +702,24 @@ class InputfieldPageTable extends Inputfield { $inputfields->add($f); - $f = $this->wire('modules')->get('InputfieldText'); + $f = $inputfields->InputfieldText; $f->attr('name', 'nameFormat'); $f->attr('value', $this->nameFormat); $f->label = $this->_('Automatic Page Name Format'); - $f->description = $this->_('When populated, pages will be created automatically using this name format whenever a user clicks the "Add New" button. If left blank, the user will be asked to enter a name for the page before it is created.'); // page name format description - $f->notes = $this->_('If the name format contains any non-alphanumeric characters, it is considered to be a [PHP date](http://www.php.net/manual/en/function.date.php) format. If it contains only alphanumeric characters then it will be used directly, with a number appended to the end (when necessary) to ensure uniqueness.'); // page name format notes + $f->description = + $this->_('When populated, pages will be created automatically using this name format whenever a user clicks the "Add New" button.') . ' ' . // page name format description 1 + $this->_('If left blank, the user will be asked to enter a name for the page before it is created.'); // page name format description 2 + $f->notes = + sprintf( + $this->_('If the name format contains any non-alphanumeric characters, it is considered to be a [PHP date](%s) format.'), + 'https://www.php.net/manual/en/datetime.format.php' + ). ' ' . + $this->_('If it contains only alphanumeric characters then it will be used directly, with a number appended to the end (when necessary) to ensure uniqueness.'); // page name format notes $f->notes .= ' ' . $this->_('Example: **Ymd:His** is a good name format for date/time based page names.'); $f->collapsed = Inputfield::collapsedBlank; $inputfields->add($f); - - $f = $this->wire('modules')->get('InputfieldRadios'); + + $f = $inputfields->InputfieldRadios; $f->attr('name', 'noclose'); $f->label = $this->_('Modal edit window behavior'); $f->addOption(0, $this->_('Automatically close on save (default)')); diff --git a/wire/modules/Inputfield/InputfieldPageTable/InputfieldPageTableAjax.php b/wire/modules/Inputfield/InputfieldPageTable/InputfieldPageTableAjax.php index 6c1a3cc3..1a95f71f 100644 --- a/wire/modules/Inputfield/InputfieldPageTable/InputfieldPageTableAjax.php +++ b/wire/modules/Inputfield/InputfieldPageTable/InputfieldPageTableAjax.php @@ -7,7 +7,7 @@ * Code by Ryan Cramer * Sponsored by Avoine * - * ProcessWire 3.x, Copyright 2016 by Ryan Cramer + * ProcessWire 3.x, Copyright 2023 by Ryan Cramer * https://processwire.com * * @method void checkAjax() @@ -37,20 +37,22 @@ class InputfieldPageTableAjax extends Wire { */ protected function ___checkAjax() { - $input = $this->wire('input'); + $pages = $this->wire()->pages; + $input = $this->wire()->input; + $fieldName = $input->get('InputfieldPageTableField'); if(!$fieldName) return; - $processPage = $this->wire('page'); + $processPage = $this->wire()->page; if(!in_array('WirePageEditor', wireClassImplements((string) $processPage->process))) return; // not ProcessPageEdit or compatible - $field = $this->wire('fields')->get($this->wire('sanitizer')->fieldName($fieldName)); + $field = $this->wire()->fields->get($this->wire()->sanitizer->fieldName($fieldName)); if(!$field || !$field->type instanceof FieldtypePageTable) return; // die('field does not exist or is not FieldtypePageTable'); $pageID = (int) $input->get('id'); if(!$pageID) return; // die('page ID not specified'); - $page = $this->wire('pages')->get($pageID); + $page = $pages->get($pageID); if(!$page->id) return; if(!$page->editable($field->name)) return; @@ -59,7 +61,7 @@ class InputfieldPageTableAjax extends Wire { // check for new item that should be added $itemID = (int) $input->get('InputfieldPageTableAdd'); - if($itemID) $this->addItem($page, $field, $this->wire('pages')->get($itemID)); + if($itemID) $this->addItem($page, $field, $pages->get($itemID)); $sort = $input->get('InputfieldPageTableSort'); if(strlen("$sort")) $this->sortItems($page, $field, $sort); @@ -79,7 +81,7 @@ class InputfieldPageTableAjax extends Wire { if(!$inputfield) return; echo $inputfield->render(); if($this->notes) { - echo "

" . $this->wire('sanitizer')->entities($this->notes) . "

"; + echo "

" . $this->wire()->sanitizer->entities($this->notes) . "

"; $this->notes = ''; } exit; @@ -96,7 +98,7 @@ class InputfieldPageTableAjax extends Wire { */ protected function addItem(Page $page, Field $field, Page $item) { // add an item and save the field - if(!$item->id || $item->createdUser->id != $this->wire('user')->id) return false; + if(!$item->id || $item->createdUser->id !== $this->wire()->user->id) return false; $value = $page->getUnformatted($field->name);