From 0dc87664918be6056e0eec38d6fc3a07dfe11584 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Thu, 6 Dec 2018 14:05:17 -0500 Subject: [PATCH] Fix issue processwire/processwire-issues#751 with Page::index() not working for hidden/unpublished pages --- wire/core/Page.php | 27 ++++++++++++++++++++++----- wire/core/PageTraversal.php | 28 ++++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/wire/core/Page.php b/wire/core/Page.php index d40285f6..27e90da9 100644 --- a/wire/core/Page.php +++ b/wire/core/Page.php @@ -943,7 +943,7 @@ class Page extends WireData implements \Countable, WireMatchable { // if the page is not yet loaded and a '__' field was set, then we queue it so that the loaded() method can // instantiate all those fields knowing that all parts of them are present for wakeup. if(!$this->isLoaded && strpos($key, '__')) { - list($key, $subKey) = explode('__', $key); + list($key, $subKey) = explode('__', $key, 2); if(!isset($this->fieldDataQueue[$key])) $this->fieldDataQueue[$key] = array(); $this->fieldDataQueue[$key][$subKey] = $value; return $this; @@ -3149,6 +3149,14 @@ class Page extends WireData implements \Countable, WireMatchable { /** * Return the index/position of this page relative to siblings. * + * If given a hidden or unpublished page, that page would not usually be part of the group of siblings, + * unless specifically including hidden and/or unpublished pages. As a result, such pages will return -1 + * for this method (as of 3.0.121), indicating they are not part of the default index. + * + * If you want this method to include hidden/unpublished pages as part of the index numbers, then + * specify boolean true for the $selector argument (which implies "include=all") OR specify a + * selector of "include=hidden", "include=unpublished" or "include=all". + * * ~~~~~ * $i = $page->index(); * $n = $page->parent->numChildren(); @@ -3157,12 +3165,16 @@ class Page extends WireData implements \Countable, WireMatchable { * * #pw-group-traversal * - * @return int Returns index number (zero-based) + * @param bool|string|array Specify one of the following (since 3.0.121): + * - Boolean true to include hidden and unpublished pages as part of the index numbers (same as "include=all"). + * - An "include=hidden", "include=unpublished" or "include=all" selector to include them in the index numbers. + * - A string selector or selector array to filter the criteria for the returned index number. + * @return int Returns index number (zero-based), or -1 if page is hidden or unpublished and no $selector argument provided. * @since 3.0.24 * */ - public function index() { - return $this->traversal()->index($this); + public function index($selector = '') { + return $this->traversal()->index($this, $selector); } /** @@ -3660,10 +3672,15 @@ class Page extends WireData implements \Countable, WireMatchable { * */ protected function processFieldDataQueue() { + + $template = $this->template; + if(!$template) return; + $fieldgroup = $template->fieldgroup; + if(!$fieldgroup) return; foreach($this->fieldDataQueue as $key => $value) { - $field = $this->fieldgroup->get($key); + $field = $fieldgroup->get($key); if(!$field) continue; // check for autojoin multi fields, which may have multiple values bundled into one string diff --git a/wire/core/PageTraversal.php b/wire/core/PageTraversal.php index e8e6a590..fe41f7b9 100644 --- a/wire/core/PageTraversal.php +++ b/wire/core/PageTraversal.php @@ -371,7 +371,10 @@ class PageTraversal { $parent = $page->parent(); if($options['until'] || $options['qty']) $options['all'] = true; - if(!$parent || !$parent->id) return $options['all'] ? $pages->newPageArray() : $pages->newNullPage(); + if(!$parent || !$parent->id) { + if($options['qty']) return 0; + return $options['all'] ? $pages->newPageArray() : $pages->newNullPage(); + } if(is_array($selector)) { $selector['parent_id'] = $parent->id; @@ -412,12 +415,29 @@ class PageTraversal { /** * Return the index/position of the given page relative to its siblings * + * If given a hidden or unpublished page, that page would not usually be part of the group of siblings. + * As a result, such pages will return -1 for this method (as of 3.0.121), indicating they are not part + * of the default index. + * + * If you want this method to include hidden/unpublished pages as part of the index numbers, then + * specify boolean true for the $selector argument (which implies "include=all") OR specify a + * selector of "include=hidden", "include=unpublished" or "include=all". + * * @param Page $page - * @return int|NullPage|Page|PageArray + * @param string|array|bool $selector Selector to apply or boolean true for "include=all" (since 3.0.121). + * - Boolean true to include hidden and unpublished pages as part of the index numbers (same as "include=all"). + * - An "include=hidden", "include=unpublished" or "include=all" selector to include them in the index numbers. + * - A string selector or selector array to filter the criteria for the returned index number. + * @return int Returns index number (zero-based), or -1 if page is hidden or unpublished and no $selector argument provided. * */ - public function index(Page $page) { - $index = $this->_next($page, '', array('prev' => true, 'all' => true, 'qty' => true)); + public function index(Page $page, $selector = '') { + if($selector === true) { + $selector = "include=all"; + } else if(empty($selector) && ($page->isHidden() || $page->isUnpublished())) { + return -1; + } + $index = $this->_next($page, $selector, array('prev' => true, 'all' => true, 'qty' => true)); return $index; }