From 3de5d4d2a6a54c24b7f84f32cb95ad5f0f601b0d Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 29 Jan 2021 15:04:44 -0500 Subject: [PATCH] Add a getFresh() method to PagesLoader and improve cache detection for the get() method --- wire/core/PagesLoader.php | 63 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/wire/core/PagesLoader.php b/wire/core/PagesLoader.php index 4a7fae3a..138d396f 100644 --- a/wire/core/PagesLoader.php +++ b/wire/core/PagesLoader.php @@ -559,7 +559,7 @@ class PagesLoader extends Wire { return $page && $page->id ? $page : $this->pages->newNullPage(); } - + /** * Returns the first page matching the given selector with no exclusions * @@ -569,20 +569,39 @@ class PagesLoader extends Wire { * */ public function get($selector, $options = array()) { + if(empty($selector)) return $this->pages->newNullPage(); - if(is_string($selector) || is_int($selector)) { - $page = $this->pages->getCache($selector); - if($page) return $page; + + if(is_int($selector)) { + $getCache = true; + } else if(is_string($selector) && (ctype_digit($selector) || strpos($selector, 'id=') === 0)) { + $getCache = true; + } else { + $getCache = false; } + + if($getCache) { + // if cache is possible, allow user-specified options to dictate whether cache is allowed + if(isset($options['loadOptions']) && isset($options['loadOptions']['getFromCache'])) { + $getCache = (bool) $options['loadOptions']['getFromCache']; + } + if($getCache) { + $page = $this->pages->getCache($selector); // selector is either 123 or id=123 + if($page) return $page; + } + } + $defaults = array( 'findOne' => true, // find only one page 'findAll' => true, // no exclusions 'getTotal' => false, // don't count totals 'caller' => 'pages.get' ); + $options = count($options) ? array_merge($defaults, $options) : $defaults; $page = $this->pages->find($selector, $options)->first(); if(!$page) $page = $this->pages->newNullPage(); + return $page; } @@ -1283,6 +1302,42 @@ class PagesLoader extends Wire { 'getOne' => true )); } + + /** + * Get a fresh, non-cached copy of a Page from the database + * + * This method is the same as `$pages->get()` except that it skips over all memory caches when loading a Page. + * Meaning, if the Page is already in memory, it doesn’t use the one in memory and instead reloads from the DB. + * Nor does it place the Page it loads in any memory cache. Use this method to load a fresh copy of a page + * that you might need to compare to an existing loaded copy, or to load a copy that won’t be seen or touched + * by anything in ProcessWire other than your own code. + * + * ~~~~~ + * $p1 = $pages->get(1234); + * $p2 = $pages->get($p1->path); + * $p1 === $p2; // true: same Page instance + * + * $p3 = $pages->getFresh($p1); + * $p1 === $p3; // false: same Page but different instance + * ~~~~~ + * + * #pw-advanced + * + * @param Page|string|array|Selectors|int $selectorOrPage Specify Page to get copy of, selector or ID + * @param array $options Options to modify behavior + * @return Page|NullPage + * @since 3.0.172 + * + */ + public function getFresh($selectorOrPage, $options = array()) { + if(!isset($options['cache'])) $options['cache'] = false; + if(!isset($options['loadOptions'])) $options['loadOptions'] = array(); + if(!isset($options['caller'])) $options['caller'] = 'pages.loader.getFresh'; + $options['loadOptions']['getFromCache'] = false; + if(!isset($options['loadOptions']['cache'])) $options['loadOptions']['cache'] = false; + $selector = $selectorOrPage instanceof Page ? $selectorOrPage->id : $selectorOrPage; + return $this->get($selector, $options); + } /** * Count and return how many pages will match the given selector string