1
0
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:
Ryan Cramer
2016-12-14 11:02:32 -05:00
parent 3821dc2be3
commit 2b9a7adbcb
10 changed files with 343 additions and 181 deletions

View File

@@ -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

View File

@@ -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
* *

View File

@@ -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;
}
} }

View File

@@ -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 pages 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 pages 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)
* *

View File

@@ -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);
} }
/** /**

View File

@@ -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;
}
} }

View File

@@ -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()'
));
} }
/** /**

View File

@@ -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;

View File

@@ -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;
} }

View File

@@ -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>