From 916ac6f5c5e76a6d165105274ada8cf0a6ebc615 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Fri, 23 Jul 2021 09:50:35 -0400 Subject: [PATCH] Add option to force use of LIKE in DatabaseQuerySelectFulltext class, for when operating on columns that lack fulltext indexes --- wire/core/DatabaseQuery.php | 6 ++- wire/core/DatabaseQuerySelectFulltext.php | 45 ++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/wire/core/DatabaseQuery.php b/wire/core/DatabaseQuery.php index 31cdb715..8d0d6320 100644 --- a/wire/core/DatabaseQuery.php +++ b/wire/core/DatabaseQuery.php @@ -745,7 +745,11 @@ abstract class DatabaseQuery extends WireData { if($exception && $options['throw']) { if($this->wire()->config->allowExceptions) throw $exception; // throw original - throw new WireDatabaseQueryException($exception->getMessage(), $exception->getCode(), $exception); + $message = (string) $exception->getMessage(); + $code = (int) $exception->getCode(); + // note: re-throw below complains about wrong arguments if the above two + // lines are called in the line below, so variables are intermediary + throw new WireDatabaseQueryException($message, $code, $exception); } return $options['returnQuery'] ? $query : $result; diff --git a/wire/core/DatabaseQuerySelectFulltext.php b/wire/core/DatabaseQuerySelectFulltext.php index 2a056828..806b0fe1 100644 --- a/wire/core/DatabaseQuerySelectFulltext.php +++ b/wire/core/DatabaseQuerySelectFulltext.php @@ -20,7 +20,7 @@ * This file is licensed under the MIT license * https://processwire.com/about/license/mit/ * - * ProcessWire 3.x, Copyright 2020 by Ryan Cramer + * ProcessWire 3.x, Copyright 2021 by Ryan Cramer * https://processwire.com * * @property-read $tableField @@ -134,6 +134,28 @@ class DatabaseQuerySelectFulltext extends Wire { 'matchLikeStartEnd' => array('%^=', '%$='), 'matchCommands' => array('#='), ); + + /** + * Alternate operators to substitute when LIKE match is forced due to no FULLTEXT index + * + * @var array of operator to replacement operator + * + */ + protected $likeAlternateOperators = array( + '*=' => '%=', + '^=' => '%^=', + '$=' => '%$=', + '~=' => '~%=', + '~|=' => '~|%=', + ); + + /** + * Force use of LIKE? + * + * @var bool + * + */ + protected $forceLike = false; /** * Construct @@ -280,6 +302,10 @@ class DatabaseQuerySelectFulltext extends Wire { // if allowOrder has not been specifically set, then set value now if($this->allowOrder === null) $this->allowOrder = $allowOrder; + if($this->forceLike && isset($this->likeAlternateOperators[$operator])) { + $operator = $this->likeAlternateOperators[$operator]; + } + $this->operator = $operator; foreach($this->methodOperators as $name => $operators) { @@ -1380,4 +1406,21 @@ class DatabaseQuerySelectFulltext extends Wire { if($word) {} return ''; } + + /** + * Call forceLike(true) to force use of LIKE, or omit argument to get current setting + * + * This forces LIKE only for matching operators that have a LIKE equivalent. + * This includes these operators: `*=`, `^=`, `$=`, `~=`, `~|=`. + * + * @param bool|null $forceLike + * @return bool + * @since 3.0.182 + * + */ + public function forceLike($forceLike = null) { + if(is_bool($forceLike)) $this->forceLike = $forceLike; + return $this->forceLike; + + } }