|
4 | 4 |
|
5 | 5 | namespace Cone\Root\Fields; |
6 | 6 |
|
7 | | -use Closure; |
8 | | -use Cone\Root\Fields\Select as SelectField; |
9 | | -use Cone\Root\Filters\Select; |
10 | | -use Illuminate\Database\Eloquent\Builder; |
11 | 7 | use Illuminate\Database\Eloquent\Model; |
12 | 8 | use Illuminate\Database\Eloquent\Relations\MorphOneOrMany as EloquentRelation; |
13 | | -use Illuminate\Http\Request; |
14 | | -use Illuminate\Support\Str; |
15 | | -use Illuminate\Support\Uri; |
16 | 9 |
|
17 | 10 | /** |
18 | 11 | * @template TRelation of \Illuminate\Database\Eloquent\Relations\MorphOneOrMany |
|
21 | 14 | */ |
22 | 15 | abstract class MorphOneOrMany extends HasOneOrMany |
23 | 16 | { |
24 | | - /** |
25 | | - * The morph types. |
26 | | - */ |
27 | | - protected array $types = []; |
28 | | - |
29 | 17 | /** |
30 | 18 | * {@inheritdoc} |
31 | 19 | */ |
32 | 20 | public function getRelation(Model $model): EloquentRelation |
33 | 21 | { |
34 | 22 | return parent::getRelation($model); |
35 | 23 | } |
36 | | - |
37 | | - /** |
38 | | - * Get the morph types. |
39 | | - */ |
40 | | - public function getTypes(): array |
41 | | - { |
42 | | - return $this->types; |
43 | | - } |
44 | | - |
45 | | - /** |
46 | | - * {@inheritdoc} |
47 | | - */ |
48 | | - public function getSearchableColumns(): array |
49 | | - { |
50 | | - return match (true) { |
51 | | - array_is_list($this->searchableColumns) => array_fill_keys($this->types, $this->searchableColumns), |
52 | | - default => $this->searchableColumns, |
53 | | - }; |
54 | | - } |
55 | | - |
56 | | - /** |
57 | | - * Map the async searchable fields. |
58 | | - */ |
59 | | - protected function mapAsyncSearchableFields(Request $request): Fields |
60 | | - { |
61 | | - $fields = new Fields; |
62 | | - |
63 | | - foreach ($this->getSearchableColumns() as $type => $columns) { |
64 | | - foreach ($columns as $column) { |
65 | | - $field = Hidden::make($this->getRelationName(), sprintf('%s:%s', $type, $column)) |
66 | | - ->searchable(callback: function (Request $request, Builder $query, mixed $value, string $attribute): Builder { |
67 | | - [$type, $column] = explode(':', $attribute); |
68 | | - |
69 | | - return match ($query->getModel()::class) { |
70 | | - $type => $query->where($query->qualifyColumn($column), 'like', "%{$value}%", 'or'), |
71 | | - default => $query, |
72 | | - }; |
73 | | - }); |
74 | | - |
75 | | - $fields->push($field); |
76 | | - } |
77 | | - } |
78 | | - |
79 | | - return $fields; |
80 | | - } |
81 | | - |
82 | | - /** |
83 | | - * {@inheritdoc} |
84 | | - */ |
85 | | - public function searchable(bool|Closure $value = true, ?Closure $callback = null, array $columns = ['id']): static |
86 | | - { |
87 | | - $columns = match (true) { |
88 | | - array_is_list($columns) => array_fill_keys($this->getTypes(), $columns), |
89 | | - default => $columns, |
90 | | - }; |
91 | | - |
92 | | - return parent::searchable($value, $callback, $columns); |
93 | | - } |
94 | | - |
95 | | - /** |
96 | | - * {@inheritdoc} |
97 | | - */ |
98 | | - public function filters(Request $request): array |
99 | | - { |
100 | | - $typeFilter = new class($this) extends Select |
101 | | - { |
102 | | - public function __construct(protected MorphOneOrMany $field) |
103 | | - { |
104 | | - parent::__construct('type'); |
105 | | - } |
106 | | - |
107 | | - public function getName(): string |
108 | | - { |
109 | | - return __('Type'); |
110 | | - } |
111 | | - |
112 | | - public function apply(Request $request, Builder $query, mixed $value): Builder |
113 | | - { |
114 | | - return $query; |
115 | | - } |
116 | | - |
117 | | - public function options(Request $request): array |
118 | | - { |
119 | | - return array_map( |
120 | | - static function (string $type): string { |
121 | | - return __(Str::of($type)->classBasename()->headline()->value()); |
122 | | - }, |
123 | | - array_combine($this->field->getTypes(), $this->field->getTypes()) |
124 | | - ); |
125 | | - } |
126 | | - |
127 | | - public function toField(): SelectField |
128 | | - { |
129 | | - return parent::toField() |
130 | | - ->options(function (Request $request, Model $model): array { |
131 | | - $related = $this->field->getRelation($model)->getRelated()::class; |
132 | | - |
133 | | - return array_replace( |
134 | | - $this->options($request), |
135 | | - [$related => __(Str::of($related)->classBasename()->headline()->value())], |
136 | | - ); |
137 | | - }); |
138 | | - } |
139 | | - }; |
140 | | - |
141 | | - return array_merge([$typeFilter], parent::filters($request)); |
142 | | - } |
143 | | - |
144 | | - /** |
145 | | - * Set the morph types. |
146 | | - */ |
147 | | - public function types(array $types): static |
148 | | - { |
149 | | - $this->types = array_merge($this->types, $types); |
150 | | - |
151 | | - return $this; |
152 | | - } |
153 | | - |
154 | | - /** |
155 | | - * {@inheritdoc} |
156 | | - */ |
157 | | - public function toInput(Request $request, Model $model): array |
158 | | - { |
159 | | - $data = parent::toInput($request, $model); |
160 | | - |
161 | | - if (! empty($data['url'])) { |
162 | | - $relation = $this->getRelation($model); |
163 | | - |
164 | | - $data['url'] = Uri::of($data['url']) |
165 | | - ->withQuery([$relation->getMorphType() => $relation->getRelated()::class]) |
166 | | - ->value(); |
167 | | - } |
168 | | - |
169 | | - return $data; |
170 | | - } |
171 | 24 | } |
0 commit comments