From a751edf51bc283f185731d25e912cfbe80b2dd42 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 18 Sep 2020 14:27:02 -0400 Subject: [PATCH] Update PageFinder and Fieldtype interface so that Fieldtype modules can optionally take over sorting of their own fields/subfields in PageFinder searches. --- wire/core/Fieldtype.php | 22 ++++++++++++++++++++++ wire/core/PageFinder.php | 30 ++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/wire/core/Fieldtype.php b/wire/core/Fieldtype.php index 7378f2a6..de6ebc1f 100644 --- a/wire/core/Fieldtype.php +++ b/wire/core/Fieldtype.php @@ -726,6 +726,28 @@ abstract class Fieldtype extends WireData implements Module { return $query; } + /** + * Get or update query to sort by given $field or $subfield + * + * Return false if this Fieldtype does not have built-in sort logic and PageFinder should handle it. + * Return string of query to add to ORDER BY statement, or boolean true if method added it already. + * + * #pw-internal + * + * @param Field $field + * @param DatabaseQuerySelect $query + * @param string $table + * @param string $subfield + * @param bool $desc True for descending, false for ascending + * @return bool|string + * @since 3.0.167 + * + */ + public function getMatchQuerySort(Field $field, $query, $table, $subfield, $desc) { + if($query && $table && $field && $subfield && $desc) {} + return false; + } + /** * Create a new field table in the database. * diff --git a/wire/core/PageFinder.php b/wire/core/PageFinder.php index ef3a6af7..d88e4b9b 100644 --- a/wire/core/PageFinder.php +++ b/wire/core/PageFinder.php @@ -2104,10 +2104,13 @@ class PageFinder extends Wire { foreach($values as $value) { $fc = substr($value, 0, 1); - $lc = substr($value, -1); + $lc = substr($value, -1); + $descending = $fc == '-' || $lc == '-'; $value = trim($value, "-+"); $subValue = ''; // $terValue = ''; // not currently used, here for future use + + if($this->lastOptions['reverseSort']) $descending = !$descending; if(strpos($value, ".")) { list($value, $subValue) = explode(".", $value, 2); // i.e. some_field.title @@ -2186,8 +2189,15 @@ class PageFinder extends Wire { } $query->leftjoin("$table AS $tableAlias ON $tableAlias.pages_id=pages.$idColumn"); + + $customValue = $field->type->getMatchQuerySort($field, $query, $tableAlias, $subValue, $descending); + + if(!empty($customValue)) { + // Fieldtype handled it: boolean true (handled by Fieldtype) or string to add to orderby + if(is_string($customValue)) $query->orderby($customValue, true); + $value = false; - if($subValue === 'count') { + } else if($subValue === 'count') { if($this->isRepeaterFieldtype($field->type)) { // repeaters have a native count column that can be used for sorting $value = "$tableAlias.count"; @@ -2212,7 +2222,7 @@ class PageFinder extends Wire { } else if($subValue == 'parent') { $query->leftjoin("pages AS $tableAlias2 ON $tableAlias.data=$tableAlias2.$idColumn"); $value = "$tableAlias2.name"; - + } else { $subValueField = $this->fields->get($subValue); if($subValueField) { @@ -2237,13 +2247,13 @@ class PageFinder extends Wire { $value = "$tableAlias." . ($subValue ? $subValue : "data"); ; } } - - $descending = $fc == '-' || $lc == '-'; - if($this->lastOptions['reverseSort']) $descending = !$descending; - if($descending) { - $query->orderby("$value DESC", true); - } else { - $query->orderby("$value", true); + + if(is_string($value) && strlen($value)) { + if($descending) { + $query->orderby("$value DESC", true); + } else { + $query->orderby("$value", true); + } } } }