zingimmick /
laravel-query-builder
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace Zing\QueryBuilder\Concerns; |
||
| 6 | |||
| 7 | use Illuminate\Database\Eloquent\Builder; |
||
| 8 | use Illuminate\Support\Str; |
||
| 9 | use Zing\QueryBuilder\Exceptions\ParameterException; |
||
| 10 | use Zing\QueryBuilder\Filter; |
||
| 11 | |||
| 12 | trait WithSearchable |
||
| 13 | { |
||
| 14 | use NestedRelation; |
||
| 15 | |||
| 16 | /** |
||
| 17 | * @param string|\Zing\QueryBuilder\Filter|array<(string|\Zing\QueryBuilder\Filter)> $searchable |
||
| 18 | * |
||
| 19 | * @return $this |
||
| 20 | */ |
||
| 21 | 8 | public function searchable($searchable) |
|
| 22 | { |
||
| 23 | 8 | $searchable = \is_array($searchable) ? $searchable : \func_get_args(); |
|
| 24 | 8 | $search = $this->request->input('search'); |
|
| 25 | 8 | if ($search === null) { |
|
| 26 | 1 | return $this; |
|
| 27 | } |
||
| 28 | |||
| 29 | 7 | if (\is_string($search) && trim($search) === '') { |
|
| 30 | 1 | return $this; |
|
| 31 | } |
||
| 32 | |||
| 33 | 6 | $searchable = $this->resolveNestedSearchable($searchable); |
|
| 34 | |||
| 35 | 6 | return $this->applySearchable($search, $searchable); |
|
| 36 | } |
||
| 37 | |||
| 38 | /** |
||
| 39 | * @param mixed $search |
||
| 40 | * @param array<(int|string), (string|array<string>|\Zing\QueryBuilder\Filter)> $searchable |
||
| 41 | * |
||
| 42 | * @return $this |
||
| 43 | */ |
||
| 44 | 6 | protected function applySearchable($search, array $searchable = []) |
|
| 45 | { |
||
| 46 | 6 | $this->where( |
|
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 47 | 6 | function (Builder $query) use ($search, $searchable): void { |
|
| 48 | 6 | collect($searchable)->each( |
|
| 49 | 6 | function ($value, $key) use ($query, $search): void { |
|
| 50 | 6 | if ($value instanceof Filter) { |
|
| 51 | 2 | if ($value->getDefault() !== null) { |
|
| 52 | 1 | throw ParameterException::unsupportedFilterWithDefaultValueForSearch(); |
|
| 53 | } |
||
| 54 | |||
| 55 | 2 | $query->orWhere(function ($query) use ($value, $search): void { |
|
| 56 | 2 | $value->filter($query, $search); |
|
| 57 | }); |
||
| 58 | |||
| 59 | 2 | return; |
|
| 60 | } |
||
| 61 | |||
| 62 | 6 | if (is_numeric($key)) { |
|
| 63 | 5 | $query->orWhere($value, 'like', sprintf('%%%s%%', $search)); |
|
| 64 | |||
| 65 | 5 | return; |
|
| 66 | } |
||
| 67 | |||
| 68 | 1 | $this->applyRelationSearchable($query, $key, (array) $value, $search); |
|
| 69 | } |
||
| 70 | ); |
||
| 71 | } |
||
| 72 | ); |
||
| 73 | |||
| 74 | 6 | return $this; |
|
| 75 | } |
||
| 76 | |||
| 77 | /** |
||
| 78 | * @param array<string> $fields |
||
| 79 | * @param mixed $search |
||
| 80 | */ |
||
| 81 | 1 | protected function applyRelationSearchable(Builder $query, string $relation, array $fields, $search): Builder |
|
| 82 | { |
||
| 83 | 1 | return $query->orWhereHas( |
|
| 84 | $relation, |
||
| 85 | 1 | function (Builder $query) use ($fields, $search): void { |
|
| 86 | 1 | $query->where( |
|
| 87 | 1 | function (Builder $query) use ($fields, $search): void { |
|
| 88 | 1 | foreach ($fields as $field) { |
|
| 89 | 1 | $query->orWhere($field, 'like', sprintf('%%%s%%', $search)); |
|
| 90 | } |
||
| 91 | } |
||
| 92 | ); |
||
| 93 | } |
||
| 94 | ); |
||
| 95 | } |
||
| 96 | |||
| 97 | /** |
||
| 98 | * @param array<(string|\Zing\QueryBuilder\Filter)> $searchable |
||
| 99 | * |
||
| 100 | * @return array<(int|string), (string|array<string>|\Zing\QueryBuilder\Filter)> |
||
| 101 | */ |
||
| 102 | 6 | private function resolveNestedSearchable(array $searchable): array |
|
| 103 | { |
||
| 104 | 6 | $results = []; |
|
| 105 | 6 | foreach ($searchable as $singleSearchable) { |
|
| 106 | 6 | if (! $singleSearchable instanceof Filter && Str::contains($singleSearchable, '.')) { |
|
| 107 | 1 | [$relation, $property] = $this->resolveNestedRelation($singleSearchable); |
|
| 108 | |||
| 109 | 1 | $results[$relation][] = $property; |
|
| 110 | } else { |
||
| 111 | 5 | $results[] = $singleSearchable; |
|
| 112 | } |
||
| 113 | } |
||
| 114 | |||
| 115 | 6 | return $results; |
|
|
0 ignored issues
–
show
|
|||
| 116 | } |
||
| 117 | } |
||
| 118 |