From 53374972ef6dd784f5c56bf88a2d8ef333e132d3 Mon Sep 17 00:00:00 2001 From: Sarjuuk Date: Mon, 19 Jan 2026 19:30:03 +0100 Subject: [PATCH] Search/Fixup * strip leading/trailing dashes from search tokens. Casues FT syntax errors when combined with our own modifiers --- includes/components/filter.class.php | 49 ++++++++++++++++++---------- includes/components/search.class.php | 12 +++++++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/includes/components/filter.class.php b/includes/components/filter.class.php index 15b13dda..b9e0015c 100644 --- a/includes/components/filter.class.php +++ b/includes/components/filter.class.php @@ -556,7 +556,7 @@ abstract class Filter return false; } - protected function transformToken(string $string, string $outPH) : string + protected function transformToken(string $string, bool $exact) : string { // escape manually entered _; entering % should be prohibited $string = str_replace('_', '\\_', $string); @@ -564,7 +564,7 @@ abstract class Filter // now replace search wildcards with sql wildcards $string = strtr($string, self::$wCards); - return sprintf($outPH, $string); + return sprintf($exact ? '%s' : '%%%s%%', $string); } protected function tokenizeString(array $fields, string $string = '', bool $exact = false, bool $shortStr = false) : array @@ -579,14 +579,14 @@ abstract class Filter $qry = []; foreach ($fields as $f) { - $sub = []; - $parts = $exact ? [$string] : array_filter(explode(' ', $string)); - foreach ($parts as $p) + $sub = []; + $tokens = $exact ? [$string] : array_filter(explode(' ', $string)); + foreach ($tokens as $t) { - if ($p[0] == '-' && (mb_strlen($p) > 3 || $shortStr)) - $sub[] = [$f, $this->transformToken(mb_substr($p, 1), $exact ? '%s' : '%%%s%%'), '!']; - else if ($p[0] != '-' && (mb_strlen($p) > 2 || $shortStr)) - $sub[] = [$f, $this->transformToken($p, $exact ? '%s' : '%%%s%%')]; + if ($t[0] == '-' && (mb_strlen($t) > 3 || $shortStr)) + $sub[] = [$f, $this->transformToken(mb_substr($t, 1), $exact), '!']; + else if ($t[0] != '-' && (mb_strlen($t) > 2 || $shortStr)) + $sub[] = [$f, $this->transformToken($t, $exact)]; } // single cnd? @@ -619,7 +619,6 @@ abstract class Filter if (!$string && $this->values['na']) $string = $this->values['na']; - // always allow sub 3 chars for logographic locales if (Lang::getLocale()->isLogographic() && !Cfg::get('LOGOGRAPHIC_FT_SEARCH')) return $this->tokenizeString($fields, $string, $exact, $shortStr); @@ -627,14 +626,30 @@ abstract class Filter if (!$string) return []; - $sub = []; - $parts = $exact ? [$string] : array_filter(explode(' ', $string)); - foreach ($parts as $p) + // always allow sub 3 chars for logographic locales + if (Lang::getLocale()->isLogographic()) + $shortStr = true; + + $sub = []; + $tokens = $exact ? [$string] : array_filter(explode(' ', $string)); + foreach ($tokens as $t) { - if ($p[0] == '-' && (mb_strlen($p) > 3 || $shortStr)) - $sub[] = $this->transformToken($p, '%s*'); - else if ($p[0] != '-' && (mb_strlen($p) > 2 || $shortStr)) - $sub[] = $this->transformToken($p, '+%s*'); + $ex = $t[0] === '-'; + if ($ex) + $t = mb_substr($t, 1); + + // cant have trailing/leading dashes. FT confuses them for additional modifiers and dies with a syntax error + // would be an issue for all modifiers, but Filter::PATTERN_FT only allows for - at this point + while (($t[0] ?? '') === '-') + $t = mb_substr($t, 1); + + while (($t[-1] ?? '') === '-') + $t = mb_substr($t, 0, -1); + + if (!$shortStr && mb_strlen($t) < 3) + continue; + + $sub[] = ($ex ? '-' : '+') . $t . '*'; } $qry = []; diff --git a/includes/components/search.class.php b/includes/components/search.class.php index 168cbbcc..b6b0695a 100644 --- a/includes/components/search.class.php +++ b/includes/components/search.class.php @@ -133,9 +133,21 @@ class Search // note: a fulltext search purely with exclude tokens will return no result if (($tokens = trim(preg_replace(Filter::PATTERN_FT, ' ', $clean))) !== '') + { foreach (array_filter(explode(' ', $tokens)) as $t) + { + // cant have trailing/leading dashes. FT confuses them for additional modifiers and dies with a syntax error + // would be an issue for all modifiers, but Filter::PATTERN_FT only allows for - at this point + while (($t[0] ?? '') === '-') + $t = mb_substr($t, 1); + + while (($t[-1] ?? '') === '-') + $t = mb_substr($t, 0, -1); + if (mb_strlen($t) > 2) $this->fulltext[] = ($ex ? '-' : '+') . $t . '*'; + } + } } }