Completed
Push — master ( 63e1f5...12461b )
by Song
02:49 queued 11s
created

AbstractFilter::getFilterBoxId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
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) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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));
0 ignored issues
show
Bug introduced by
It seems like $options defined by parameter $options on line 287 can also be of type object<Illuminate\Support\Collection>; however, Encore\Admin\Grid\Filter...er\Radio::__construct() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
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));
0 ignored issues
show
Bug introduced by
It seems like $options defined by parameter $options on line 297 can also be of type object<Illuminate\Support\Collection>; however, Encore\Admin\Grid\Filter...er\Radio::__construct() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
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));
0 ignored issues
show
Bug introduced by
It seems like $options defined by parameter $options on line 309 can also be of type object<Illuminate\Support\Collection>; however, Encore\Admin\Grid\Filter...DateTime::__construct() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
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