From 4276a5d9174f4213dbd37e76146f69941282a393 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 26 Jun 2020 09:43:43 -0400 Subject: [PATCH] Update PageFinder to support altOperators in selectors. This enables you to use more than one operator in a selector. For example, if you wanted to first try to find pages matching a phrase (*=), and if it doesn't find any, fallback to find pages matching words (~=), you can just append the two opers together. i.e. "field*=~=value". This works for any operator combinations and you can stack as many as you need. --- wire/core/PageFinder.php | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/wire/core/PageFinder.php b/wire/core/PageFinder.php index 2266f1b9..165577a9 100644 --- a/wire/core/PageFinder.php +++ b/wire/core/PageFinder.php @@ -326,6 +326,14 @@ class PageFinder extends Wire { */ protected $finalSelectors = null; // Fully parsed final selectors + /** + * Number of Selector objects that have alternate operators + * + * @var int + * + */ + protected $numAltOperators = 0; + /** * Fields that can only be used by themselves (not OR'd with other fields) * @@ -684,6 +692,11 @@ class PageFinder extends Wire { } else { $this->total = count($matches); } + + if(!$this->total && $this->numAltOperators) { + // check if any selectors provided alternate operators to try + $matches = $this->findAlt($selectors, $options, $matches); + } $this->lastOptions = $options; @@ -691,6 +704,33 @@ class PageFinder extends Wire { return $matches; } + + /** + * Perform an alternate/fallback find when first fails to match and alternate operators available + * + * @param Selectors $selectors + * @param array $options + * @param array $matches + * @return array + * + */ + protected function findAlt($selectors, $options, $matches) { + // check if any selectors provided alternate operators to try + $numAlts = 0; + foreach($selectors as $key => $selector) { + $altOperators = $selector->altOperators; + if(!count($altOperators)) continue; + $altOperator = array_shift($altOperators); + $sel = Selectors::getSelectorByOperator($altOperator); + if(!$sel) continue; + $selector->copyTo($sel); + $selectors[$key] = $sel; + $numAlts++; + } + if(!$numAlts) return $matches; + $this->numAltOperators = 0; + return $this->___find($selectors, $options); + } /** * Same as find() but returns just a simple array of page IDs without any other info @@ -1377,6 +1417,7 @@ class PageFinder extends Wire { $joins = array(); $database = $this->wire('database'); $this->preProcessSelectors($selectors, $options); + $this->numAltOperators = 0; if($options['returnAllCols']) { $columns = array('pages.*'); @@ -1418,6 +1459,7 @@ class PageFinder extends Wire { $fields = is_array($fields) ? $fields : array($fields); if(count($fields) > 1) $fields = $this->arrangeFields($fields); $field1 = reset($fields); // first field including optional subfield + $this->numAltOperators += count($selector->altOperators); // TODO Make native fields and path/url multi-field and multi-value aware if($field1 === 'sort' && $selector->operator === '=') {