X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/58fa7679bccafd00f9a50bcd4a87e96876331b03..refs/pull/3391/head:/app/Entities/Tools/SearchOptions.php diff --git a/app/Entities/Tools/SearchOptions.php b/app/Entities/Tools/SearchOptions.php index 6c03c57a6..99271058e 100644 --- a/app/Entities/Tools/SearchOptions.php +++ b/app/Entities/Tools/SearchOptions.php @@ -1,10 +1,11 @@ - $value) { $instance->$type = $value; } + return $instance; } @@ -43,7 +45,7 @@ class SearchOptions * Will look for a classic string term and use that * Otherwise we'll use the details from an advanced search form. */ - public static function fromRequest(Request $request): SearchOptions + public static function fromRequest(Request $request): self { if (!$request->has('search') && !$request->has('term')) { return static::fromString(''); @@ -53,20 +55,28 @@ class SearchOptions return static::fromString($request->get('term')); } - $instance = new static(); + $instance = new SearchOptions(); $inputs = $request->only(['search', 'types', 'filters', 'exact', 'tags']); - $instance->searches = explode(' ', $inputs['search'] ?? []); - $instance->exacts = array_filter($inputs['exact'] ?? []); + + $parsedStandardTerms = static::parseStandardTermString($inputs['search'] ?? ''); + $instance->searches = $parsedStandardTerms['terms']; + $instance->exacts = $parsedStandardTerms['exacts']; + + array_push($instance->exacts, ...array_filter($inputs['exact'] ?? [])); + $instance->tags = array_filter($inputs['tags'] ?? []); + foreach (($inputs['filters'] ?? []) as $filterKey => $filterVal) { if (empty($filterVal)) { continue; } $instance->filters[$filterKey] = $filterVal === 'true' ? '' : $filterVal; } + if (isset($inputs['types']) && count($inputs['types']) < 4) { $instance->filters['type'] = implode('|', $inputs['types']); } + return $instance; } @@ -77,15 +87,15 @@ class SearchOptions { $terms = [ 'searches' => [], - 'exacts' => [], - 'tags' => [], - 'filters' => [] + 'exacts' => [], + 'tags' => [], + 'filters' => [], ]; $patterns = [ - 'exacts' => '/"(.*?)"/', - 'tags' => '/\[(.*?)\]/', - 'filters' => '/\{(.*?)\}/' + 'exacts' => '/"(.*?)"/', + 'tags' => '/\[(.*?)\]/', + 'filters' => '/\{(.*?)\}/', ]; // Parse special terms @@ -99,11 +109,9 @@ class SearchOptions } // Parse standard terms - foreach (explode(' ', trim($searchString)) as $searchTerm) { - if ($searchTerm !== '') { - $terms['searches'][] = $searchTerm; - } - } + $parsedStandardTerms = static::parseStandardTermString($searchString); + array_push($terms['searches'], ...$parsedStandardTerms['terms']); + array_push($terms['exacts'], ...$parsedStandardTerms['exacts']); // Split filter values out $splitFilters = []; @@ -116,6 +124,33 @@ class SearchOptions return $terms; } + /** + * Parse a standard search term string into individual search terms and + * extract any exact terms searches to be made. + * + * @return array{terms: array, exacts: array} + */ + protected static function parseStandardTermString(string $termString): array + { + $terms = explode(' ', $termString); + $indexDelimiters = SearchIndex::$delimiters; + $parsed = [ + 'terms' => [], + 'exacts' => [], + ]; + + foreach ($terms as $searchTerm) { + if ($searchTerm === '') { + continue; + } + + $parsedList = (strpbrk($searchTerm, $indexDelimiters) === false) ? 'terms' : 'exacts'; + $parsed[$parsedList][] = $searchTerm; + } + + return $parsed; + } + /** * Encode this instance to a search string. */