3 namespace BookStack\Entities\Tools;
5 use Illuminate\Http\Request;
12 public $searches = [];
30 * Create a new instance from a search string.
32 public static function fromString(string $search): self
34 $decoded = static::decode($search);
35 $instance = new static();
36 foreach ($decoded as $type => $value) {
37 $instance->$type = $value;
44 * Create a new instance from a request.
45 * Will look for a classic string term and use that
46 * Otherwise we'll use the details from an advanced search form.
48 public static function fromRequest(Request $request): self
50 if (!$request->has('search') && !$request->has('term')) {
51 return static::fromString('');
54 if ($request->has('term')) {
55 return static::fromString($request->get('term'));
58 $instance = new static();
59 $inputs = $request->only(['search', 'types', 'filters', 'exact', 'tags']);
60 $instance->searches = explode(' ', $inputs['search'] ?? []);
61 $instance->exacts = array_filter($inputs['exact'] ?? []);
62 $instance->tags = array_filter($inputs['tags'] ?? []);
63 foreach (($inputs['filters'] ?? []) as $filterKey => $filterVal) {
64 if (empty($filterVal)) {
67 $instance->filters[$filterKey] = $filterVal === 'true' ? '' : $filterVal;
69 if (isset($inputs['types']) && count($inputs['types']) < 4) {
70 $instance->filters['type'] = implode('|', $inputs['types']);
77 * Decode a search string into an array of terms.
79 protected static function decode(string $searchString): array
89 'exacts' => '/"(.*?)"/',
90 'tags' => '/\[(.*?)\]/',
91 'filters' => '/\{(.*?)\}/',
94 // Parse special terms
95 foreach ($patterns as $termType => $pattern) {
97 preg_match_all($pattern, $searchString, $matches);
98 if (count($matches) > 0) {
99 $terms[$termType] = $matches[1];
100 $searchString = preg_replace($pattern, '', $searchString);
104 // Parse standard terms
105 foreach (explode(' ', trim($searchString)) as $searchTerm) {
106 if ($searchTerm !== '') {
107 $terms['searches'][] = $searchTerm;
111 // Split filter values out
113 foreach ($terms['filters'] as $filter) {
114 $explodedFilter = explode(':', $filter, 2);
115 $splitFilters[$explodedFilter[0]] = (count($explodedFilter) > 1) ? $explodedFilter[1] : '';
117 $terms['filters'] = $splitFilters;
123 * Encode this instance to a search string.
125 public function toString(): string
127 $string = implode(' ', $this->searches ?? []);
129 foreach ($this->exacts as $term) {
130 $string .= ' "' . $term . '"';
133 foreach ($this->tags as $term) {
134 $string .= " [{$term}]";
137 foreach ($this->filters as $filterName => $filterVal) {
138 $string .= ' {' . $filterName . ($filterVal ? ':' . $filterVal : '') . '}';