1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Encore\Admin\Grid\Filter; |
4
|
|
|
|
5
|
|
|
use Encore\Admin\Grid\Filter; |
6
|
|
|
use Encore\Admin\Grid\Filter\Presenter\Checkbox; |
7
|
|
|
use Encore\Admin\Grid\Filter\Presenter\DateTime; |
8
|
|
|
use Encore\Admin\Grid\Filter\Presenter\MultipleSelect; |
9
|
|
|
use Encore\Admin\Grid\Filter\Presenter\Presenter; |
10
|
|
|
use Encore\Admin\Grid\Filter\Presenter\Radio; |
11
|
|
|
use Encore\Admin\Grid\Filter\Presenter\Select; |
12
|
|
|
use Encore\Admin\Grid\Filter\Presenter\Text; |
13
|
|
|
use Illuminate\Support\Arr; |
14
|
|
|
use Illuminate\Support\Collection; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Class AbstractFilter. |
18
|
|
|
* |
19
|
|
|
* @method Text url() |
20
|
|
|
* @method Text email() |
21
|
|
|
* @method Text integer() |
22
|
|
|
* @method Text decimal($options = []) |
23
|
|
|
* @method Text currency($options = []) |
24
|
|
|
* @method Text percentage($options = []) |
25
|
|
|
* @method Text ip() |
26
|
|
|
* @method Text mac() |
27
|
|
|
* @method Text mobile($mask = '19999999999') |
28
|
|
|
* @method Text inputmask($options = [], $icon = '') |
29
|
|
|
* @method Text placeholder($placeholder = '') |
30
|
|
|
*/ |
31
|
|
|
abstract class AbstractFilter |
32
|
|
|
{ |
33
|
|
|
/** |
34
|
|
|
* Element id. |
35
|
|
|
* |
36
|
|
|
* @var array|string |
37
|
|
|
*/ |
38
|
|
|
protected $id; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Label of presenter. |
42
|
|
|
* |
43
|
|
|
* @var string |
44
|
|
|
*/ |
45
|
|
|
protected $label; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var array|string |
49
|
|
|
*/ |
50
|
|
|
protected $value; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @var array|string |
54
|
|
|
*/ |
55
|
|
|
protected $defaultValue; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* @var string |
59
|
|
|
*/ |
60
|
|
|
protected $column; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Presenter object. |
64
|
|
|
* |
65
|
|
|
* @var Presenter |
66
|
|
|
*/ |
67
|
|
|
protected $presenter; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Query for filter. |
71
|
|
|
* |
72
|
|
|
* @var string |
73
|
|
|
*/ |
74
|
|
|
protected $query = 'where'; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @var Filter |
78
|
|
|
*/ |
79
|
|
|
protected $parent; |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* @var string |
83
|
|
|
*/ |
84
|
|
|
protected $view = 'admin::filter.where'; |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @var Collection |
88
|
|
|
*/ |
89
|
|
|
public $group; |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* @var bool |
93
|
|
|
*/ |
94
|
|
|
protected $ignore = false; |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* AbstractFilter constructor. |
98
|
|
|
* |
99
|
|
|
* @param $column |
100
|
|
|
* @param string $label |
101
|
|
|
*/ |
102
|
|
|
public function __construct($column, $label = '') |
103
|
|
|
{ |
104
|
|
|
$this->column = $column; |
105
|
|
|
$this->label = $this->formatLabel($label); |
106
|
|
|
$this->id = $this->formatId($column); |
107
|
|
|
|
108
|
|
|
$this->setupDefaultPresenter(); |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Setup default presenter. |
113
|
|
|
* |
114
|
|
|
* @return void |
115
|
|
|
*/ |
116
|
|
|
protected function setupDefaultPresenter() |
117
|
|
|
{ |
118
|
|
|
$this->setPresenter(new Text($this->label)); |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Format label. |
123
|
|
|
* |
124
|
|
|
* @param string $label |
125
|
|
|
* |
126
|
|
|
* @return string |
127
|
|
|
*/ |
128
|
|
|
protected function formatLabel($label) |
129
|
|
|
{ |
130
|
|
|
$label = $label ?: ucfirst($this->column); |
131
|
|
|
|
132
|
|
|
return str_replace(['.', '_'], ' ', $label); |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* Format name. |
137
|
|
|
* |
138
|
|
|
* @param string $column |
139
|
|
|
* |
140
|
|
|
* @return string |
141
|
|
|
*/ |
142
|
|
|
protected function formatName($column) |
143
|
|
|
{ |
144
|
|
|
$columns = explode('.', $column); |
145
|
|
|
|
146
|
|
View Code Duplication |
if (count($columns) == 1) { |
|
|
|
|
147
|
|
|
$name = $columns[0]; |
148
|
|
|
} else { |
149
|
|
|
$name = array_shift($columns); |
150
|
|
|
foreach ($columns as $column) { |
151
|
|
|
$name .= "[$column]"; |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
$parenName = $this->parent->getName(); |
156
|
|
|
|
157
|
|
|
return $parenName ? "{$parenName}_{$name}" : $name; |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* Format id. |
162
|
|
|
* |
163
|
|
|
* @param $columns |
164
|
|
|
* |
165
|
|
|
* @return array|string |
166
|
|
|
*/ |
167
|
|
|
protected function formatId($columns) |
168
|
|
|
{ |
169
|
|
|
return str_replace('.', '_', $columns); |
170
|
|
|
} |
171
|
|
|
|
172
|
|
|
/** |
173
|
|
|
* @param Filter $filter |
174
|
|
|
*/ |
175
|
|
|
public function setParent(Filter $filter) |
176
|
|
|
{ |
177
|
|
|
$this->parent = $filter; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Get siblings of current filter. |
182
|
|
|
* |
183
|
|
|
* @param null $index |
184
|
|
|
* |
185
|
|
|
* @return AbstractFilter[]|mixed |
186
|
|
|
*/ |
187
|
|
|
public function siblings($index = null) |
188
|
|
|
{ |
189
|
|
|
if (!is_null($index)) { |
190
|
|
|
return Arr::get($this->parent->filters(), $index); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
return $this->parent->filters(); |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Get previous filter. |
198
|
|
|
* |
199
|
|
|
* @param int $step |
200
|
|
|
* |
201
|
|
|
* @return AbstractFilter[]|mixed |
202
|
|
|
*/ |
203
|
|
|
public function previous($step = 1) |
204
|
|
|
{ |
205
|
|
|
return $this->siblings( |
206
|
|
|
array_search($this, $this->parent->filters()) - $step |
207
|
|
|
); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* Get next filter. |
212
|
|
|
* |
213
|
|
|
* @param int $step |
214
|
|
|
* |
215
|
|
|
* @return AbstractFilter[]|mixed |
216
|
|
|
*/ |
217
|
|
|
public function next($step = 1) |
218
|
|
|
{ |
219
|
|
|
return $this->siblings( |
220
|
|
|
array_search($this, $this->parent->filters()) + $step |
221
|
|
|
); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Get query condition from filter. |
226
|
|
|
* |
227
|
|
|
* @param array $inputs |
228
|
|
|
* |
229
|
|
|
* @return array|mixed|null |
230
|
|
|
*/ |
231
|
|
|
public function condition($inputs) |
232
|
|
|
{ |
233
|
|
|
if ($this->ignore) { |
234
|
|
|
return; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
$value = Arr::get($inputs, $this->column); |
238
|
|
|
|
239
|
|
|
if (!isset($value)) { |
240
|
|
|
return; |
241
|
|
|
} |
242
|
|
|
|
243
|
|
|
$this->value = $value; |
244
|
|
|
|
245
|
|
|
return $this->buildCondition($this->column, $this->value); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
/** |
249
|
|
|
* Ignore this query filter. |
250
|
|
|
* |
251
|
|
|
* @return $this |
252
|
|
|
*/ |
253
|
|
|
public function ignore() |
254
|
|
|
{ |
255
|
|
|
$this->ignore = true; |
256
|
|
|
|
257
|
|
|
return $this; |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Select filter. |
262
|
|
|
* |
263
|
|
|
* @param array|\Illuminate\Support\Collection $options |
264
|
|
|
* |
265
|
|
|
* @return Select |
266
|
|
|
*/ |
267
|
|
|
public function select($options = []) |
268
|
|
|
{ |
269
|
|
|
return $this->setPresenter(new Select($options)); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
/** |
273
|
|
|
* @param array|\Illuminate\Support\Collection $options |
274
|
|
|
* |
275
|
|
|
* @return MultipleSelect |
276
|
|
|
*/ |
277
|
|
|
public function multipleSelect($options = []) |
278
|
|
|
{ |
279
|
|
|
return $this->setPresenter(new MultipleSelect($options)); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* @param array|\Illuminate\Support\Collection $options |
284
|
|
|
* |
285
|
|
|
* @return Radio |
286
|
|
|
*/ |
287
|
|
|
public function radio($options = []) |
288
|
|
|
{ |
289
|
|
|
return $this->setPresenter(new Radio($options)); |
|
|
|
|
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* @param array|\Illuminate\Support\Collection $options |
294
|
|
|
* |
295
|
|
|
* @return Checkbox |
296
|
|
|
*/ |
297
|
|
|
public function checkbox($options = []) |
298
|
|
|
{ |
299
|
|
|
return $this->setPresenter(new Checkbox($options)); |
|
|
|
|
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Datetime filter. |
304
|
|
|
* |
305
|
|
|
* @param array|\Illuminate\Support\Collection $options |
306
|
|
|
* |
307
|
|
|
* @return DateTime |
308
|
|
|
*/ |
309
|
|
|
public function datetime($options = []) |
310
|
|
|
{ |
311
|
|
|
return $this->setPresenter(new DateTime($options)); |
|
|
|
|
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Date filter. |
316
|
|
|
* |
317
|
|
|
* @return DateTime |
318
|
|
|
*/ |
319
|
|
|
public function date() |
320
|
|
|
{ |
321
|
|
|
return $this->datetime(['format' => 'YYYY-MM-DD']); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Time filter. |
326
|
|
|
* |
327
|
|
|
* @return DateTime |
328
|
|
|
*/ |
329
|
|
|
public function time() |
330
|
|
|
{ |
331
|
|
|
return $this->datetime(['format' => 'HH:mm:ss']); |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
/** |
335
|
|
|
* Day filter. |
336
|
|
|
* |
337
|
|
|
* @return DateTime |
338
|
|
|
*/ |
339
|
|
|
public function day() |
340
|
|
|
{ |
341
|
|
|
return $this->datetime(['format' => 'DD']); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
/** |
345
|
|
|
* Month filter. |
346
|
|
|
* |
347
|
|
|
* @return DateTime |
348
|
|
|
*/ |
349
|
|
|
public function month() |
350
|
|
|
{ |
351
|
|
|
return $this->datetime(['format' => 'MM']); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Year filter. |
356
|
|
|
* |
357
|
|
|
* @return DateTime |
358
|
|
|
*/ |
359
|
|
|
public function year() |
360
|
|
|
{ |
361
|
|
|
return $this->datetime(['format' => 'YYYY']); |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
/** |
365
|
|
|
* Set presenter object of filter. |
366
|
|
|
* |
367
|
|
|
* @param Presenter $presenter |
368
|
|
|
* |
369
|
|
|
* @return mixed |
370
|
|
|
*/ |
371
|
|
|
protected function setPresenter(Presenter $presenter) |
372
|
|
|
{ |
373
|
|
|
$presenter->setParent($this); |
374
|
|
|
|
375
|
|
|
return $this->presenter = $presenter; |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
/** |
379
|
|
|
* Get presenter object of filter. |
380
|
|
|
* |
381
|
|
|
* @return Presenter |
382
|
|
|
*/ |
383
|
|
|
protected function presenter() |
384
|
|
|
{ |
385
|
|
|
return $this->presenter; |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
/** |
389
|
|
|
* Set default value for filter. |
390
|
|
|
* |
391
|
|
|
* @param null $default |
392
|
|
|
* |
393
|
|
|
* @return $this |
394
|
|
|
*/ |
395
|
|
|
public function default($default = null) |
396
|
|
|
{ |
397
|
|
|
if ($default) { |
398
|
|
|
$this->defaultValue = $default; |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
return $this; |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
public function getFilterBoxId() |
405
|
|
|
{ |
406
|
|
|
return $this->parent ? $this->parent->getFilterID() : 'filter-box'; |
407
|
|
|
} |
408
|
|
|
|
409
|
|
|
/** |
410
|
|
|
* Get element id. |
411
|
|
|
* |
412
|
|
|
* @return array|string |
413
|
|
|
*/ |
414
|
|
|
public function getId() |
415
|
|
|
{ |
416
|
|
|
return $this->id; |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
/** |
420
|
|
|
* Set element id. |
421
|
|
|
* |
422
|
|
|
* @param string $id |
423
|
|
|
* |
424
|
|
|
* @return $this |
425
|
|
|
*/ |
426
|
|
|
public function setId($id) |
427
|
|
|
{ |
428
|
|
|
$this->id = $this->formatId($id); |
429
|
|
|
|
430
|
|
|
return $this; |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
/** |
434
|
|
|
* Get column name of current filter. |
435
|
|
|
* |
436
|
|
|
* @return string |
437
|
|
|
*/ |
438
|
|
|
public function getColumn() |
439
|
|
|
{ |
440
|
|
|
$parentName = $this->parent->getName(); |
441
|
|
|
|
442
|
|
|
return $parentName ? "{$parentName}_{$this->column}" : $this->column; |
443
|
|
|
} |
444
|
|
|
|
445
|
|
|
/** |
446
|
|
|
* Get value of current filter. |
447
|
|
|
* |
448
|
|
|
* @return array|string |
449
|
|
|
*/ |
450
|
|
|
public function getValue() |
451
|
|
|
{ |
452
|
|
|
return $this->value; |
453
|
|
|
} |
454
|
|
|
|
455
|
|
|
/** |
456
|
|
|
* Build conditions of filter. |
457
|
|
|
* |
458
|
|
|
* @return mixed |
459
|
|
|
*/ |
460
|
|
|
protected function buildCondition() |
461
|
|
|
{ |
462
|
|
|
$column = explode('.', $this->column); |
463
|
|
|
|
464
|
|
|
if (count($column) == 1) { |
465
|
|
|
return [$this->query => func_get_args()]; |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
return $this->buildRelationQuery(...func_get_args()); |
469
|
|
|
} |
470
|
|
|
|
471
|
|
|
/** |
472
|
|
|
* Build query condition of model relation. |
473
|
|
|
* |
474
|
|
|
* @return array |
475
|
|
|
*/ |
476
|
|
|
protected function buildRelationQuery() |
477
|
|
|
{ |
478
|
|
|
$args = func_get_args(); |
479
|
|
|
|
480
|
|
|
$relation = substr($this->column, 0, strrpos($this->column, '.')); |
481
|
|
|
$args[0] = last(explode('.', $this->column)); |
482
|
|
|
|
483
|
|
|
return ['whereHas' => [$relation, function ($relation) use ($args) { |
484
|
|
|
call_user_func_array([$relation, $this->query], $args); |
485
|
|
|
}]]; |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
/** |
489
|
|
|
* Variables for filter view. |
490
|
|
|
* |
491
|
|
|
* @return array |
492
|
|
|
*/ |
493
|
|
|
protected function variables() |
494
|
|
|
{ |
495
|
|
|
return array_merge([ |
496
|
|
|
'id' => $this->id, |
497
|
|
|
'column' => $this->column, |
498
|
|
|
'name' => $this->formatName($this->column), |
499
|
|
|
'label' => $this->label, |
500
|
|
|
'value' => $this->value ?: $this->defaultValue, |
501
|
|
|
'presenter' => $this->presenter(), |
502
|
|
|
], $this->presenter()->variables()); |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
/** |
506
|
|
|
* Render this filter. |
507
|
|
|
* |
508
|
|
|
* @return \Illuminate\View\View|string |
509
|
|
|
*/ |
510
|
|
|
public function render() |
511
|
|
|
{ |
512
|
|
|
return view($this->view, $this->variables()); |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
/** |
516
|
|
|
* Render this filter. |
517
|
|
|
* |
518
|
|
|
* @return \Illuminate\View\View|string |
519
|
|
|
*/ |
520
|
|
|
public function __toString() |
521
|
|
|
{ |
522
|
|
|
return $this->render(); |
523
|
|
|
} |
524
|
|
|
|
525
|
|
|
/** |
526
|
|
|
* @param $method |
527
|
|
|
* @param $params |
528
|
|
|
* |
529
|
|
|
* @throws \Exception |
530
|
|
|
* |
531
|
|
|
* @return mixed |
532
|
|
|
*/ |
533
|
|
|
public function __call($method, $params) |
534
|
|
|
{ |
535
|
|
|
if (method_exists($this->presenter, $method)) { |
536
|
|
|
return $this->presenter()->{$method}(...$params); |
537
|
|
|
} |
538
|
|
|
|
539
|
|
|
throw new \Exception('Method "'.$method.'" not exists.'); |
540
|
|
|
} |
541
|
|
|
} |
542
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.