diff --git a/wire/core/WireInputData.php b/wire/core/WireInputData.php index 71073185..d3410b5e 100644 --- a/wire/core/WireInputData.php +++ b/wire/core/WireInputData.php @@ -31,7 +31,7 @@ * @method string pagePathName($varName) Sanitize to what could be a valid page path in ProcessWire * @method string email($varName) Sanitize email address, converting to blank if invalid * @method string emailHeader($varName) Sanitize string for use in an email header - * @method string text($varName) Sanitize to single line of text up to 255 characters (1024 bytes max), HTML markup is removed + * @method string text($varName, $options = array()) Sanitize to single line of text up to 255 characters (1024 bytes max), HTML markup is removed * @method string textarea($varName) Sanitize to multi-line text up to 16k characters (48k bytes), HTML markup is removed * @method string url($varName) Sanitize to a valid URL, or convert to blank if it can't be sanitized * @method string selectorField($varName) Sanitize a field name for use in a selector string diff --git a/wire/modules/Process/ProcessPageLister/ProcessPageListerBookmarks.php b/wire/modules/Process/ProcessPageLister/ProcessPageListerBookmarks.php index dc28ecfd..e2442bae 100644 --- a/wire/modules/Process/ProcessPageLister/ProcessPageListerBookmarks.php +++ b/wire/modules/Process/ProcessPageLister/ProcessPageListerBookmarks.php @@ -312,8 +312,14 @@ class ProcessPageListerBookmarks extends Wire { $f->label = $this->_x('What pages should this bookmark show?', 'bookmark-editor'); $selector = $bookmark['selector']; if($bookmark['sort']) $selector .= ", sort=$bookmark[sort]"; - if($this->lister->initSelector && strpos($selector, $this->lister->initSelector) !== false) { - $selector = str_replace($this->lister->initSelector, '', $selector); // ensure that $selector does not contain initSelector + if($this->lister->initSelector) { + $initSelector = $this->lister->initSelector; + if(strpos($selector, $initSelector) === false) { + $initSelector = trim(preg_replace('![,\s]*\binclude=(all|unpublished|hidden)\b!i', '', $initSelector), ', '); + } + if(strpos($selector, $initSelector) !== false) { + $selector = str_replace($initSelector, '', $selector); // ensure that $selector does not contain initSelector + } } if($this->lister->template) $f->initTemplate = $this->lister->template; $default = $this->lister->className() == 'ProcessPageLister'; @@ -483,9 +489,9 @@ class ProcessPageListerBookmarks extends Wire { */ protected function executeSaveBookmark() { - $input = $this->wire('input'); - $sanitizer = $this->wire('sanitizer'); - $languages = $this->wire('languages'); + $input = $this->wire()->input; + $sanitizer = $this->wire()->sanitizer; + $languages = $this->wire()->languages; $bookmarkID = $this->bookmarks->_bookmarkID($input->post('bookmark_id')); $bookmarkTitle = $input->post->text('bookmark_title'); diff --git a/wire/modules/Process/ProcessPageType/ProcessPageType.module b/wire/modules/Process/ProcessPageType/ProcessPageType.module index f9713a65..1a93af4c 100644 --- a/wire/modules/Process/ProcessPageType/ProcessPageType.module +++ b/wire/modules/Process/ProcessPageType/ProcessPageType.module @@ -8,7 +8,7 @@ * For more details about how Process modules work, please see: * /wire/core/Process.php * - * ProcessWire 3.x, Copyright 2018 by Ryan Cramer + * ProcessWire 3.x, Copyright 2020 by Ryan Cramer * https://processwire.com * * @property array $showFields Names of fields to show in the main list table (default=['name']) @@ -62,6 +62,14 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi */ protected $lister = null; + /** + * Requested Lister bookmark ID (when applicable) + * + * @var string|null|bool + * + */ + protected $listerBookmarkID = ''; + /** * Construct * @@ -115,9 +123,10 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi */ protected function initLister() { - if(!$this->useLister()) return; + if(!$this->useLister() || $this->lister) return; // init lister, but only if executing an action that will use it + $modules = $this->wire()->modules; $segment = $this->wire('input')->urlSegment1; $user = $this->wire('user'); $listerSegments = array( @@ -129,14 +138,32 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi 'save', 'edit-bookmark', ); - if(empty($segment) || in_array($segment, $listerSegments) && $user->hasPermission('page-lister')) { - if($this->wire('modules')->isInstalled('ProcessPageListerPro')) { - $this->lister = $this->wire('modules')->get('ProcessPageListerPro'); + + if(strpos($segment, 'bm') === 0 && preg_match('/^bm[0-9O]+$/', $segment)) { + // bookmark ID, i.e. users/bm42O1604139292 + $bookmarkID = $segment; + } else { + $bookmarkID = ''; + } + + if(empty($segment) || $bookmarkID || in_array($segment, $listerSegments)) { + if(!$user->hasPermission('page-lister')) return; + if($modules->isInstalled('ProcessPageListerPro')) { + $this->lister = $modules->get('ProcessPageListerPro'); + if($this->lister && method_exists($this->lister, 'isValid') && !$this->lister->isValid()) { + $this->lister = null; + } } - if((!$this->lister || !$this->lister->isValid()) && $this->wire('modules')->isInstalled('ProcessPageLister')) { - $this->lister = $this->wire('modules')->get('ProcessPageLister'); + if(!$this->lister && $modules->isInstalled('ProcessPageLister')) { + $this->lister = $modules->get('ProcessPageLister'); } } + + if($this->lister && $bookmarkID) { + $bookmarks = $this->lister->getBookmarksInstance(); + $bookmarkID = $bookmarks->_bookmarkID(ltrim($bookmarkID, 'bm')); + $this->listerBookmarkID = $this->lister->checkBookmark($bookmarkID); + } } // Lister-specific methods, all mapped directly to Lister or ListerPro @@ -147,6 +174,24 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi public function ___executeSave() { return $this->getLister()->executeSave(); } public function ___executeEditBookmark() { return $this->getLister()->executeEditBookmark(); } + /** + * Catch-all for bookmarks + * + * @return string + * @throws Wire404Exception + * @throws WireException + * + */ + public function ___executeUnknown() { + $lister = null; + if($this->useLister()) { + $this->initLister(); + $lister = $this->getLister(); + if($lister && $this->listerBookmarkID) return $lister->executeUnknown(); + } + throw new Wire404Exception("Unknown action", Wire404Exception::codeNonexist); + } + /** * Main execution method, delegated to listing items in this page type * @@ -259,7 +304,7 @@ class ProcessPageType extends Process implements ConfigurableModule, WirePageEdi 'delimiters' => array(), 'allowSystem' => true, 'allowIncludeAll' => true, - 'allowBookmarks' => false, + 'allowBookmarks' => true, 'showIncludeWarnings' => false, 'toggles' => array('collapseFilters'), ); diff --git a/wire/modules/Process/ProcessUser/ProcessUser.module b/wire/modules/Process/ProcessUser/ProcessUser.module index 4f8d2570..1861990c 100644 --- a/wire/modules/Process/ProcessUser/ProcessUser.module +++ b/wire/modules/Process/ProcessUser/ProcessUser.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 2020 by Ryan Cramer * https://processwire.com * * @property int $maxAjaxQty @@ -107,9 +107,10 @@ class ProcessUser extends ProcessPageType { */ public function hookListerExecute($event) { - $role = (int) $this->wire('session')->get($this, 'listerRole'); + $role = (int) $this->wire()->session->getFor($this, 'listerRole'); if(!$role) return; - + + /** @var ProcessPageLister $lister */ $lister = $event->object; $defaultSelector = $lister->defaultSelector; if(strpos($defaultSelector, 'roles=') !== false) { @@ -132,25 +133,25 @@ class ProcessUser extends ProcessPageType { $settings = parent::getListerSettings($lister, $selector); $selector = ''; - $role = (int) $this->wire('input')->get('roles'); - $user = $this->wire('user'); - $session = $this->wire('session'); + $role = (int) $this->wire()->input->get('roles'); + $user = $this->wire()->user; + $session = $this->wire()->session; $ajax = $this->wire('config')->ajax; if($role) { $lister->resetLister(); - $session->set($this, 'listerRole', $role); + $session->setFor($this, 'listerRole', $role); } else if(!$ajax) { - if((int) $session->get($this, 'listerRole') > 0) { + if((int) $session->getFor($this, 'listerRole') > 0) { $lister->resetLister(); - $session->set($this, 'listerRole', 0); + $session->setFor($this, 'listerRole', 0); } } else { - $role = $session->get($this, 'listerRole'); + $role = $session->getFor($this, 'listerRole'); } if(!$role && !$user->isSuperuser()) { - $userAdminAll = $this->wire('permissions')->get('user-admin-all'); + $userAdminAll = $this->wire()->permissions->get('user-admin-all'); if($userAdminAll->id && !$user->hasPermission($userAdminAll)) { // system has user-admin-all permission, and user doesn't have it // so limit them only to the permission user-admin-[role] roles that they have assigned @@ -162,8 +163,9 @@ class ProcessUser extends ProcessPageType { if($rolePage->id) $roles[] = $rolePage->id; } // allow them to view users that only have guest role - $guestRoleID = $this->wire('config')->guestUserRolePageID; - $guestUserID = $this->wire('config')->guestUserPageID; + $config = $this->wire()->config; + $guestRoleID = $config->guestUserRolePageID; + $guestUserID = $config->guestUserPageID; $selector .= ", id!=$guestUserID, roles=(roles.count=1, roles=$guestRoleID)"; if(count($roles)) { $selector .= ", roles=(roles=" . implode('|', $roles) . ")"; // string of | separated role IDs @@ -174,6 +176,7 @@ class ProcessUser extends ProcessPageType { $settings['initSelector'] .= $selector; $settings['defaultSelector'] = "name%=, roles=" . ($role ? $role : ''); $settings['delimiters'] = array('roles' => ', '); + $settings['allowBookmarks'] = true; return $settings; } @@ -287,8 +290,10 @@ class ProcessUser extends ProcessPageType { * */ public function hookGetSelectablePages($event) { - if($event->object->attr('name') != 'roles') return; - $suRoleID = $this->wire('config')->superUserRolePageID; + /** @var InputfieldPage $inputfield */ + $inputfield = $event->object; + if($inputfield->attr('name') != 'roles') return; + $suRoleID = $this->wire()->config->superUserRolePageID; foreach($event->return as $role) { if($role->id == $suRoleID) $event->return->remove($role); }