Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Push — master ( b8bb45...33d313 )
by Cristian
15:15 queued 08:07
created

CrudFilter::dump()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 5
rs 10
c 1
b 0
f 1
1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel;
4
5
use Symfony\Component\HttpFoundation\ParameterBag;
6
7
class CrudFilter
8
{
9
    public $name; // the name of the filtered variable (db column name)
10
    public $type = 'select2'; // the name of the filter view that will be loaded
11
    public $label;
12
    public $placeholder;
13
    public $values;
14
    public $options;
15
    public $logic;
16
    public $fallbackLogic;
17
    public $currentValue;
18
    public $view;
19
    public $viewNamespace = 'crud::filters';
20
    public $applied = false;
21
22
    public function __construct($options, $values, $logic, $fallbackLogic)
23
    {
24
        // if filter exists
25
        if ($this->crud()->hasFilterWhere('name', $options['name'])) {
26
            $properties = get_object_vars($this->crud()->firstFilterWhere('name', $options['name']));
0 ignored issues
show
Bug introduced by
$this->crud()->firstFilt...ame', $options['name']) of type boolean is incompatible with the type object expected by parameter $object of get_object_vars(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

26
            $properties = get_object_vars(/** @scrutinizer ignore-type */ $this->crud()->firstFilterWhere('name', $options['name']));
Loading history...
27
            foreach ($properties as $property => $value) {
28
                $this->{$property} = $value;
29
            }
30
        } else {
31
            // it means we're creating the filter now,
32
            $this->name = $options['name'];
33
            $this->type = $options['type'] ?? $this->type;
34
            $this->label = $options['label'] ?? $this->crud()->makeLabel($this->name);
35
            $this->viewNamespace = $options['view_namespace'] ?? $this->viewNamespace;
36
            $this->view = $this->type;
37
            $this->placeholder = $options['placeholder'] ?? '';
38
39
            $this->values = is_callable($values) ? $values() : $values;
40
            $this->options = $options;
41
            $this->logic = $logic;
42
            $this->fallbackLogic = $fallbackLogic;
43
        }
44
45
        if (\Request::has($this->name)) {
46
            $this->currentValue = \Request::input($this->name);
47
        }
48
    }
49
50
    /**
51
     * Check if the field is currently active. This happens when there's a GET parameter
52
     * in the current request with the same name as the name of the field.
53
     *
54
     * @return bool
55
     */
56
    public function isActive()
57
    {
58
        if (\Request::has($this->name)) {
59
            return true;
60
        }
61
62
        return false;
63
    }
64
65
    /**
66
     * Check if the filter has already had the apply method called on it.
67
     *
68
     * @return bool
69
     */
70
    public function wasApplied()
71
    {
72
        return $this->applied;
73
    }
74
75
    /**
76
     * Check if the filter has not had the apply method called on it yet.
77
     * This is the inverse of the wasApplied() method.
78
     *
79
     * @return bool
80
     */
81
    public function wasNotApplied()
82
    {
83
        return ! $this->applied;
84
    }
85
86
    /**
87
     * Run the filter logic, default logic and/or fallback logic so that from this point on
88
     * the CRUD query has its results filtered, according to the Request.
89
     *
90
     * @param  array $input The GET parameters for which the filter should be applied.
91
     * @return void
92
     */
93
    public function apply($input = null)
94
    {
95
        // mark the field as already applied
96
        $this->applied(true);
97
98
        if (is_array($input)) {
99
            $input = new ParameterBag($input);
100
        }
101
102
        $input = $input ?? new ParameterBag($this->crud()->getRequest()->all());
103
104
        if (! $input->has($this->name)) {
105
            return;
106
        }
107
108
        // if a closure was passed as "filterLogic"
109
        if (is_callable($this->logic)) {
110
            return ($this->logic)($input->get($this->name));
111
        } else {
112
            return $this->applyDefaultLogic($this->name, false);
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $operator of Backpack\CRUD\app\Librar...er::applyDefaultLogic(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

112
            return $this->applyDefaultLogic($this->name, /** @scrutinizer ignore-type */ false);
Loading history...
Bug introduced by
Are you sure the usage of $this->applyDefaultLogic($this->name, false) targeting Backpack\CRUD\app\Librar...er::applyDefaultLogic() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
113
        }
114
115
        // if fallback logic was supplied and is a closure
116
        if (is_callable($this->fallbackLogic)) {
0 ignored issues
show
Unused Code introduced by
IfNode is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
117
            return ($this->fallbackLogic)();
118
        }
119
    }
120
121
    /**
122
     * Get the full path of the filter view, including the view namespace.
123
     *
124
     * @return string
125
     */
126
    public function getViewWithNamespace()
127
    {
128
        return $this->viewNamespace.'.'.$this->view;
129
    }
130
131
    // ---------------------
132
    // FLUENT SYNTAX METHODS
133
    // ---------------------
134
135
    /**
136
     * Create a CrudFilter object with the parameter as its name.
137
     *
138
     * @param  string $name Name of the column in the db, or model attribute.
139
     * @return CrudPanel
140
     */
141
    public static function name($name)
142
    {
143
        return new static(compact('name'), null, null, null);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static(compac...me'), null, null, null) returns the type Backpack\CRUD\app\Library\CrudPanel\CrudFilter which is incompatible with the documented return type Backpack\CRUD\app\Library\CrudPanel\CrudPanel.
Loading history...
144
    }
145
146
    /**
147
     * Remove the current filter from the current operation.
148
     *
149
     * @return void
150
     */
151
    public function remove()
152
    {
153
        $this->crud()->removeFilter($this->name);
154
    }
155
156
    /**
157
     * Remove an attribute from the current filter definition array.
158
     *
159
     * @param  string $attribute Name of the attribute being removed.
160
     * @return CrudFilter
161
     */
162
    public function forget($attribute)
163
    {
164
        if (property_exists($this, $attribute)) {
165
            $this->{$attribute} = false;
166
        }
167
168
        if (isset($this->options[$attribute])) {
169
            unset($this->options[$attribute]);
170
        }
171
172
        $this->crud()->replaceFilter($this->name, $this);
173
174
        return $this;
175
    }
176
177
    /**
178
     * Remove an attribute from one field's definition array.
179
     * @param  string $field     The name of the field.
180
     * @param  string $attribute The name of the attribute being removed.
181
     */
182
    public function removeFilterAttribute($filter, $attribute)
0 ignored issues
show
Unused Code introduced by
The parameter $filter is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

182
    public function removeFilterAttribute(/** @scrutinizer ignore-unused */ $filter, $attribute)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
183
    {
184
        $fields = $this->fields();
0 ignored issues
show
Bug introduced by
The method fields() does not exist on Backpack\CRUD\app\Library\CrudPanel\CrudFilter. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

184
        /** @scrutinizer ignore-call */ 
185
        $fields = $this->fields();
Loading history...
185
186
        unset($fields[$field][$attribute]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $field does not exist. Did you maybe mean $fields?
Loading history...
187
188
        $this->setOperationSetting('fields', $fields);
0 ignored issues
show
Bug introduced by
The method setOperationSetting() does not exist on Backpack\CRUD\app\Library\CrudPanel\CrudFilter. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

188
        $this->/** @scrutinizer ignore-call */ 
189
               setOperationSetting('fields', $fields);
Loading history...
189
    }
190
191
    /**
192
     * Move the current filter after another filter.
193
     *
194
     * @param  string $destination Name of the destination filter.
195
     * @return CrudFilter
196
     */
197
    public function after($destination)
198
    {
199
        $this->crud()->moveFilter($this->name, 'after', $destination);
200
201
        return $this;
202
    }
203
204
    /**
205
     * Move the current field before another field.
206
     *
207
     * @param  string $destination Name of the destination field.
208
     * @return CrudFilter
209
     */
210
    public function before($destination)
211
    {
212
        $this->crud()->moveFilter($this->name, 'before', $destination);
213
214
        return $this;
215
    }
216
217
    /**
218
     * Make the current field the first one in the fields list.
219
     *
220
     * @return CrudPanel
221
     */
222
    public function makeFirst()
223
    {
224
        $this->crud()->moveFilter($this->name, 'before', $this->crud()->filters()->first()->name);
225
226
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Backpack\CRUD\app\Library\CrudPanel\CrudFilter which is incompatible with the documented return type Backpack\CRUD\app\Library\CrudPanel\CrudPanel.
Loading history...
227
    }
228
229
    /**
230
     * Make the current field the last one in the fields list.
231
     *
232
     * @return CrudPanel
233
     */
234
    public function makeLast()
235
    {
236
        $this->crud()->removeFilter($this->name);
237
        $this->crud()->addCrudFilter($this);
238
239
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Backpack\CRUD\app\Library\CrudPanel\CrudFilter which is incompatible with the documented return type Backpack\CRUD\app\Library\CrudPanel\CrudPanel.
Loading history...
240
    }
241
242
    // -----------------------
243
    // FILTER-SPECIFIC SETTERS
244
    // -----------------------
245
246
    /**
247
     * Set the type of the filter.
248
     *
249
     * @param  string $value Name of blade view that shows the field.
250
     * @return CrudFilter
251
     */
252
    public function type($value)
253
    {
254
        $this->type = $value;
255
        $this->view = $value;
256
257
        return $this->save();
258
    }
259
260
    /**
261
     * Set the label of the filter - the element that the end-user can see and click
262
     * to activate the filter or an input that will activate the filter.
263
     *
264
     * @param  string $value A name for this filter that the end-user will understand.
265
     * @return CrudFilter
266
     */
267
    public function label($value)
268
    {
269
        $this->label = $value;
270
271
        return $this->save();
272
    }
273
274
    /**
275
     * Set the values for the current filter, for the filters who need values.
276
     * For example, the dropdown, select2 and select2 filters let the user select
277
     * pre-determined values to filter with. This is how to set those values that will be picked up.
278
     *
279
     * @param  array $value Key-value array with values for the user to pick from.
280
     * @return CrudFilter
281
     */
282
    public function values($value)
283
    {
284
        $this->values = $value;
285
286
        return $this->save();
287
    }
288
289
    /**
290
     * Set the blade view that will be used by the filter.
291
     * Should NOT include the namespace, that's defined separately using 'viewNamespace'.
292
     *
293
     * @param  string $value Path to the blade file, after the view namespace.
294
     * @return CrudFilter
295
     */
296
    public function view($value)
297
    {
298
        $this->view = $value;
299
300
        return $this->save();
301
    }
302
303
    /**
304
     * The path to the blade views directory where the filter file will be found. Ex: 'crud::filters'
305
     * Useful to load filters from a different package or directory.
306
     *
307
     * @param  string $value Blade path to the directory.
308
     * @return CrudFilter
309
     */
310
    public function viewNamespace($value)
311
    {
312
        $this->viewNamespace = $value;
313
314
        return $this->save();
315
    }
316
317
    /**
318
     * Define what happens when the filter is active, through a closure.
319
     *
320
     * @param  Closure $value Closure that will be called when Request has this name as GET parameter.
0 ignored issues
show
Bug introduced by
The type Backpack\CRUD\app\Library\CrudPanel\Closure was not found. Did you mean Closure? If so, make sure to prefix the type with \.
Loading history...
321
     * @return CrudFilter
322
     */
323
    public function logic($value)
324
    {
325
        $this->logic = $value;
326
327
        return $this->save();
328
    }
329
330
    /**
331
     * Define what happens when the filter is NOT active, through a closure.
332
     *
333
     * @param  Closure $value Closure that will be called when Request does NOT have this name as GET parameter.
334
     * @return CrudFilter
335
     */
336
    public function fallbackLogic($value)
337
    {
338
        $this->fallbackLogic = $value;
339
340
        return $this->save();
341
    }
342
343
    /**
344
     * Define if the filter has already been applied (logic or fallbackLogic called).
345
     *
346
     * @param  bool $value Whether the filter has been run.
347
     * @return CrudFilter
348
     */
349
    public function applied($value)
350
    {
351
        $this->applied = $value;
352
353
        return $this->save();
354
    }
355
356
    /**
357
     * Aliases of the logic() method.
358
     */
359
    public function whenActive($value)
360
    {
361
        return $this->logic($value);
362
    }
363
364
    public function ifActive($value)
365
    {
366
        return $this->logic($value);
367
    }
368
369
    /**
370
     * Alises of the fallbackLogic() method.
371
     */
372
    public function whenInactive($value)
373
    {
374
        return $this->fallbackLogic($value);
375
    }
376
377
    public function whenNotActive($value)
378
    {
379
        return $this->fallbackLogic($value);
380
    }
381
382
    public function ifInactive($value)
383
    {
384
        return $this->fallbackLogic($value);
385
    }
386
387
    public function ifNotActive($value)
388
    {
389
        return $this->fallbackLogic($value);
390
    }
391
392
    public function else($value)
393
    {
394
        return $this->fallbackLogic($value);
395
    }
396
397
    // ---------------
398
    // PRIVATE METHODS
399
    // ---------------
400
401
    private function crud()
402
    {
403
        return app()->make('crud');
404
    }
405
406
    /**
407
     * Set the value for a certain attribute on the CrudFilter object.
408
     *
409
     * @param string $attribute Name of the attribute.
410
     * @param string $value     Value of that attribute.
411
     */
412
    private function setOptionValue($attribute, $value)
413
    {
414
        $this->options[$attribute] = $value;
415
    }
416
417
    /**
418
     * Replace all field options on the CrudFilter object
419
     * with the given array of attribute-value pairs.
420
     *
421
     * @param array $array Array of options and their values.
422
     */
423
    private function setAllOptionsValues($array)
0 ignored issues
show
Unused Code introduced by
The method setAllOptionsValues() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
424
    {
425
        $this->options = $array;
426
    }
427
428
    /**
429
     * Update the global CrudPanel object with the current field options.
430
     *
431
     * @return CrudFilter
432
     */
433
    private function save()
434
    {
435
        $key = $this->name;
436
437
        if ($this->crud()->hasFilterWhere('name', $key)) {
438
            $this->crud()->modifyFilter($key, (array) $this);
439
        } else {
440
            $this->crud()->addCrudFilter($this);
441
        }
442
443
        return $this;
444
    }
445
446
    /**
447
     * @param string $name
448
     * @param string $operator
449
     * @param array  $input
450
     */
451
    private function applyDefaultLogic($name, $operator, $input = null)
452
    {
453
        $input = $input ?? $this->crud()->getRequest()->all();
454
455
        // if this filter is active (the URL has it as a GET parameter)
456
        switch ($operator) {
457
            // if no operator was passed, just use the equals operator
458
            case false:
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $operator of type string to the boolean false. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
459
                $this->crud()->addClause('where', $name, $input[$name]);
460
                break;
461
462
            case 'scope':
463
                $this->crud()->addClause($operator);
464
                break;
465
466
            // TODO:
467
            // whereBetween
468
            // whereNotBetween
469
            // whereIn
470
            // whereNotIn
471
            // whereNull
472
            // whereNotNull
473
            // whereDate
474
            // whereMonth
475
            // whereDay
476
            // whereYear
477
            // whereColumn
478
            // like
479
480
            // sql comparison operators
481
            case '=':
482
            case '<=>':
483
            case '<>':
484
            case '!=':
485
            case '>':
486
            case '>=':
487
            case '<':
488
            case '<=':
489
                $this->crud()->addClause('where', $name, $operator, $input[$name]);
490
                break;
491
492
            default:
493
                abort(500, 'Unknown filter operator.');
494
                break;
495
        }
496
    }
497
498
    // -----------------
499
    // DEBUGGING METHODS
500
    // -----------------
501
502
    /**
503
     * Dump the current object to the screen,
504
     * so that the developer can see its contents.
505
     *
506
     * @return CrudFilter
507
     */
508
    public function dump()
509
    {
510
        dump($this);
511
512
        return $this;
513
    }
514
515
    /**
516
     * Dump and die. Duumps the current object to the screen,
517
     * so that the developer can see its contents, then stops
518
     * the execution.
519
     *
520
     * @return CrudFilter
521
     */
522
    public function dd()
523
    {
524
        dd($this);
525
526
        return $this;
527
    }
528
529
    // -------------
530
    // MAGIC METHODS
531
    // -------------
532
533
    /**
534
     * If a developer calls a method that doesn't exist, assume they want:
535
     * - $this->options['whatever'] to be set to that value;
536
     * - that filter be updated inside the global CrudPanel object;.
537
     *
538
     * Eg: type('number') will set the "type" attribute to "number"
539
     *
540
     * @param  string $method     The method being called that doesn't exist.
541
     * @param  array $parameters  The arguments when that method was called.
542
     *
543
     * @return CrudFilter
544
     */
545
    public function __call($method, $parameters)
546
    {
547
        $this->setOptionValue($method, $parameters[0]);
548
549
        return $this->save();
550
    }
551
}
552