-<?php namespace BookStack\Entities;
+<?php
+
+namespace BookStack\Entities\Tools;
use Illuminate\Http\Request;
class SearchOptions
{
-
/**
* @var array
*/
/**
* Create a new instance from a search string.
*/
- public static function fromString(string $search): SearchOptions
+ public static function fromString(string $search): self
{
$decoded = static::decode($search);
- $instance = new static();
+ $instance = new SearchOptions();
foreach ($decoded as $type => $value) {
$instance->$type = $value;
}
+
return $instance;
}
* 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('');
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;
}
{
$terms = [
'searches' => [],
- 'exacts' => [],
- 'tags' => [],
- 'filters' => []
+ 'exacts' => [],
+ 'tags' => [],
+ 'filters' => [],
];
$patterns = [
- 'exacts' => '/"(.*?)"/',
- 'tags' => '/\[(.*?)\]/',
- 'filters' => '/\{(.*?)\}/'
+ 'exacts' => '/"(.*?)"/',
+ 'tags' => '/\[(.*?)\]/',
+ 'filters' => '/\{(.*?)\}/',
];
// Parse special terms
}
// 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 = [];
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<string>, exacts: array<string>}
+ */
+ 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.
*/
return $string;
}
-
-}
\ No newline at end of file
+}