- I patched the likely search blank-page cause in [plugin.php](/Users/tyemeclifford/Documents/GH/blog/bl-plugins/search/plugin.php).

What changed:
Removed the enlarged nested search cache fields I had added, which could 
push larger sites into memory/time failures.
Added a self-heal so existing oversized search caches regenerate into 
the smaller format.
Stopped fuzzy matching against full body content; it now only fuzzes 
title/tags/category/description.
Hardened search-term splitting and malformed input handling.
This commit is contained in:
Ty Clifford
2026-07-03 09:29:37 -04:00
parent efcde2a393
commit 9d9790976a
+44 -16
View File
@@ -477,8 +477,14 @@ EOF;
$stringToSearch = $this->webhook($webhook, true, false); $stringToSearch = $this->webhook($webhook, true, false);
$stringToSearch = trim($stringToSearch, '/'); $stringToSearch = trim($stringToSearch, '/');
$stringToSearch = urldecode($stringToSearch); $stringToSearch = urldecode($stringToSearch);
$stringToSearch = preg_replace('/\s+/u', ' ', $stringToSearch); $normalizedWhitespace = preg_replace('/\s+/u', ' ', $stringToSearch);
$stringToSearch = trim($stringToSearch); if ($normalizedWhitespace === null) {
$normalizedWhitespace = preg_replace('/\s+/', ' ', $stringToSearch);
}
if ($normalizedWhitespace !== null) {
$stringToSearch = $normalizedWhitespace;
}
$stringToSearch = trim((string) $stringToSearch);
if (mb_strlen($stringToSearch, 'UTF-8') > 120) { if (mb_strlen($stringToSearch, 'UTF-8') > 120) {
$stringToSearch = mb_substr($stringToSearch, 0, 120, 'UTF-8'); $stringToSearch = mb_substr($stringToSearch, 0, 120, 'UTF-8');
} }
@@ -554,7 +560,7 @@ EOF;
return $safeText; return $safeText;
} }
$words = preg_split('/\s+/u', trim($searchTerm), -1, PREG_SPLIT_NO_EMPTY); $words = $this->splitWords($searchTerm);
$words = array_filter($words, function($word) { $words = array_filter($words, function($word) {
return mb_strlen($word, 'UTF-8') >= 2; return mb_strlen($word, 'UTF-8') >= 2;
}); });
@@ -597,7 +603,7 @@ EOF;
return ''; return '';
} }
$words = preg_split('/\s+/u', trim($searchTerm), -1, PREG_SPLIT_NO_EMPTY); $words = $this->splitWords($searchTerm);
$words = array_filter($words, function($word) { $words = array_filter($words, function($word) {
return mb_strlen($word, 'UTF-8') >= 2; return mb_strlen($word, 'UTF-8') >= 2;
}); });
@@ -652,6 +658,19 @@ EOF;
return trim((string) $plainText); return trim((string) $plainText);
} }
private function splitWords($text)
{
$words = preg_split('/\s+/u', trim((string) $text), -1, PREG_SPLIT_NO_EMPTY);
if (!is_array($words)) {
$words = preg_split('/\s+/', trim((string) $text), -1, PREG_SPLIT_NO_EMPTY);
}
if (!is_array($words)) {
return array();
}
return $words;
}
// Generate the cache file // Generate the cache file
// This function is necessary to call it when you create, edit or remove content // This function is necessary to call it when you create, edit or remove content
private function createCache() private function createCache()
@@ -702,8 +721,6 @@ EOF;
} }
} }
} }
$cache[$pageKey]['search'] = $this->buildSearchFields($cache[$pageKey]);
} }
// Generate JSON file with the cache // Generate JSON file with the cache
@@ -749,6 +766,15 @@ EOF;
return array(); return array();
} }
if ($this->cacheContainsStoredSearchFields($cache)) {
$this->createCache();
$json = file_get_contents($cacheFile);
$cache = json_decode($json, true);
if (empty($cache) || !is_array($cache)) {
return array();
}
}
$terms = $this->tokenizeSearchTerm($text); $terms = $this->tokenizeSearchTerm($text);
if (empty($terms)) { if (empty($terms)) {
return array(); return array();
@@ -770,6 +796,15 @@ EOF;
return array_keys($scores); return array_keys($scores);
} }
private function cacheContainsStoredSearchFields($cache)
{
foreach ($cache as $data) {
return is_array($data) && isset($data['search']);
}
return false;
}
private function buildSearchFields($data) private function buildSearchFields($data)
{ {
$fields = array( $fields = array(
@@ -838,10 +873,7 @@ EOF;
private function tokenizeSearchTerm($text) private function tokenizeSearchTerm($text)
{ {
$normalized = $this->normalizeSearchText($text); $normalized = $this->normalizeSearchText($text);
$words = preg_split('/\s+/u', $normalized, -1, PREG_SPLIT_NO_EMPTY); $words = $this->splitWords($normalized);
if (!is_array($words)) {
return array();
}
$tokens = array(); $tokens = array();
foreach ($words as $word) { foreach ($words as $word) {
@@ -885,8 +917,7 @@ EOF;
$termScore += $this->scoreTermInField($fields['content'], $term, 25); $termScore += $this->scoreTermInField($fields['content'], $term, 25);
if ($termScore === 0) { if ($termScore === 0) {
$termScore += $this->fuzzyTermScore($term, trim($fields['title'] . ' ' . $fields['tags'] . ' ' . $fields['category']), 24); $termScore += $this->fuzzyTermScore($term, trim($fields['title'] . ' ' . $fields['tags'] . ' ' . $fields['category'] . ' ' . $fields['description']), 24);
$termScore += $this->fuzzyTermScore($term, $fields['content'], 10);
} }
if ($termScore > 0) { if ($termScore > 0) {
@@ -944,10 +975,7 @@ EOF;
return 0; return 0;
} }
$words = preg_split('/\s+/u', $field, -1, PREG_SPLIT_NO_EMPTY); $words = $this->splitWords($field);
if (!is_array($words)) {
return 0;
}
$bestScore = 0; $bestScore = 0;
$checked = array(); $checked = array();