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

Test Setup Failed
Pull Request — master (#3182)
by
unknown
24:32
created

CrudFilter::ifNotActive()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Backpack\CRUD\app\Library\CrudPanel;
4
5
use Closure;
6
use Illuminate\Support\Str;
7
use Symfony\Component\HttpFoundation\ParameterBag;
8
9
class CrudFilter
10
{
11
    public $name; // the name of the filtered variable (db column name)
12
    public $type = 'select2'; // the name of the filter view that will be loaded
13
    public $key; //camelCased version of filter name to use in internal ids, js functions and css classes.
14
    public $label;
15
    public $placeholder;
16
    public $values;
17
    public $options;
18
    public $logic;
19
    public $fallbackLogic;
20
    public $currentValue;
21
    public $view;
22
    public $viewNamespace = 'crud::filters';
23
    public $applied = false;
24
25
    public function __construct($options, $values, $logic, $fallbackLogic)
26
    {
27
        // if filter exists
28
        if ($this->crud()->hasFilterWhere('name', $options['name'])) {
29
            $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

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

120
            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...
121
        }
122
123
        // if fallback logic was supplied and is a closure
124
        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...
125
            return ($this->fallbackLogic)();
126
        }
127
    }
128
129
    /**
130
     * Get the full path of the filter view, including the view namespace.
131
     *
132
     * @return string
133
     */
134
    public function getViewWithNamespace()
135
    {
136
        return $this->viewNamespace.'.'.$this->view;
137
    }
138
139
    // ---------------------
140
    // FLUENT SYNTAX METHODS
141
    // ---------------------
142
143
    /**
144
     * Create a CrudFilter object with the parameter as its name.
145
     *
146
     * @param  string $name Name of the column in the db, or model attribute.
147
     * @return CrudPanel
148
     */
149
    public static function name($name)
150
    {
151
        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...
152
    }
153
154
    /**
155
     * Remove the current filter from the current operation.
156
     *
157
     * @return void
158
     */
159
    public function remove()
160
    {
161
        $this->crud()->removeFilter($this->name);
162
    }
163
164
    /**
165
     * Remove an attribute from the current filter definition array.
166
     *
167
     * @param  string $attribute Name of the attribute being removed.
168
     * @return CrudFilter
169
     */
170
    public function forget($attribute)
171
    {
172
        if (property_exists($this, $attribute)) {
173
            $this->{$attribute} = false;
174
        }
175
176
        if (isset($this->options[$attribute])) {
177
            unset($this->options[$attribute]);
178
        }
179
180
        $this->crud()->replaceFilter($this->name, $this);
181
182
        return $this;
183
    }
184
185
    /**
186
     * Remove an attribute from one field's definition array.
187
     * @param  string $field     The name of the field.
188
     * @param  string $attribute The name of the attribute being removed.
189
     */
190
    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

190
    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...
191
    {
192
        $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

192
        /** @scrutinizer ignore-call */ 
193
        $fields = $this->fields();
Loading history...
193
194
        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...
195
196
        $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

196
        $this->/** @scrutinizer ignore-call */ 
197
               setOperationSetting('fields', $fields);
Loading history...
197
    }
198
199
    /**
200
     * Move the current filter after another filter.
201
     *
202
     * @param  string $destination Name of the destination filter.
203
     * @return CrudFilter
204
     */
205
    public function after($destination)
206
    {
207
        $this->crud()->moveFilter($this->name, 'after', $destination);
208
209
        return $this;
210
    }
211
212
    /**
213
     * Move the current field before another field.
214
     *
215
     * @param  string $destination Name of the destination field.
216
     * @return CrudFilter
217
     */
218
    public function before($destination)
219
    {
220
        $this->crud()->moveFilter($this->name, 'before', $destination);
221
222
        return $this;
223
    }
224
225
    /**
226
     * Make the current field the first one in the fields list.
227
     *
228
     * @return CrudPanel
229
     */
230
    public function makeFirst()
231
    {
232
        $this->crud()->moveFilter($this->name, 'before', $this->crud()->filters()->first()->name);
233
234
        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...
235
    }
236
237
    /**
238
     * Make the current field the last one in the fields list.
239
     *
240
     * @return CrudPanel
241
     */
242
    public function makeLast()
243
    {
244
        $this->crud()->removeFilter($this->name);
245
        $this->crud()->addCrudFilter($this);
246
247
        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...
248
    }
249
250
    // -----------------------
251
    // FILTER-SPECIFIC SETTERS
252
    // -----------------------
253
254
    /**
255
     * Set the type of the filter.
256
     *
257
     * @param  string $value Name of blade view that shows the field.
258
     * @return CrudFilter
259
     */
260
    public function type($value)
261
    {
262
        $this->type = $value;
263
        $this->view = $value;
264
265
        return $this->save();
266
    }
267
268
    /**
269
     * Set the label of the filter - the element that the end-user can see and click
270
     * to activate the filter or an input that will activate the filter.
271
     *
272
     * @param  string $value A name for this filter that the end-user will understand.
273
     * @return CrudFilter
274
     */
275
    public function label($value)
276
    {
277
        $this->label = $value;
278
279
        return $this->save();
280
    }
281
282
    /**
283
     * Set the values for the current filter, for the filters who need values.
284
     * For example, the dropdown, select2 and select2 filters let the user select
285
     * pre-determined values to filter with. This is how to set those values that will be picked up.
286
     *
287
     * @param  array $value Key-value array with values for the user to pick from.
288
     * @return CrudFilter
289
     */
290
    public function values($value)
291
    {
292
        $this->values = $value;
293
294
        return $this->save();
295
    }
296
297
    /**
298
     * Set the blade view that will be used by the filter.
299
     * Should NOT include the namespace, that's defined separately using 'viewNamespace'.
300
     *
301
     * @param  string $value Path to the blade file, after the view namespace.
302
     * @return CrudFilter
303
     */
304
    public function view($value)
305
    {
306
        $this->view = $value;
307
308
        return $this->save();
309
    }
310
311
    /**
312
     * The path to the blade views directory where the filter file will be found. Ex: 'crud::filters'
313
     * Useful to load filters from a different package or directory.
314
     *
315
     * @param  string $value Blade path to the directory.
316
     * @return CrudFilter
317
     */
318
    public function viewNamespace($value)
319
    {
320
        $this->viewNamespace = $value;
321
322
        return $this->save();
323
    }
324
325
    /**
326
     * Define what happens when the filter is active, through a closure.
327
     *
328
     * @param  Closure $value Closure that will be called when Request has this name as GET parameter.
329
     * @return CrudFilter
330
     */
331
    public function logic($value)
332
    {
333
        $this->logic = $value;
334
335
        return $this->save();
336
    }
337
338
    /**
339
     * Define what happens when the filter is NOT active, through a closure.
340
     *
341
     * @param  Closure $value Closure that will be called when Request does NOT have this name as GET parameter.
342
     * @return CrudFilter
343
     */
344
    public function fallbackLogic($value)
345
    {
346
        $this->fallbackLogic = $value;
347
348
        return $this->save();
349
    }
350
351
    /**
352
     * Define if the filter has already been applied (logic or fallbackLogic called).
353
     *
354
     * @param  bool $value Whether the filter has been run.
355
     * @return CrudFilter
356
     */
357
    public function applied($value)
358
    {
359
        $this->applied = $value;
360
361
        return $this->save();
362
    }
363
364
    /**
365
     * Aliases of the logic() method.
366
     */
367
    public function whenActive($value)
368
    {
369
        return $this->logic($value);
370
    }
371
372
    public function ifActive($value)
373
    {
374
        return $this->logic($value);
375
    }
376
377
    /**
378
     * Alises of the fallbackLogic() method.
379
     */
380
    public function whenInactive($value)
381
    {
382
        return $this->fallbackLogic($value);
383
    }
384
385
    public function whenNotActive($value)
386
    {
387
        return $this->fallbackLogic($value);
388
    }
389
390
    public function ifInactive($value)
391
    {
392
        return $this->fallbackLogic($value);
393
    }
394
395
    public function ifNotActive($value)
396
    {
397
        return $this->fallbackLogic($value);
398
    }
399
400
    public function else($value)
401
    {
402
        return $this->fallbackLogic($value);
403
    }
404
405
    // ---------------
406
    // PRIVATE METHODS
407
    // ---------------
408
409
    private function crud()
410
    {
411
        return app()->make('crud');
412
    }
413
414
    /**
415
     * Set the value for a certain attribute on the CrudFilter object.
416
     *
417
     * @param string $attribute Name of the attribute.
418
     * @param string $value     Value of that attribute.
419
     */
420
    private function setOptionValue($attribute, $value)
421
    {
422
        $this->options[$attribute] = $value;
423
    }
424
425
    /**
426
     * Replace all field options on the CrudFilter object
427
     * with the given array of attribute-value pairs.
428
     *
429
     * @param array $array Array of options and their values.
430
     */
431
    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...
432
    {
433
        $this->options = $array;
434
    }
435
436
    /**
437
     * Update the global CrudPanel object with the current field options.
438
     *
439
     * @return CrudFilter
440
     */
441
    private function save()
442
    {
443
        $key = $this->name;
444
445
        if ($this->crud()->hasFilterWhere('name', $key)) {
446
            $this->crud()->modifyFilter($key, (array) $this);
447
        } else {
448
            $this->crud()->addCrudFilter($this);
449
        }
450
451
        return $this;
452
    }
453
454
    /**
455
     * @param string $name
456
     * @param string $operator
457
     * @param array  $input
458
     */
459
    private function applyDefaultLogic($name, $operator, $input = null)
460
    {
461
        $input = $input ?? $this->crud()->getRequest()->all();
462
463
        // if this filter is active (the URL has it as a GET parameter)
464
        switch ($operator) {
465
            // if no operator was passed, just use the equals operator
466
            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...
467
                $this->crud()->addClause('where', $name, $input[$name]);
468
                break;
469
470
            case 'scope':
471
                $this->crud()->addClause($operator);
472
                break;
473
474
            // TODO:
475
            // whereBetween
476
            // whereNotBetween
477
            // whereIn
478
            // whereNotIn
479
            // whereNull
480
            // whereNotNull
481
            // whereDate
482
            // whereMonth
483
            // whereDay
484
            // whereYear
485
            // whereColumn
486
            // like
487
488
            // sql comparison operators
489
            case '=':
490
            case '<=>':
491
            case '<>':
492
            case '!=':
493
            case '>':
494
            case '>=':
495
            case '<':
496
            case '<=':
497
                $this->crud()->addClause('where', $name, $operator, $input[$name]);
498
                break;
499
500
            default:
501
                abort(500, 'Unknown filter operator.');
502
                break;
503
        }
504
    }
505
506
    // -----------------
507
    // DEBUGGING METHODS
508
    // -----------------
509
510
    /**
511
     * Dump the current object to the screen,
512
     * so that the developer can see its contents.
513
     *
514
     * @return CrudFilter
515
     */
516
    public function dump()
517
    {
518
        dump($this);
519
520
        return $this;
521
    }
522
523
    /**
524
     * Dump and die. Duumps the current object to the screen,
525
     * so that the developer can see its contents, then stops
526
     * the execution.
527
     *
528
     * @return CrudFilter
529
     */
530
    public function dd()
531
    {
532
        dd($this);
533
534
        return $this;
535
    }
536
537
    // -------------
538
    // MAGIC METHODS
539
    // -------------
540
541
    /**
542
     * If a developer calls a method that doesn't exist, assume they want:
543
     * - $this->options['whatever'] to be set to that value;
544
     * - that filter be updated inside the global CrudPanel object;.
545
     *
546
     * Eg: type('number') will set the "type" attribute to "number"
547
     *
548
     * @param  string $method     The method being called that doesn't exist.
549
     * @param  array $parameters  The arguments when that method was called.
550
     *
551
     * @return CrudFilter
552
     */
553
    public function __call($method, $parameters)
554
    {
555
        $this->setOptionValue($method, $parameters[0]);
556
557
        return $this->save();
558
    }
559
}
560