1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-14 10:45:54 +02:00

Add PageFinder support for partial match operator on parent.path selectors like: parent.path%=something

This commit is contained in:
Ryan Cramer
2019-06-19 10:34:26 -04:00
parent 62b81164a0
commit 3577b81591

View File

@@ -169,6 +169,7 @@ class PageFinder extends Wire {
protected $sortsAfter = array(); // apply these sorts after pages loaded
protected $reverseAfter = false; // reverse order after load?
protected $pageArrayData = array(); // any additional data that should be populated back to any resulting PageArray objects
protected $partialMatchOperators = array('%=', '^=', '$=', '%^=', '%$=', '*=');
protected $singlesFields = array( // fields that can only be used by themselves (not OR'd with other fields)
'has_parent',
'hasParent',
@@ -2048,6 +2049,7 @@ class PageFinder extends Wire {
// the following fields are defined in each iteration here because they may be modified in the loop
$table = "pages";
$operator = $selector->operator;
$isPartialOperator = in_array($operator, $this->partialMatchOperators);
$subfield = '';
$IDs = array(); // populated in special cases where we can just match parent IDs
$sql = '';
@@ -2073,7 +2075,7 @@ class PageFinder extends Wire {
if($isParent || $isChildren || $isPages) {
// parent, children, pages
if(($isPages || $isParent) && (!$subfield || in_array($subfield, array('id', 'path', 'url')))) {
if(($isPages || $isParent) && !$isPartialOperator && (!$subfield || in_array($subfield, array('id', 'path', 'url')))) {
// match by location (id or path)
// convert parent fields like '/about/company/history' to the equivalent ID
foreach($values as $k => $v) {
@@ -2104,11 +2106,7 @@ class PageFinder extends Wire {
$s = '';
if($field === 'children') $finderMethod = 'findParentIDs';
// inherit include mode from main selector
$includeSelector = trim(
$selectors->getSelectorByField('include') . ',' .
$selectors->getSelectorByField('status') . ',' .
$selectors->getSelectorByField('check_access'), ','
);
$includeSelector = $this->getIncludeSelector($selectors);
} else if($field === 'children') {
$s = 'children.id';
} else {
@@ -2174,6 +2172,7 @@ class PageFinder extends Wire {
}
$isName = $field === 'name' || strpos($field, 'name') === 0;
$isPath = $field === 'path' || $field === 'url';
if($isName && $operator == '~=') {
// handle one or more space-separated full words match to 'name' field in any order
@@ -2183,13 +2182,23 @@ class PageFinder extends Wire {
$s .= ($s ? ' AND ' : '') . "$table.$field RLIKE '" . '[[:<:]]' . $word . '[[:>:]]' . "'";
}
} else if($isName && in_array($operator, array('%=', '^=', '$=', '%^=', '%$=', '*='))) {
} else if($isName && $isPartialOperator) {
// handle partial match to 'name' field
$value = $database->escapeStr($sanitizer->pageName($value, Sanitizer::toAscii));
if($operator == '^=' || $operator == '%^=') $value = "$value%";
else if($operator == '$=' || $operator == '%$=') $value = "%$value";
else $value = "%$value%";
$s = "$table.$field LIKE '$value'";
} else if($isPath && $isPartialOperator) {
// partial match of path (used when original selector is parent.path%=...)
$tempSelector = trim($this->getIncludeSelector($selectors) . ", $field$operator" . $sanitizer->selectorValue($value), ',');
$tempIDs = $sanitizer->intArray($this->wire('pages')->findIDs($tempSelector));
if(count($tempIDs)) {
$s = "$table.id IN(" . implode(',', $tempIDs) . ')';
} else {
$s = "$table.id=-1"; // force non-match
}
} else if(!$database->isOperator($operator)) {
throw new PageFinderSyntaxException("Operator '{$operator}' is not supported for '$field'.");
@@ -2229,6 +2238,22 @@ class PageFinder extends Wire {
//$this->nativeWheres[] = $SQL;
}
/**
* Get the include|status|check_access portions from given Selectors and return selector string for them
*
* @param Selectors|string $selectors
* @return string
*
*/
protected function getIncludeSelector($selectors) {
if(!$selectors instanceof Selectors) $selectors = new Selectors($selectors);
return trim(
$selectors->getSelectorByField('include') . ',' .
$selectors->getSelectorByField('status') . ',' .
$selectors->getSelectorByField('check_access'), ','
);
}
/**
* Make the query specific to all pages below a certain parent (children, grandchildren, great grandchildren, etc.)
*