mirror of
https://github.com/processwire/processwire.git
synced 2025-08-10 00:37:02 +02:00
Update to allow for Page objects to load pages (children, parent, etc.) that don't get cached when their load option specified cache=false. Also makes the 'parent' page lazy loading for Page objects, so that it doesn't load the parent Page until a $page->parent() call is requested. Updates for @apeisa / Avoine request.
This commit is contained in:
@@ -46,6 +46,9 @@ if(!defined("PROCESSWIRE")) die();
|
|||||||
* always have this disabled for live/production sites since it reveals more information
|
* always have this disabled for live/production sites since it reveals more information
|
||||||
* than is advisible for security.
|
* than is advisible for security.
|
||||||
*
|
*
|
||||||
|
* You may also set this to the constant `Config::debugVerbose` to enable verbose debug mode,
|
||||||
|
* which uses more memory and time.
|
||||||
|
*
|
||||||
* #notes This enables debug mode for ALL requests. See the debugIf option for an alternative.
|
* #notes This enables debug mode for ALL requests. See the debugIf option for an alternative.
|
||||||
*
|
*
|
||||||
* @var bool
|
* @var bool
|
||||||
|
@@ -79,7 +79,7 @@
|
|||||||
*
|
*
|
||||||
* @property bool $advanced Special mode for ProcessWire system development. Not recommended for regular site development or production use. #pw-group-system
|
* @property bool $advanced Special mode for ProcessWire system development. Not recommended for regular site development or production use. #pw-group-system
|
||||||
* @property bool $demo Special mode for demonstration use that causes POST requests to be disabled. Applies to core, but may not be safe with 3rd party modules. #pw-group-system
|
* @property bool $demo Special mode for demonstration use that causes POST requests to be disabled. Applies to core, but may not be safe with 3rd party modules. #pw-group-system
|
||||||
* @property bool $debug Special mode for use when debugging or developing a site. Recommended TRUE when site is in development and FALSE when not. #pw-group-system
|
* @property bool|int $debug Special mode for use when debugging or developing a site. Recommended TRUE when site is in development and FALSE when not. Or set to Config::debugVerbose for verbose debug mode. #pw-group-system
|
||||||
* @property string $debugIf Enable debug mode if condition is met #pw-group-system
|
* @property string $debugIf Enable debug mode if condition is met #pw-group-system
|
||||||
* @property array $debugTools Tools, and their order, to show in debug mode (admin) #pw-group-system
|
* @property array $debugTools Tools, and their order, to show in debug mode (admin) #pw-group-system
|
||||||
*
|
*
|
||||||
@@ -156,6 +156,12 @@
|
|||||||
*/
|
*/
|
||||||
class Config extends WireData {
|
class Config extends WireData {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant for verbose debug mode (uses more memory)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const debugVerbose = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get URL for requested resource or module
|
* Get URL for requested resource or module
|
||||||
*
|
*
|
||||||
|
@@ -72,6 +72,7 @@
|
|||||||
* @property string $editUrl URL that this page can be edited at. #pw-group-advanced
|
* @property string $editUrl URL that this page can be edited at. #pw-group-advanced
|
||||||
* @property string $editURL Alias of $editUrl. #pw-internal
|
* @property string $editURL Alias of $editUrl. #pw-internal
|
||||||
* @property PageRender $render May be used for field markup rendering like $page->render->title. #pw-advanced
|
* @property PageRender $render May be used for field markup rendering like $page->render->title. #pw-advanced
|
||||||
|
* @property bool $loaderCache Whether or not pages loaded as a result of this one may be cached by PagesLoaderCache. #pw-internal
|
||||||
*
|
*
|
||||||
* @property bool|null $_hasAutogenName Internal runtime use, set by Pages class when page as auto-generated name. #pw-internal
|
* @property bool|null $_hasAutogenName Internal runtime use, set by Pages class when page as auto-generated name. #pw-internal
|
||||||
* @property bool|null $_forceSaveParents Internal runtime/debugging use, force a page to refresh its pages_parents DB entries on save(). #pw-internal
|
* @property bool|null $_forceSaveParents Internal runtime/debugging use, force a page to refresh its pages_parents DB entries on save(). #pw-internal
|
||||||
@@ -278,7 +279,15 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
* @var Page|null
|
* @var Page|null
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected $parent = null;
|
protected $_parent = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parent ID for lazy loading purposes
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $_parent_id = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The previous parent used by the page, if it was changed during runtime.
|
* The previous parent used by the page, if it was changed during runtime.
|
||||||
@@ -368,6 +377,14 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
*/
|
*/
|
||||||
protected $lazyLoad = false;
|
protected $lazyLoad = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not pages loaded by this one are allowed to be cached by PagesLoaderCache class
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $loaderCache = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this page allowing it's output to be formatted?
|
* Is this page allowing it's output to be formatted?
|
||||||
*
|
*
|
||||||
@@ -698,9 +715,18 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
break;
|
break;
|
||||||
case 'parent':
|
case 'parent':
|
||||||
case 'parent_id':
|
case 'parent_id':
|
||||||
if(($key == 'parent_id' || is_int($value)) && $value) $value = $this->wire('pages')->get((int)$value);
|
if(is_object($value) && $value instanceof Page) {
|
||||||
else if(is_string($value)) $value = $this->wire('pages')->get($value);
|
// ok
|
||||||
if($value) $this->setParent($value);
|
$this->setParent($value);
|
||||||
|
} else if($value && !$this->_parent &&
|
||||||
|
($key == 'parent_id' || is_int($value) || (is_string($value) && ctype_digit("$value")))) {
|
||||||
|
// store only parent ID so that parent is lazy loaded,
|
||||||
|
// but only if parent hasn't already been previously loaded
|
||||||
|
$this->_parent_id = (int) $value;
|
||||||
|
} else if($value && (is_string($value) || is_int($value))) {
|
||||||
|
$value = $this->_pages('get', $value);
|
||||||
|
$this->setParent($value);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'parentPrevious':
|
case 'parentPrevious':
|
||||||
if(is_null($value) || $value instanceof Page) $this->parentPrevious = $value;
|
if(is_null($value) || $value instanceof Page) $this->parentPrevious = $value;
|
||||||
@@ -748,6 +774,9 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
$this->instanceID = $value;
|
$this->instanceID = $value;
|
||||||
self::$instanceIDs[$value] = $this->settings['id'];
|
self::$instanceIDs[$value] = $this->settings['id'];
|
||||||
break;
|
break;
|
||||||
|
case 'loaderCache':
|
||||||
|
$this->loaderCache = (bool) $value;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if(strpos($key, 'name') === 0 && ctype_digit(substr($key, 5)) && $this->wire('languages')) {
|
if(strpos($key, 'name') === 0 && ctype_digit(substr($key, 5)) && $this->wire('languages')) {
|
||||||
// i.e. name1234
|
// i.e. name1234
|
||||||
@@ -953,8 +982,12 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch($key) {
|
switch($key) {
|
||||||
|
case 'parent':
|
||||||
|
$value = $this->_parent ? $this->_parent : $this->parent();
|
||||||
|
break;
|
||||||
case 'parent_id':
|
case 'parent_id':
|
||||||
$value = $this->parent ? $this->parent->id : 0;
|
$value = $this->_parent ? $this->_parent->id : 0;
|
||||||
|
if(!$value) $value = $this->_parent_id;
|
||||||
break;
|
break;
|
||||||
case 'templates_id':
|
case 'templates_id':
|
||||||
$value = $this->template ? $this->template->id : 0;
|
$value = $this->template ? $this->template->id : 0;
|
||||||
@@ -994,6 +1027,9 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
$value = $this->wire('modules')->get('PageRender');
|
$value = $this->wire('modules')->get('PageRender');
|
||||||
$value->setPropertyPage($this);
|
$value->setPropertyPage($this);
|
||||||
break;
|
break;
|
||||||
|
case 'loaderCache':
|
||||||
|
$value = $this->loaderCache;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if($key && isset($this->settings[(string)$key])) return $this->settings[$key];
|
if($key && isset($this->settings[(string)$key])) return $this->settings[$key];
|
||||||
@@ -1725,20 +1761,21 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function setParent(Page $parent) {
|
public function setParent(Page $parent) {
|
||||||
if($this->parent && $this->parent->id == $parent->id) return $this;
|
if($this->_parent && $this->_parent->id == $parent->id) return $this;
|
||||||
if($parent->id && $this->id == $parent->id || $parent->parents->has($this)) {
|
if($parent->id && $this->id == $parent->id || $parent->parents->has($this)) {
|
||||||
throw new WireException("Page cannot be its own parent");
|
throw new WireException("Page cannot be its own parent");
|
||||||
}
|
}
|
||||||
if($this->isLoaded) {
|
if($this->isLoaded) {
|
||||||
$this->trackChange('parent', $this->parent, $parent);
|
$this->trackChange('parent', $this->_parent, $parent);
|
||||||
if(($this->parent && $this->parent->id) && $this->parent->id != $parent->id) {
|
if(($this->_parent && $this->_parent->id) && $this->_parent->id != $parent->id) {
|
||||||
if($this->settings['status'] & Page::statusSystem) {
|
if($this->settings['status'] & Page::statusSystem) {
|
||||||
throw new WireException("Parent changes are disallowed on this page");
|
throw new WireException("Parent changes are disallowed on this page");
|
||||||
}
|
}
|
||||||
if(is_null($this->parentPrevious)) $this->parentPrevious = $this->parent;
|
if(is_null($this->parentPrevious)) $this->parentPrevious = $this->_parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->parent = $parent;
|
$this->_parent = $parent;
|
||||||
|
$this->_parent_id = $parent->id;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1809,7 +1846,7 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
} else if(is_array($selector)) {
|
} else if(is_array($selector)) {
|
||||||
$selector["has_parent"] = $this->id;
|
$selector["has_parent"] = $this->id;
|
||||||
}
|
}
|
||||||
return $this->wire('pages')->find($selector, $options);
|
return $this->_pages('find', $selector, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1950,10 +1987,16 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function parent($selector = '') {
|
public function parent($selector = '') {
|
||||||
if(!$this->parent) return $this->wire('pages')->newNullPage();
|
if(!$this->_parent) {
|
||||||
if(empty($selector)) return $this->parent;
|
if($this->_parent_id) {
|
||||||
if($this->parent->matches($selector)) return $this->parent;
|
$this->_parent = $this->_pages('get', (int) $this->_parent_id);
|
||||||
if($this->parent->parent_id) return $this->parent->parent($selector); // recursive, in a way
|
} else {
|
||||||
|
return $this->wire('pages')->newNullPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(empty($selector)) return $this->_parent;
|
||||||
|
if($this->_parent->matches($selector)) return $this->_parent;
|
||||||
|
if($this->_parent->parent_id) return $this->_parent->parent($selector); // recursive, in a way
|
||||||
return $this->wire('pages')->newNullPage();
|
return $this->wire('pages')->newNullPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3709,5 +3752,25 @@ class Page extends WireData implements \Countable, WireMatchable {
|
|||||||
throw new WireException("Invalid arguments to Page::lazy()");
|
throw new WireException("Invalid arguments to Page::lazy()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles get/find loads specific to this Page from the $pages API variable
|
||||||
|
*
|
||||||
|
* #pw-internal
|
||||||
|
*
|
||||||
|
* @param string $method The $pages API method to call (get, find, findOne, or count)
|
||||||
|
* @param string|int $selector The selector argument of the $pages call
|
||||||
|
* @param array $options Any additional options (see Pages::find for options).
|
||||||
|
* @return Pages|Page|PageArray|NullPage
|
||||||
|
* @throws WireException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function _pages($method = '', $selector = '', $options = array()) {
|
||||||
|
if(empty($method)) return $this->wire('pages');
|
||||||
|
if(!isset($options['cache'])) $options['cache'] = $this->loaderCache;
|
||||||
|
if(!isset($options['caller'])) $options['caller'] = "page._pages.$method";
|
||||||
|
$result = $this->wire('pages')->$method($selector, $options);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,15 +34,17 @@ class PageTraversal {
|
|||||||
// onlyVisible takes the place of selector
|
// onlyVisible takes the place of selector
|
||||||
$onlyVisible = $selector;
|
$onlyVisible = $selector;
|
||||||
if(!$onlyVisible) return $page->get('numChildren');
|
if(!$onlyVisible) return $page->get('numChildren');
|
||||||
return $page->wire('pages')->count("parent_id=$page->id");
|
return $page->_pages('count', "parent_id=$page->id");
|
||||||
|
|
||||||
} else if($selector === 1) {
|
} else if($selector === 1) {
|
||||||
// viewable pages only
|
// viewable pages only
|
||||||
$numChildren = $page->get('numChildren');
|
$numChildren = $page->get('numChildren');
|
||||||
if(!$numChildren) return 0;
|
if(!$numChildren) return 0;
|
||||||
if($page->wire('user')->isSuperuser()) return $numChildren;
|
if($page->wire('user')->isSuperuser()) return $numChildren;
|
||||||
if($page->wire('user')->hasPermission('page-edit')) return $page->wire('pages')->count("parent_id=$page->id, include=unpublished");
|
if($page->wire('user')->hasPermission('page-edit')) {
|
||||||
return $page->wire('pages')->count("parent_id=$page->id, include=hidden");
|
return $page->_pages('count', "parent_id=$page->id, include=unpublished");
|
||||||
|
}
|
||||||
|
return $page->_pages('count', "parent_id=$page->id, include=hidden");
|
||||||
|
|
||||||
} else if(empty($selector) || (!is_string($selector) && !is_array($selector))) {
|
} else if(empty($selector) || (!is_string($selector) && !is_array($selector))) {
|
||||||
return $page->get('numChildren');
|
return $page->get('numChildren');
|
||||||
@@ -53,7 +55,7 @@ class PageTraversal {
|
|||||||
} else if(is_array($selector)) {
|
} else if(is_array($selector)) {
|
||||||
$selector["parent_id"] = $page->id;
|
$selector["parent_id"] = $page->id;
|
||||||
}
|
}
|
||||||
return $page->wire('pages')->count($selector);
|
return $page->_pages('count', $selector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +69,7 @@ class PageTraversal {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function children(Page $page, $selector = '', $options = array()) {
|
public function children(Page $page, $selector = '', $options = array()) {
|
||||||
if(!$page->numChildren) return $page->wire('pages')->newPageArray();
|
if(!$page->numChildren) return $page->_pages()->newPageArray();
|
||||||
$defaults = array('caller' => 'page.children');
|
$defaults = array('caller' => 'page.children');
|
||||||
$options = array_merge($defaults, $options);
|
$options = array_merge($defaults, $options);
|
||||||
$sortfield = $page->sortfield();
|
$sortfield = $page->sortfield();
|
||||||
@@ -81,7 +83,7 @@ class PageTraversal {
|
|||||||
$selector = trim("parent_id=$page->id, $selector", ", ");
|
$selector = trim("parent_id=$page->id, $selector", ", ");
|
||||||
if(strpos($selector, 'sort=') === false) $selector .= ", sort=$sortfield";
|
if(strpos($selector, 'sort=') === false) $selector .= ", sort=$sortfield";
|
||||||
}
|
}
|
||||||
return $page->wire('pages')->find($selector, $options);
|
return $page->_pages('find', $selector, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,7 +98,7 @@ class PageTraversal {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function child(Page $page, $selector = '', $options = array()) {
|
public function child(Page $page, $selector = '', $options = array()) {
|
||||||
if(!$page->numChildren) return $page->wire('pages')->newNullPage();
|
if(!$page->numChildren) return $page->_pages()->newNullPage();
|
||||||
$defaults = array('getTotal' => false, 'caller' => 'page.child');
|
$defaults = array('getTotal' => false, 'caller' => 'page.child');
|
||||||
$options = array_merge($defaults, $options);
|
$options = array_merge($defaults, $options);
|
||||||
if(is_array($selector)) {
|
if(is_array($selector)) {
|
||||||
@@ -107,7 +109,7 @@ class PageTraversal {
|
|||||||
if(strpos($selector, 'start=') === false) $selector .= ", start=0"; // prevent pagination
|
if(strpos($selector, 'start=') === false) $selector .= ", start=0"; // prevent pagination
|
||||||
}
|
}
|
||||||
$children = $this->children($page, $selector, $options);
|
$children = $this->children($page, $selector, $options);
|
||||||
return count($children) ? $children->first() : $page->wire('pages')->newNullPage();
|
return count($children) ? $children->first() : $page->_pages()->newNullPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,7 +213,7 @@ class PageTraversal {
|
|||||||
$selector = trim($selector, ", ");
|
$selector = trim($selector, ", ");
|
||||||
}
|
}
|
||||||
$options = array('caller' => 'page.siblings');
|
$options = array('caller' => 'page.siblings');
|
||||||
return $page->wire('pages')->find($selector, $options);
|
return $page->_pages('find', $selector, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -247,18 +249,18 @@ class PageTraversal {
|
|||||||
|
|
||||||
} else if(strpos($until, '/') === 0) {
|
} else if(strpos($until, '/') === 0) {
|
||||||
// page path
|
// page path
|
||||||
$stopPage = $pages->get($until);
|
$stopPage = $page->_pages('get', $until);
|
||||||
|
|
||||||
} else if(is_array($selector) || is_array($options['until'])) {
|
} else if(is_array($selector) || is_array($options['until'])) {
|
||||||
// either selector or until is an array
|
// either selector or until is an array
|
||||||
$s = new Selectors($options['until']);
|
$s = new Selectors($options['until']);
|
||||||
foreach(new Selectors($selector) as $item) $s->add($item);
|
foreach(new Selectors($selector) as $item) $s->add($item);
|
||||||
$s->add(new SelectorEqual('limit', 1));
|
$s->add(new SelectorEqual('limit', 1));
|
||||||
$stopPage = $page->wire('pages')->find($s)->first();
|
$stopPage = $page->_pages('find', $s)->first();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// selector string
|
// selector string
|
||||||
$stopPage = $page->wire('pages')->find("$selector, limit=1, $until")->first();
|
$stopPage = $page->_pages('find', "$selector, limit=1, $until")->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($stopPage && $stopPage->id) {
|
if($stopPage && $stopPage->id) {
|
||||||
@@ -324,6 +326,7 @@ class PageTraversal {
|
|||||||
} else if($options['all']) {
|
} else if($options['all']) {
|
||||||
$result = $pages->getById($rows, array(
|
$result = $pages->getById($rows, array(
|
||||||
'parent_id' => $parent->id,
|
'parent_id' => $parent->id,
|
||||||
|
'cache' => $page->loaderCache
|
||||||
));
|
));
|
||||||
if($options['all'] && $options['prev']) $result = $result->reverse();
|
if($options['all'] && $options['prev']) $result = $result->reverse();
|
||||||
|
|
||||||
@@ -332,7 +335,8 @@ class PageTraversal {
|
|||||||
$result = $pages->getById(array($row['id']), array(
|
$result = $pages->getById(array($row['id']), array(
|
||||||
'template' => $page->wire('templates')->get($row['templates_id']),
|
'template' => $page->wire('templates')->get($row['templates_id']),
|
||||||
'parent_id' => $row['parent_id'],
|
'parent_id' => $row['parent_id'],
|
||||||
'getOne' => true
|
'getOne' => true,
|
||||||
|
'cache' => $page->loaderCache
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,6 +452,128 @@ class PageTraversal {
|
|||||||
return $this->_next($page, $filter, $options);
|
return $this->_next($page, $filter, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the URL to the page with $options
|
||||||
|
*
|
||||||
|
* You can specify an `$options` argument to this method with any of the following:
|
||||||
|
*
|
||||||
|
* - `pageNum` (int|string): Specify pagination number, or "+" for next pagination, or "-" for previous pagination.
|
||||||
|
* - `urlSegmentStr` (string): Specify a URL segment string to append.
|
||||||
|
* - `urlSegments` (array): Specify array of URL segments to append (may be used instead of urlSegmentStr).
|
||||||
|
* - `data` (array): Array of key=value variables to form a query string.
|
||||||
|
* - `http` (bool): Specify true to make URL include scheme and hostname (default=false).
|
||||||
|
* - `language` (Language): Specify Language object to return URL in that Language.
|
||||||
|
*
|
||||||
|
* You can also specify any of the following for `$options` as shortcuts:
|
||||||
|
*
|
||||||
|
* - If you specify an `int` for options it is assumed to be the `pageNum` option.
|
||||||
|
* - If you specify `+` or `-` for options it is assumed to be the `pageNum` “next/previous pagination” option.
|
||||||
|
* - If you specify any other `string` for options it is assumed to be the `urlSegmentStr` option.
|
||||||
|
* - If you specify a `boolean` (true) for options it is assumed to be the `http` option.
|
||||||
|
*
|
||||||
|
* Please also note regarding `$options`:
|
||||||
|
*
|
||||||
|
* - This method honors template slash settings for page, URL segments and page numbers.
|
||||||
|
* - Any passed in URL segments are automatically sanitized with `Sanitizer::pageNameUTF8()`.
|
||||||
|
* - If using the `pageNum` or URL segment options please also make sure these are enabled on the page’s template.
|
||||||
|
* - The query string generated by any `data` variables is entity encoded when output formatting is on.
|
||||||
|
* - The `language` option requires that the `LanguageSupportPageNames` module is installed.
|
||||||
|
* - The prefix for page numbers honors `$config->pageNumUrlPrefix` and multi-language prefixes as well.
|
||||||
|
*
|
||||||
|
* @param Page $page
|
||||||
|
* @param array|int|string|bool|Language $options Optionally specify options to modify default behavior (see method description).
|
||||||
|
* @return string Returns page URL, for example: `/my-site/about/contact/`
|
||||||
|
* @see Page::path(), Page::httpUrl(), Page::editUrl(), Page::localUrl()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function urlOptions(Page $page, $options = array()) {
|
||||||
|
|
||||||
|
$config = $page->wire('config');
|
||||||
|
|
||||||
|
$defaults = array(
|
||||||
|
'http' => is_bool($options) ? $options : false,
|
||||||
|
'pageNum' => is_int($options) || (is_string($options) && in_array($options, array('+', '-'))) ? $options : 1,
|
||||||
|
'data' => array(),
|
||||||
|
'urlSegmentStr' => is_string($options) ? $options : '',
|
||||||
|
'urlSegments' => array(),
|
||||||
|
'language' => is_object($options) && $options instanceof Page && $options->className() === 'Language' ? $options : null,
|
||||||
|
);
|
||||||
|
|
||||||
|
if(empty($options)) return rtrim($config->urls->root, '/') . $page->path();
|
||||||
|
|
||||||
|
$options = is_array($options) ? array_merge($defaults, $options) : $defaults;
|
||||||
|
$template = $page->template;
|
||||||
|
$sanitizer = $page->wire('sanitizer');
|
||||||
|
$language = null;
|
||||||
|
$url = null;
|
||||||
|
|
||||||
|
if(count($options['urlSegments'])) {
|
||||||
|
$options['urlSegmentStr'] = implode('/', $options['urlSegments']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($options['language'] && $page->wire('modules')->isInstalled('LanguageSupportPageNames')) {
|
||||||
|
if(!is_object($options['language'])) {
|
||||||
|
$options['language'] = null;
|
||||||
|
} else if(!$options['language'] instanceof Page) {
|
||||||
|
$options['language'] = null;
|
||||||
|
} else if(strpos($options['language']->className(), 'Language') === false) {
|
||||||
|
$options['language'] = null;
|
||||||
|
}
|
||||||
|
if($options['language']) {
|
||||||
|
/** @var Language $language */
|
||||||
|
$language = $options['language'];
|
||||||
|
// localUrl method provided as hook by LanguageSupportPageNames
|
||||||
|
$url = $page->localUrl($language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_null($url)) {
|
||||||
|
$url = rtrim($config->urls->root, '/') . $page->path();
|
||||||
|
if($template->slashUrls === 0 && $page->id > 1) $url = rtrim($url, '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_string($options['urlSegmentStr']) && strlen($options['urlSegmentStr'])) {
|
||||||
|
$url = rtrim($url, '/') . '/' . $sanitizer->pagePathNameUTF8(trim($options['urlSegmentStr'], '/'));
|
||||||
|
if($template->slashUrlSegments === '' || $template->slashUrlSegments) $url .= '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
if($options['pageNum']) {
|
||||||
|
if($options['pageNum'] === '+') {
|
||||||
|
$options['pageNum'] = $page->wire('input')->pageNum + 1;
|
||||||
|
} else if($options['pageNum'] === '-' || $options['pageNum'] === -1) {
|
||||||
|
$options['pageNum'] = $page->wire('input')->pageNum - 1;
|
||||||
|
}
|
||||||
|
if((int) $options['pageNum'] > 1) {
|
||||||
|
$prefix = '';
|
||||||
|
if($language) {
|
||||||
|
$lsp = $page->wire('modules')->get('LanguageSupportPageNames');
|
||||||
|
$prefix = $lsp ? $lsp->get("pageNumUrlPrefix$language") : '';
|
||||||
|
}
|
||||||
|
if(!strlen($prefix)) $prefix = $config->pageNumUrlPrefix;
|
||||||
|
$url = rtrim($url, '/') . '/' . $prefix . ((int) $options['pageNum']);
|
||||||
|
if($template->slashPageNum) $url .= '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(count($options['data'])) {
|
||||||
|
$query = http_build_query($options['data']);
|
||||||
|
if($page->of()) $query = $sanitizer->entities($query);
|
||||||
|
$url .= '?' . $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($options['http']) {
|
||||||
|
switch($template->https) {
|
||||||
|
case -1: $scheme = 'http'; break;
|
||||||
|
case 1: $scheme = 'https'; break;
|
||||||
|
default: $scheme = $config->https ? 'https' : 'http';
|
||||||
|
}
|
||||||
|
$url = "$scheme://" . $page->wire('config')->httpHost . $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************************************************
|
/******************************************************************************************************************
|
||||||
* LEGACY METHODS
|
* LEGACY METHODS
|
||||||
*
|
*
|
||||||
@@ -709,127 +835,6 @@ class PageTraversal {
|
|||||||
return $all;
|
return $all;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the URL to the page with $options
|
|
||||||
*
|
|
||||||
* You can specify an `$options` argument to this method with any of the following:
|
|
||||||
*
|
|
||||||
* - `pageNum` (int|string): Specify pagination number, or "+" for next pagination, or "-" for previous pagination.
|
|
||||||
* - `urlSegmentStr` (string): Specify a URL segment string to append.
|
|
||||||
* - `urlSegments` (array): Specify array of URL segments to append (may be used instead of urlSegmentStr).
|
|
||||||
* - `data` (array): Array of key=value variables to form a query string.
|
|
||||||
* - `http` (bool): Specify true to make URL include scheme and hostname (default=false).
|
|
||||||
* - `language` (Language): Specify Language object to return URL in that Language.
|
|
||||||
*
|
|
||||||
* You can also specify any of the following for `$options` as shortcuts:
|
|
||||||
*
|
|
||||||
* - If you specify an `int` for options it is assumed to be the `pageNum` option.
|
|
||||||
* - If you specify `+` or `-` for options it is assumed to be the `pageNum` “next/previous pagination” option.
|
|
||||||
* - If you specify any other `string` for options it is assumed to be the `urlSegmentStr` option.
|
|
||||||
* - If you specify a `boolean` (true) for options it is assumed to be the `http` option.
|
|
||||||
*
|
|
||||||
* Please also note regarding `$options`:
|
|
||||||
*
|
|
||||||
* - This method honors template slash settings for page, URL segments and page numbers.
|
|
||||||
* - Any passed in URL segments are automatically sanitized with `Sanitizer::pageNameUTF8()`.
|
|
||||||
* - If using the `pageNum` or URL segment options please also make sure these are enabled on the page’s template.
|
|
||||||
* - The query string generated by any `data` variables is entity encoded when output formatting is on.
|
|
||||||
* - The `language` option requires that the `LanguageSupportPageNames` module is installed.
|
|
||||||
* - The prefix for page numbers honors `$config->pageNumUrlPrefix` and multi-language prefixes as well.
|
|
||||||
*
|
|
||||||
* @param Page $page
|
|
||||||
* @param array|int|string|bool|Language $options Optionally specify options to modify default behavior (see method description).
|
|
||||||
* @return string Returns page URL, for example: `/my-site/about/contact/`
|
|
||||||
* @see Page::path(), Page::httpUrl(), Page::editUrl(), Page::localUrl()
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function urlOptions(Page $page, $options = array()) {
|
|
||||||
|
|
||||||
$config = $page->wire('config');
|
|
||||||
|
|
||||||
$defaults = array(
|
|
||||||
'http' => is_bool($options) ? $options : false,
|
|
||||||
'pageNum' => is_int($options) || (is_string($options) && in_array($options, array('+', '-'))) ? $options : 1,
|
|
||||||
'data' => array(),
|
|
||||||
'urlSegmentStr' => is_string($options) ? $options : '',
|
|
||||||
'urlSegments' => array(),
|
|
||||||
'language' => is_object($options) && $options instanceof Page && $options->className() === 'Language' ? $options : null,
|
|
||||||
);
|
|
||||||
|
|
||||||
if(empty($options)) return rtrim($config->urls->root, '/') . $page->path();
|
|
||||||
|
|
||||||
$options = is_array($options) ? array_merge($defaults, $options) : $defaults;
|
|
||||||
$template = $page->template;
|
|
||||||
$sanitizer = $page->wire('sanitizer');
|
|
||||||
$language = null;
|
|
||||||
$url = null;
|
|
||||||
|
|
||||||
if(count($options['urlSegments'])) {
|
|
||||||
$options['urlSegmentStr'] = implode('/', $options['urlSegments']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($options['language'] && $page->wire('modules')->isInstalled('LanguageSupportPageNames')) {
|
|
||||||
if(!is_object($options['language'])) {
|
|
||||||
$options['language'] = null;
|
|
||||||
} else if(!$options['language'] instanceof Page) {
|
|
||||||
$options['language'] = null;
|
|
||||||
} else if(strpos($options['language']->className(), 'Language') === false) {
|
|
||||||
$options['language'] = null;
|
|
||||||
}
|
|
||||||
if($options['language']) {
|
|
||||||
/** @var Language $language */
|
|
||||||
$language = $options['language'];
|
|
||||||
// localUrl method provided as hook by LanguageSupportPageNames
|
|
||||||
$url = $page->localUrl($language);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_null($url)) {
|
|
||||||
$url = rtrim($config->urls->root, '/') . $page->path();
|
|
||||||
if($template->slashUrls === 0 && $page->id > 1) $url = rtrim($url, '/');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_string($options['urlSegmentStr']) && strlen($options['urlSegmentStr'])) {
|
|
||||||
$url = rtrim($url, '/') . '/' . $sanitizer->pagePathNameUTF8(trim($options['urlSegmentStr'], '/'));
|
|
||||||
if($template->slashUrlSegments === '' || $template->slashUrlSegments) $url .= '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
if($options['pageNum']) {
|
|
||||||
if($options['pageNum'] === '+') {
|
|
||||||
$options['pageNum'] = $page->wire('input')->pageNum + 1;
|
|
||||||
} else if($options['pageNum'] === '-' || $options['pageNum'] === -1) {
|
|
||||||
$options['pageNum'] = $page->wire('input')->pageNum - 1;
|
|
||||||
}
|
|
||||||
if((int) $options['pageNum'] > 1) {
|
|
||||||
$prefix = '';
|
|
||||||
if($language) {
|
|
||||||
$lsp = $page->wire('modules')->get('LanguageSupportPageNames');
|
|
||||||
$prefix = $lsp ? $lsp->get("pageNumUrlPrefix$language") : '';
|
|
||||||
}
|
|
||||||
if(!strlen($prefix)) $prefix = $config->pageNumUrlPrefix;
|
|
||||||
$url = rtrim($url, '/') . '/' . $prefix . ((int) $options['pageNum']);
|
|
||||||
if($template->slashPageNum) $url .= '/';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count($options['data'])) {
|
|
||||||
$query = http_build_query($options['data']);
|
|
||||||
if($page->of()) $query = $sanitizer->entities($query);
|
|
||||||
$url .= '?' . $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($options['http']) {
|
|
||||||
switch($template->https) {
|
|
||||||
case -1: $scheme = 'http'; break;
|
|
||||||
case 1: $scheme = 'https'; break;
|
|
||||||
default: $scheme = $config->https ? 'https' : 'http';
|
|
||||||
}
|
|
||||||
$url = "$scheme://" . $page->wire('config')->httpHost . $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the next or previous sibling page (new fast version)
|
* Return the next or previous sibling page (new fast version)
|
||||||
*
|
*
|
||||||
|
@@ -138,12 +138,12 @@ class Pages extends Wire {
|
|||||||
*/
|
*/
|
||||||
public function __construct(ProcessWire $wire) {
|
public function __construct(ProcessWire $wire) {
|
||||||
$this->setWire($wire);
|
$this->setWire($wire);
|
||||||
|
$this->debug = $wire->config->debug === Config::debugVerbose ? true : false;
|
||||||
$this->sortfields = $this->wire(new PagesSortfields());
|
$this->sortfields = $this->wire(new PagesSortfields());
|
||||||
$this->loader = $this->wire(new PagesLoader($this));
|
$this->loader = $this->wire(new PagesLoader($this));
|
||||||
$this->cacher = $this->wire(new PagesLoaderCache($this));
|
$this->cacher = $this->wire(new PagesLoaderCache($this));
|
||||||
$this->trasher = null;
|
$this->trasher = null;
|
||||||
$this->editor = null;
|
$this->editor = null;
|
||||||
$this->debug = $wire->config->debug;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -316,12 +316,13 @@ class Pages extends Wire {
|
|||||||
* #pw-group-retrieval
|
* #pw-group-retrieval
|
||||||
*
|
*
|
||||||
* @param string|array|Selectors|int $selector Selector string, array or Selectors object. May also be page path or ID.
|
* @param string|array|Selectors|int $selector Selector string, array or Selectors object. May also be page path or ID.
|
||||||
|
* @param array $options See `Pages::find()` for extra options that may be specified.
|
||||||
* @return Page|NullPage Always returns a Page object, but will return NullPage (with id=0) when no match found.
|
* @return Page|NullPage Always returns a Page object, but will return NullPage (with id=0) when no match found.
|
||||||
* @see Pages::findOne(), Pages::find()
|
* @see Pages::findOne(), Pages::find()
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function get($selector) {
|
public function get($selector, $options = array()) {
|
||||||
return $this->loader->get($selector);
|
return $this->loader->get($selector, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -40,6 +40,14 @@ class PagesLoader extends Wire {
|
|||||||
*/
|
*/
|
||||||
protected $nativeColumns = array();
|
protected $nativeColumns = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total number of pages loaded by getById()
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $totalPagesLoaded = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug mode for pages class
|
* Debug mode for pages class
|
||||||
*
|
*
|
||||||
@@ -220,6 +228,10 @@ class PagesLoader extends Wire {
|
|||||||
$pagesInfo = $pageFinder->find($selectors, $options);
|
$pagesInfo = $pageFinder->find($selectors, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($this->debug && empty($loadOptions['caller'])) {
|
||||||
|
$loadOptions['caller'] = "$caller($selectorString)";
|
||||||
|
}
|
||||||
|
|
||||||
// note that we save this pagination state here and set it at the end of this method
|
// note that we save this pagination state here and set it at the end of this method
|
||||||
// because it's possible that more find operations could be executed as the pages are loaded
|
// because it's possible that more find operations could be executed as the pages are loaded
|
||||||
$total = $pageFinder->getTotal();
|
$total = $pageFinder->getTotal();
|
||||||
@@ -309,10 +321,11 @@ class PagesLoader extends Wire {
|
|||||||
$note .= ": " . $pages->first()->path;
|
$note .= ": " . $pages->first()->path;
|
||||||
if($count > 1) $note .= " ... " . $pages->last()->path;
|
if($count > 1) $note .= " ... " . $pages->last()->path;
|
||||||
}
|
}
|
||||||
Debug::saveTimer("$caller($selectorString)", $note);
|
if(substr($caller, -1) !== ')') $caller .= "($selectorString)";
|
||||||
|
Debug::saveTimer($caller, $note);
|
||||||
foreach($pages as $item) {
|
foreach($pages as $item) {
|
||||||
if($item->_debug_loaded) continue;
|
if($item->_debug_loader) continue;
|
||||||
$item->setQuietly('_debug_loader', "$caller($selectorString)");
|
$item->setQuietly('_debug_loader', $caller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,21 +371,23 @@ class PagesLoader extends Wire {
|
|||||||
* Returns the first page matching the given selector with no exclusions
|
* Returns the first page matching the given selector with no exclusions
|
||||||
*
|
*
|
||||||
* @param string|int|array|Selectors $selector
|
* @param string|int|array|Selectors $selector
|
||||||
|
* @param array $options See Pages::find method for options
|
||||||
* @return Page|NullPage Always returns a Page object, but will return NullPage (with id=0) when no match found
|
* @return Page|NullPage Always returns a Page object, but will return NullPage (with id=0) when no match found
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function get($selector) {
|
public function get($selector, $options = array()) {
|
||||||
if(empty($selector)) return $this->pages->newNullPage();
|
if(empty($selector)) return $this->pages->newNullPage();
|
||||||
if(is_string($selector) || is_int($selector)) {
|
if(is_string($selector) || is_int($selector)) {
|
||||||
$page = $this->pages->getCache($selector);
|
$page = $this->pages->getCache($selector);
|
||||||
if($page) return $page;
|
if($page) return $page;
|
||||||
}
|
}
|
||||||
$options = array(
|
$defaults = array(
|
||||||
'findOne' => true, // find only one page
|
'findOne' => true, // find only one page
|
||||||
'findAll' => true, // no exclusions
|
'findAll' => true, // no exclusions
|
||||||
'getTotal' => false, // don't count totals
|
'getTotal' => false, // don't count totals
|
||||||
'caller' => 'pages.get'
|
'caller' => 'pages.get'
|
||||||
);
|
);
|
||||||
|
$options = count($options) ? array_merge($defaults, $options) : $defaults;
|
||||||
$page = $this->pages->find($selector, $options)->first();
|
$page = $this->pages->find($selector, $options)->first();
|
||||||
if(!$page) $page = $this->pages->newNullPage();
|
if(!$page) $page = $this->pages->newNullPage();
|
||||||
return $page;
|
return $page;
|
||||||
@@ -398,6 +413,7 @@ class PagesLoader extends Wire {
|
|||||||
* - pageClass: string, default=auto-detect. Class to instantiate Page objects with. Leave blank to determine from template.
|
* - pageClass: string, default=auto-detect. Class to instantiate Page objects with. Leave blank to determine from template.
|
||||||
* - pageArrayClass: string, default=PageArray. PageArray-derived class to store pages in (when 'getOne' is false).
|
* - pageArrayClass: string, default=PageArray. PageArray-derived class to store pages in (when 'getOne' is false).
|
||||||
* - page (Page|null): Existing Page object to populate (also requires the getOne option to be true). (default=null)
|
* - page (Page|null): Existing Page object to populate (also requires the getOne option to be true). (default=null)
|
||||||
|
* - caller (string): Name of calling function, for debugging purposes (default=blank).
|
||||||
*
|
*
|
||||||
* Use the $options array for potential speed optimizations:
|
* Use the $options array for potential speed optimizations:
|
||||||
* - Specify a 'template' with your call, when possible, so that this method doesn't have to determine it separately.
|
* - Specify a 'template' with your call, when possible, so that this method doesn't have to determine it separately.
|
||||||
@@ -434,6 +450,7 @@ class PagesLoader extends Wire {
|
|||||||
'page' => null,
|
'page' => null,
|
||||||
'pageClass' => '', // blank = auto detect
|
'pageClass' => '', // blank = auto detect
|
||||||
'pageArrayClass' => 'PageArray',
|
'pageArrayClass' => 'PageArray',
|
||||||
|
'caller' => '',
|
||||||
);
|
);
|
||||||
|
|
||||||
if(is_array($template)) {
|
if(is_array($template)) {
|
||||||
@@ -651,6 +668,7 @@ class PagesLoader extends Wire {
|
|||||||
$page->setOutputFormatting($this->outputFormatting);
|
$page->setOutputFormatting($this->outputFormatting);
|
||||||
$loaded[$page->id] = $page;
|
$loaded[$page->id] = $page;
|
||||||
if($options['cache']) $this->pages->cache($page);
|
if($options['cache']) $this->pages->cache($page);
|
||||||
|
$this->totalPagesLoaded++;
|
||||||
}
|
}
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
$error = $e->getMessage() . " [pageClass=$class, template=$template]";
|
$error = $e->getMessage() . " [pageClass=$class, template=$template]";
|
||||||
@@ -674,11 +692,18 @@ class PagesLoader extends Wire {
|
|||||||
if($this->debug) {
|
if($this->debug) {
|
||||||
$page = $this->wire('page');
|
$page = $this->wire('page');
|
||||||
if($page && $page->template == 'admin') {
|
if($page && $page->template == 'admin') {
|
||||||
$_template = is_null($template) ? '' : ", $template";
|
if(empty($options['caller'])) {
|
||||||
$_parent_id = is_null($parent_id) ? '' : ", $parent_id";
|
$_template = is_null($template) ? '' : ", $template";
|
||||||
$_ids = count($_ids) > 1 ? "[" . implode(',', $_ids) . "]" : implode('', $_ids);
|
$_parent_id = is_null($parent_id) ? '' : ", $parent_id";
|
||||||
|
if(count($_ids) > 10) {
|
||||||
|
$_ids = '[' . reset($_ids) . '…' . end($_ids) . ', ' . count($_ids) . ' pages]';
|
||||||
|
} else {
|
||||||
|
$_ids = count($_ids) > 1 ? "[" . implode(',', $_ids) . "]" : implode('', $_ids);
|
||||||
|
}
|
||||||
|
$options['caller'] = "pages.getById($_ids$_template$_parent_id)";
|
||||||
|
}
|
||||||
foreach($pages as $item) {
|
foreach($pages as $item) {
|
||||||
$item->setQuietly('_debug_loader', "getByID($_ids$_template$_parent_id)");
|
$item->setQuietly('_debug_loader', $options['caller']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1076,4 +1101,14 @@ class PagesLoader extends Wire {
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the total quantity of pages loaded by getById()
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function getTotalPagesLoaded() {
|
||||||
|
return $this->totalPagesLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -256,6 +256,7 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
|
|||||||
if(!isset($options['findAll'])) $options['findAll'] = true;
|
if(!isset($options['findAll'])) $options['findAll'] = true;
|
||||||
if(!isset($options['loadOptions'])) $options['loadOptions'] = array();
|
if(!isset($options['loadOptions'])) $options['loadOptions'] = array();
|
||||||
$options['loadOptions'] = $this->getLoadOptions($options['loadOptions']);
|
$options['loadOptions'] = $this->getLoadOptions($options['loadOptions']);
|
||||||
|
if(empty($options['caller'])) $options['caller'] = $this->className() . ".find($selectorString)";
|
||||||
$pages = $this->wire('pages')->find($this->selectorString($selectorString), $options);
|
$pages = $this->wire('pages')->find($this->selectorString($selectorString), $options);
|
||||||
/** @var PageArray $pages */
|
/** @var PageArray $pages */
|
||||||
foreach($pages as $page) {
|
foreach($pages as $page) {
|
||||||
@@ -271,13 +272,17 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
|
|||||||
/**
|
/**
|
||||||
* Get the first match of your selector string
|
* Get the first match of your selector string
|
||||||
*
|
*
|
||||||
* @param string $selectorString
|
* @param string|int $selectorString
|
||||||
* @return Page|null
|
* @return Page|NullPage|null
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function get($selectorString) {
|
public function get($selectorString) {
|
||||||
|
|
||||||
$options = $this->getLoadOptions(array('getOne' => true));
|
$options = $this->getLoadOptions(array('getOne' => true));
|
||||||
|
if(empty($options['caller'])) {
|
||||||
|
$caller = $this->className() . ".get($selectorString)";
|
||||||
|
$options['caller'] = $caller;
|
||||||
|
}
|
||||||
|
|
||||||
if(ctype_digit("$selectorString")) {
|
if(ctype_digit("$selectorString")) {
|
||||||
// selector string contains a page ID
|
// selector string contains a page ID
|
||||||
@@ -307,7 +312,10 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
|
|||||||
// selector string with operators, can pass through
|
// selector string with operators, can pass through
|
||||||
}
|
}
|
||||||
|
|
||||||
$page = $this->pages->get($this->selectorString($selectorString), array('loadOptions' => $options));
|
$page = $this->pages->get($this->selectorString($selectorString), array(
|
||||||
|
'caller' => $caller,
|
||||||
|
'loadOptions' => $options
|
||||||
|
));
|
||||||
if($page->id && !$this->isValid($page)) $page = $this->wire('pages')->newNullPage();
|
if($page->id && !$this->isValid($page)) $page = $this->wire('pages')->newNullPage();
|
||||||
if($page->id) $this->loaded($page);
|
if($page->id) $this->loaded($page);
|
||||||
|
|
||||||
@@ -392,7 +400,9 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function getIterator() {
|
public function getIterator() {
|
||||||
return $this->find("id>0, sort=name");
|
return $this->find("id>0, sort=name", array(
|
||||||
|
'caller' => $this->className() . '.getIterator()'
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -168,6 +168,7 @@ class Languages extends PagesType {
|
|||||||
$selector = "parent_id=$parent_id, template=$template, include=all, sort=sort";
|
$selector = "parent_id=$parent_id, template=$template, include=all, sort=sort";
|
||||||
$languagesAll = $this->wire('pages')->find($selector, array(
|
$languagesAll = $this->wire('pages')->find($selector, array(
|
||||||
'loadOptions' => $this->getLoadOptions(),
|
'loadOptions' => $this->getLoadOptions(),
|
||||||
|
'caller' => $this->className() . '.getAll()'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if(count($languagesAll)) $this->languagesAll = $languagesAll;
|
if(count($languagesAll)) $this->languagesAll = $languagesAll;
|
||||||
|
@@ -61,6 +61,12 @@
|
|||||||
* @property int $editOption Edit option setting, used only by ListerPro
|
* @property int $editOption Edit option setting, used only by ListerPro
|
||||||
* @property bool $responsiveTable Whether or not Lister table should be responsive rather than horiz scroll
|
* @property bool $responsiveTable Whether or not Lister table should be responsive rather than horiz scroll
|
||||||
*
|
*
|
||||||
|
* @method string buildListerTableColActions(Page $p, $value)
|
||||||
|
* @method string renderResults($selector = null)
|
||||||
|
* @method string getSelector($limit = null)
|
||||||
|
* @method PageArray findResults($selector)
|
||||||
|
* @method string executeReset()
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* @todo make system fields hookable for output like markupValue is for custom fields
|
* @todo make system fields hookable for output like markupValue is for custom fields
|
||||||
* @todo show bookmark title somewhere on page so users know what they are looking at (+ browser title?)
|
* @todo show bookmark title somewhere on page so users know what they are looking at (+ browser title?)
|
||||||
@@ -484,7 +490,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
*
|
*
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return this
|
* @return ProcessPageLister|Process
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function set($key, $value) {
|
public function set($key, $value) {
|
||||||
@@ -568,7 +574,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
if(!is_null($sort)) {
|
if(!is_null($sort)) {
|
||||||
$sort = $this->sanitizer->name($sort);
|
$sort = $this->sanitizer->name($sort);
|
||||||
$this->sessionSet("sort", $sort);
|
$this->sessionSet("sort", $sort);
|
||||||
$this->sort = $sort;
|
$this->set('sort', $sort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,6 +587,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
$fields = $this->template ? $this->template->fieldgroup : $this->wire('fields');
|
$fields = $this->template ? $this->template->fieldgroup : $this->wire('fields');
|
||||||
$options = $this->getSystemColumns();
|
$options = $this->getSystemColumns();
|
||||||
|
|
||||||
|
/** @var InputfieldAsmSelect $f */
|
||||||
$f = $this->modules->get('InputfieldAsmSelect');
|
$f = $this->modules->get('InputfieldAsmSelect');
|
||||||
$f->attr('name', 'columns');
|
$f->attr('name', 'columns');
|
||||||
$f->label = $this->_('Default columns');
|
$f->label = $this->_('Default columns');
|
||||||
@@ -656,6 +663,9 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
/**
|
/**
|
||||||
* Whether or not to allow the given $field as a column, for buildColumnsField
|
* Whether or not to allow the given $field as a column, for buildColumnsField
|
||||||
*
|
*
|
||||||
|
* @param Field $field
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
protected function allowColumnField(Field $field) {
|
protected function allowColumnField(Field $field) {
|
||||||
|
|
||||||
@@ -696,6 +706,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
*/
|
*/
|
||||||
protected function buildColumnsForm() {
|
protected function buildColumnsForm() {
|
||||||
|
|
||||||
|
/** @var InputfieldForm $form */
|
||||||
$form = $this->modules->get('InputfieldForm');
|
$form = $this->modules->get('InputfieldForm');
|
||||||
$form->attr('id', 'ProcessListerColumnsForm');
|
$form->attr('id', 'ProcessListerColumnsForm');
|
||||||
$form->method = 'get';
|
$form->method = 'get';
|
||||||
@@ -721,6 +732,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
*/
|
*/
|
||||||
protected function buildFiltersForm() {
|
protected function buildFiltersForm() {
|
||||||
|
|
||||||
|
/** @var InputfieldForm $form */
|
||||||
$form = $this->modules->get('InputfieldForm');
|
$form = $this->modules->get('InputfieldForm');
|
||||||
$form->attr('id', 'ProcessListerFiltersForm');
|
$form->attr('id', 'ProcessListerFiltersForm');
|
||||||
$form->method = 'get';
|
$form->method = 'get';
|
||||||
@@ -734,6 +746,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
if(in_array('noNewFilters', $this->toggles)) $f->allowAddRemove = false;
|
if(in_array('noNewFilters', $this->toggles)) $f->allowAddRemove = false;
|
||||||
$form->add($f);
|
$form->add($f);
|
||||||
|
|
||||||
|
/** @var InputfieldHidden $f */
|
||||||
$f = $this->modules->get('InputfieldHidden');
|
$f = $this->modules->get('InputfieldHidden');
|
||||||
$f->attr('name', 'sort');
|
$f->attr('name', 'sort');
|
||||||
$f->attr('id', 'lister_sort');
|
$f->attr('id', 'lister_sort');
|
||||||
@@ -1033,6 +1046,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
*/
|
*/
|
||||||
protected function buildListerTable(PageArray $results) {
|
protected function buildListerTable(PageArray $results) {
|
||||||
|
|
||||||
|
/** @var MarkupAdminDataTable $table */
|
||||||
$table = $this->modules->get('MarkupAdminDataTable');
|
$table = $this->modules->get('MarkupAdminDataTable');
|
||||||
$table->setSortable(false);
|
$table->setSortable(false);
|
||||||
$table->setResizable(true);
|
$table->setResizable(true);
|
||||||
@@ -1141,8 +1155,8 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
$delimiter = isset($this->delimiters[$fullname]) ? $this->delimiters[$fullname] : "<br />";
|
$delimiter = isset($this->delimiters[$fullname]) ? $this->delimiters[$fullname] : "<br />";
|
||||||
|
|
||||||
if(!$subname && ($value instanceof Page || $value instanceof PageArray)) {
|
if(!$subname && ($value instanceof Page || $value instanceof PageArray)) {
|
||||||
if($field && $field->labelFieldName) {
|
if($field && $field->get('labelFieldName')) {
|
||||||
$subname = $field->labelFieldName;
|
$subname = $field->get('labelFieldName');
|
||||||
if($this->wire('sanitizer')->fieldName($subname) == $subname) $subname .= "|name"; // fallback
|
if($this->wire('sanitizer')->fieldName($subname) == $subname) $subname .= "|name"; // fallback
|
||||||
} else {
|
} else {
|
||||||
$subname = 'title|name';
|
$subname = 'title|name';
|
||||||
@@ -1219,6 +1233,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
if($subname == 'data') $v = (string) $v;
|
if($subname == 'data') $v = (string) $v;
|
||||||
if($subname && is_object($v)) $v = $v->$subname;
|
if($subname && is_object($v)) $v = $v->$subname;
|
||||||
if($v instanceof Pageimage) {
|
if($v instanceof Pageimage) {
|
||||||
|
/** @var Pageimage $v */
|
||||||
$vfull = $v;
|
$vfull = $v;
|
||||||
if($this->imageWidth || $this->imageHeight) $v = $v->size($this->imageWidth, $this->imageHeight);
|
if($this->imageWidth || $this->imageHeight) $v = $v->size($this->imageWidth, $this->imageHeight);
|
||||||
$alt = $vfull->basename . ($vfull->description ? ' - ' . $this->sanitizer->entities1($vfull->description) : "");
|
$alt = $vfull->basename . ($vfull->description ? ' - ' . $this->sanitizer->entities1($vfull->description) : "");
|
||||||
@@ -1226,6 +1241,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
$isImage = true;
|
$isImage = true;
|
||||||
|
|
||||||
} else if($v instanceof Pagefile) {
|
} else if($v instanceof Pagefile) {
|
||||||
|
/** @var Pageimage $v */
|
||||||
$v = "<a target='_blank' href='$v->url'>$v->basename</a>";
|
$v = "<a target='_blank' href='$v->url'>$v->basename</a>";
|
||||||
} else {
|
} else {
|
||||||
$v = $this->wire('sanitizer')->entities($v);
|
$v = $this->wire('sanitizer')->entities($v);
|
||||||
@@ -1291,7 +1307,6 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
*/
|
*/
|
||||||
protected function ___buildListerTableColActions(Page $p, $value) {
|
protected function ___buildListerTableColActions(Page $p, $value) {
|
||||||
$class = '';
|
$class = '';
|
||||||
$icon = '';
|
|
||||||
$statusIcon = '';
|
$statusIcon = '';
|
||||||
$isTrash = false;
|
$isTrash = false;
|
||||||
if(!strlen($value)) $value = $this->blankLabel;
|
if(!strlen($value)) $value = $this->blankLabel;
|
||||||
@@ -1548,13 +1563,13 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
$total = $results->getTotal();
|
$total = $results->getTotal();
|
||||||
$end = $start+$count;
|
$end = $start+$count;
|
||||||
$pagerOut = '';
|
$pagerOut = '';
|
||||||
$errorOut = '';
|
|
||||||
|
|
||||||
if(count($results)) {
|
if(count($results)) {
|
||||||
$table = $this->buildListerTable($results);
|
$table = $this->buildListerTable($results);
|
||||||
$tableOut = $table->render();
|
$tableOut = $table->render();
|
||||||
$headline = sprintf($this->_('%1$d to %2$d of %3$d'), $start+1, $end, $total);
|
$headline = sprintf($this->_('%1$d to %2$d of %3$d'), $start+1, $end, $total);
|
||||||
if($total > $limit) {
|
if($total > $limit) {
|
||||||
|
/** @var MarkupPagerNav $pager */
|
||||||
$pager = $this->modules->get('MarkupPagerNav');
|
$pager = $this->modules->get('MarkupPagerNav');
|
||||||
$pagerOut = $pager->render($results);
|
$pagerOut = $pager->render($results);
|
||||||
$pageURL = $this->wire('page')->url;
|
$pageURL = $this->wire('page')->url;
|
||||||
@@ -1650,7 +1665,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function ___execute() {
|
public function ___execute() {
|
||||||
if(!$this->wire('page')) return;
|
if(!$this->wire('page')) return '';
|
||||||
$modules = $this->wire('modules');
|
$modules = $this->wire('modules');
|
||||||
|
|
||||||
$this->setupOpenPageIDs();
|
$this->setupOpenPageIDs();
|
||||||
@@ -1803,7 +1818,6 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
$loadedFilesAdd = array();
|
$loadedFilesAdd = array();
|
||||||
$loadedJSConfig = $this->sessionGet('loadedJSConfig');
|
$loadedJSConfig = $this->sessionGet('loadedJSConfig');
|
||||||
$config = $this->wire('config');
|
$config = $this->wire('config');
|
||||||
$out = '';
|
|
||||||
|
|
||||||
foreach($config->scripts as $file) {
|
foreach($config->scripts as $file) {
|
||||||
if(strpos($file, 'ProcessPageLister')) continue;
|
if(strpos($file, 'ProcessPageLister')) continue;
|
||||||
@@ -1875,7 +1889,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
* Implementation for ./edit-bookmark/ URL segment
|
* Implementation for ./edit-bookmark/ URL segment
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws WirePermissionException
|
* @throws WirePermissionException|WireException
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function ___executeEditBookmark() {
|
public function ___executeEditBookmark() {
|
||||||
@@ -1886,6 +1900,9 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
/**
|
/**
|
||||||
* Output JSON list of navigation items for this module's bookmarks
|
* Output JSON list of navigation items for this module's bookmarks
|
||||||
*
|
*
|
||||||
|
* @param array $options
|
||||||
|
* @return string|array
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function ___executeNavJSON(array $options = array()) {
|
public function ___executeNavJSON(array $options = array()) {
|
||||||
|
|
||||||
@@ -1956,6 +1973,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function getModuleConfigInputfields(array $data) {
|
public static function getModuleConfigInputfields(array $data) {
|
||||||
|
if($data) {} // ignore
|
||||||
$inputfields = new InputfieldWrapper();
|
$inputfields = new InputfieldWrapper();
|
||||||
return $inputfields;
|
return $inputfields;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,19 @@
|
|||||||
<?php namespace ProcessWire;
|
<?php namespace ProcessWire;
|
||||||
|
|
||||||
|
/** @var Config $config */
|
||||||
|
/** @var Pages $pages */
|
||||||
|
/** @var Sanitizer $sanitizer */
|
||||||
|
/** @var Session $session */
|
||||||
|
/** @var WireInput $input */
|
||||||
|
/** @var Fuel $fuel */
|
||||||
|
/** @var Modules $modules */
|
||||||
|
/** @var WireDatabasePDO $database */
|
||||||
|
/** @var DatabaseMysqli $db */
|
||||||
|
/** @var User $user */
|
||||||
|
/** @var Page $page */
|
||||||
|
/** @var WireCache $cache */
|
||||||
|
/** @var WireClassLoader $classLoader */
|
||||||
|
|
||||||
if(!defined("PROCESSWIRE")) die();
|
if(!defined("PROCESSWIRE")) die();
|
||||||
$debugToolsLabel = __('Debug Mode Tools', __FILE__);
|
$debugToolsLabel = __('Debug Mode Tools', __FILE__);
|
||||||
|
|
||||||
@@ -19,6 +33,7 @@ $debugToolsLabel = __('Debug Mode Tools', __FILE__);
|
|||||||
<?php
|
<?php
|
||||||
$o = '';
|
$o = '';
|
||||||
$oc = 0;
|
$oc = 0;
|
||||||
|
$oct = $pages->loader()->getTotalPagesLoaded();
|
||||||
foreach($pages->getCache() as $p) {
|
foreach($pages->getCache() as $p) {
|
||||||
$oc++;
|
$oc++;
|
||||||
$parts = explode('/', trim($p->path, '/'));
|
$parts = explode('/', trim($p->path, '/'));
|
||||||
@@ -30,12 +45,13 @@ $debugToolsLabel = __('Debug Mode Tools', __FILE__);
|
|||||||
"<td>$p->id</td>" .
|
"<td>$p->id</td>" .
|
||||||
"<td>$path</td>" .
|
"<td>$path</td>" .
|
||||||
"<td>" . wireClassName($p) . "</td>" .
|
"<td>" . wireClassName($p) . "</td>" .
|
||||||
"<td>$p->_debug_loader</td>" .
|
($config->debug === Config::debugVerbose ? "<td>" . $sanitizer->entities($p->_debug_loader) . "</td>" : "") .
|
||||||
"</tr>";
|
"</tr>";
|
||||||
}
|
}
|
||||||
|
$occ = $oct > $oc ? "$oc/$oct" : $oc;
|
||||||
?>
|
?>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h3><a href='#'><?php echo __('Pages Loaded', __FILE__) . " <span class='ui-priority-secondary'>($oc)</span>"; ?></a></h3>
|
<h3><a href='#'><?php echo __('Pages Loaded', __FILE__) . " <span class='ui-priority-secondary'>($occ)</span>"; ?></a></h3>
|
||||||
<div>
|
<div>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
@@ -43,11 +59,15 @@ $debugToolsLabel = __('Debug Mode Tools', __FILE__);
|
|||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th>Path</th>
|
<th>Path</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Loader</th>
|
<?php if($config->debug === Config::debugVerbose) echo "<th>Loader</th>"; ?>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php echo $o; unset($o, $oc); ?>
|
<?php
|
||||||
|
echo $o;
|
||||||
|
if($oct > $oc) echo "<p>A total of <strong>$oct</strong> pages were loaded, <strong>$oc</strong> of which are in memory:</p>";
|
||||||
|
unset($o, $oc, $oct, $occ);
|
||||||
|
?>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user