GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( b9a354...5c9a99 )
by Aden
03:57
created

ModelAdmin::isSortableBy()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 19
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 19
rs 8.8571
cc 5
eloc 8
nc 4
nop 1
1
<?php
2
3
namespace LaravelFlare\Flare\Admin\Models;
4
5
use Illuminate\Support\Str;
6
use LaravelFlare\Flare\Admin\Admin;
7
use LaravelFlare\Flare\Traits\ModelAdmin\ModelSaving;
8
use LaravelFlare\Flare\Exceptions\ModelAdminException;
9
use LaravelFlare\Flare\Traits\ModelAdmin\ModelQuerying;
10
use LaravelFlare\Flare\Contracts\ModelAdmin\ModelQueryable;
11
use LaravelFlare\Flare\Admin\Attributes\AttributeCollection;
12
13
class ModelAdmin extends Admin implements ModelQueryable
14
{
15
    use ModelQuerying;
16
    use ModelSaving;
17
18
    /**
19
     * Class of Model to Manage.
20
     * 
21
     * @var string
22
     */
23
    protected $managedModel;
24
25
    /**
26
     * ModelAdmin Icon.
27
     *
28
     * Font Awesome Defined Icon, eg 'user' = 'fa-user'
29
     *
30
     * @var string
31
     */
32
    protected $icon = '';
33
34
    /**
35
     * Validation Rules for onCreate, onEdit actions.
36
     * 
37
     * @var array
38
     */
39
    protected $rules = [];
40
41
    /**
42
     * Columns for Model.
43
     *
44
     * Defines which fields to show in the listing tables output.
45
     * 
46
     * @var array
47
     */
48
    protected $columns = [];
49
50
    /**
51
     * Map Model Attributes to AttributeTypes with
52
     * additional parameters which will be output
53
     * as fields when viewing, editting or adding
54
     * a new model entry.
55
     * 
56
     * @var array
57
     */
58
    protected $fields = [];
59
60
    /**
61
     * Columns for Model are Sortable.
62
     *
63
     * @var bool
64
     */
65
    protected $sortable = true;
66
67
    /**
68
     * The Controller to be used by the Model Admin.
69
     *
70
     * This defaults to parent::getController()
71
     * if it has been left undefined. 
72
     * 
73
     * @var string
74
     */
75
    protected $controller = '\LaravelFlare\Flare\Admin\Models\ModelAdminController';
76
77
    /**
78
     * The Policy used for the Model Authorization logic.
79
     *
80
     * This class should implement the ModelAdminPoliceable which
81
     * includes authorization checks for the create, view, edit and delete actions.
82
     * 
83
     * @var string
84
     */
85
    protected $policy = '\LaravelFlare\Flare\Permissions\ModelAdminPolicy';
86
87
    /**
88
     * The current model to be managed.
89
     * 
90
     * @var Model
91
     */
92
    public $model;
93
94
    /**
95
     * __construct.
96
     */
97
    public function __construct()
98
    {
99
        $this->getManagedModel();
100
101
        $this->model = $this->model();
102
103
        $this->formatFields();
104
    }
105
106
    /**
107
     * Returns a Model Instance.
108
     * 
109
     * @return Model
110
     */
111
    public function model()
112
    {
113
        if (!$this->model) {
114
            $class = $this->getManagedModel();
115
116
            return $this->model = new $class();
117
        }
118
119
        return $this->model;
120
    }
121
122
    /**
123
     * Returns a New Model Instance.
124
     *
125
     * @return Model
126
     */
127
    public function newModel()
128
    {
129
        $class = self::getManagedModel();
130
131
        return new $class();
132
    }
133
134
    /**
135
     * Returns the Managed Model Class.
136
     * 
137
     * @return string
138
     */
139
    public function getManagedModel()
140
    {
141
        if (!isset($this->managedModel) || $this->managedModel === null) {
142
            throw new ModelAdminException('You have a ModelAdmin which does not have a model assigned to it. ModelAdmins must include a model to manage.', 1);
143
        }
144
145
        return $this->managedModel;
146
    }
147
148
    /**
149
     * Set the Managed Model Class.
150
     * 
151
     * @param string $managedModel
152
     */
153
    public function setManagedModel($managedModel = null)
154
    {
155
        $this->managedModel = $managedModel;
156
    }
157
158
    /**
159
     * Returns the Route Paramets.
160
     * 
161
     * @return array
162
     */
163
    public function routeParameters()
164
    {
165
        return array_merge(parent::routeParameters(), [
166
                                                    'model' => $this->managedModel,
167
                                                ]);
168
    }
169
170
    /**
171
     * Formats and returns the Columns.
172
     *
173
     * This is really gross, I'm removing it soon.
174
     * 
175
     * @return
176
     */
177
    public function getColumns()
178
    {
179
        $columns = [];
180
181
        foreach ($this->columns as $field => $fieldTitle) {
182
            if (in_array($field, $this->model->getFillable())) {
183
                if (!$field) {
184
                    $field = $fieldTitle;
185
                    $fieldTitle = Str::title($fieldTitle);
186
                }
187
                $columns[$field] = $fieldTitle;
188
                continue;
189
            }
190
191
            // We can replace this with data_get() I believe.
192
            if (($methodBreaker = strpos($field, '.')) !== false) {
193
                $method = substr($field, 0, $methodBreaker);
194
                if (method_exists($this->model, $method)) {
195
                    if (method_exists($this->model->$method(), $submethod = str_replace($method.'.', '', $field))) {
196
                        $this->model->$method()->$submethod();
197
198
                        $columns[$field] = $fieldTitle;
199
                        continue;
200
                    }
201
                }
202
            }
203
204
            if (is_numeric($field)) {
205
                $field = $fieldTitle;
206
                $fieldTitle = Str::title($fieldTitle);
207
            }
208
209
            $columns[$field] = $fieldTitle;
210
        }
211
212
        if (count($columns)) {
213
            return $columns;
214
        }
215
216
        return [$this->model->getKeyName() => $this->model->getKeyName()];
217
    }
218
219
    /**
220
     * Gets an Attribute by the provided key
221
     * on either the current model or a provided model instance.
222
     * 
223
     * @param string $key
224
     * @param mixed  $model
225
     * 
226
     * @return mixed
227
     */
228
    public function getAttribute($key, $model = false)
229
    {
230
        if (!$model) {
231
            $model = $this->model;
232
        }
233
234
        if ($this->hasGetAccessor($key)) {
235
            $method = 'get'.Str::studly($key).'Attribute';
236
237
            return $this->{$method}($model);
238
        }
239
240
        if ($this->hasRelatedKey($key, $model)) {
241
            return $this->relatedKey($key, $model);
242
        }    
243
244
        return $model->getAttribute($key);
245
    }
246
247
    /**
248
     * Determine if a get accessor exists for an attribute.
249
     *
250
     * @param string $key
251
     * 
252
     * @return bool
253
     */
254
    public function hasGetAccessor($key)
255
    {
256
        return method_exists($this, 'get'.Str::studly($key).'Attribute');
257
    }
258
259
    /**
260
     * Determines if a key resolved a related Model.
261
     * 
262
     * @param string $key
263
     * @param mixed  $model
264
     * 
265
     * @return bool
266
     */
267
    public function hasRelatedKey($key, $model = false)
268
    {
269
        if (!$model) {
270
            $model = $this->model;
271
        }
272
273
        if (($methodBreaker = strpos($key, '.')) !== false) {
274
            $method = substr($key, 0, $methodBreaker);
275
            if (method_exists($model, $method)) {
276
                return true;
277
            }
278
        }
279
280
        return false;
281
    }
282
283
    /**
284
     * Resolves a relation based on the key provided,
285
     * either on the current model or a provided model instance.
286
     * 
287
     * @param string $key
288
     * @param mixed  $model
289
     * 
290
     * @return mixed
291
     */
292
    public function relatedKey($key, $model = false)
293
    {
294
        if (!$model) {
295
            $model = $this->model;
296
        }
297
298
        if (($methodBreaker = strpos($key, '.')) !== false) {
299
            $method = substr($key, 0, $methodBreaker);
300
            if (method_exists($model, $method)) {
301
                if (method_exists($model->$method, $submethod = str_replace($method.'.', '', $key))) {
302
                    return $model->$method->$submethod();
303
                }
304
305
                if (isset($model->$method->$submethod)) {
306
                    return $model->$method->$submethod;
307
                }
308
309
                return $model->getRelationValue($method);
310
            }
311
        }
312
313
        return false;
314
    }
315
316
    /**
317
     * Set a given attribute on the model.
318
     *
319
     * @param string $key
320
     * @param mixed  $value
321
     */
322
    public function setAttribute($key, $value)
323
    {
324
        if ($this->hasSetMutator($key)) {
325
            $method = 'set'.Str::studly($key).'Attribute';
326
327
            return $this->{$method}($value);
328
        }
329
330
        $this->model->attributes[$key] = $value;
331
    }
332
333
    /**
334
     * Determine if a set mutator exists for an attribute.
335
     *
336
     * @param string $key
337
     * 
338
     * @return bool
339
     */
340
    public function hasSetMutator($key)
341
    {
342
        return method_exists($this, 'set'.Str::studly($key).'Attribute');
343
    }
344
345
    /**
346
     * Determine if a get mutator exists for an attribute.
347
     *
348
     * @param string $key
349
     * 
350
     * @return bool
351
     */
352
    public function hasGetMutator($key)
353
    {
354
        return method_exists($this, 'get'.Str::studly($key).'Attribute');
355
    }
356
357
    /**
358
     * Returns an array of Attribute Fields ready for output.
359
     *
360
     * @param  string $type 
361
     * 
362
     * @return array
363
     */
364
    public function outputFields($type = 'view')
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed.

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

Loading history...
365
    {
366
        return $this->getFields();
367
    }
368
369
    /**
370
     * Gets the Managed Model Mapping.
371
     * 
372
     * @return array
373
     */
374
    public function getFields()
375
    {
376
        $this->setFields($this->fields);
377
378
        return $this->fields;
379
    }
380
381
    /**
382
     * Sets the Managed Model Mapping.
383
     * 
384
     * @param array $fields
385
     */
386
    public function setFields($fields = [])
387
    {
388
        $this->fields = $fields;
389
390
        $this->formatFields();
391
    }
392
393
    /**
394
     * Format the provided Attribute Fields into a more usable format.
395
     * 
396
     * @return void
397
     */
398
    protected function formatFields()
399
    {
400
        $fields = $this->fields;
401
402
        if (!$fields instanceof AttributeCollection) {
403
            $fields = new AttributeCollection($fields, $this);
404
        }
405
406
        return $this->fields = $fields->formatFields();
0 ignored issues
show
Documentation Bug introduced by
It seems like $fields->formatFields() of type object<LaravelFlare\Flar...es\AttributeCollection> is incompatible with the declared type array of property $fields.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
407
    }
408
409
    /**
410
     * Determine if the Model Admin is sortable in it's list view.
411
     * 
412
     * @return bool
413
     */
414
    public function isSortable()
415
    {
416
        return isset($this->sortable) && $this->sortable ? true : false;
417
    }
418
419
    /**
420
     * Determine if the Model Admin is sortable by a defined key / column.
421
     *
422
     * @param string $key
423
     * 
424
     * @return bool
425
     */
426
    public function isSortableBy($key)
427
    {
428
        // Sorting is not allowed on Model Admin
429
        if (!$this->isSortable()) {
430
            return false;
431
        }
432
433
        // Key results are mutated, so sorting is not available
434
        if ($this->model()->hasGetMutator($key) || $this->hasGetMutator($key)) {
435
            return false;
436
        }
437
438
        // Key is a relation, so sorting is not available 
439
        if (strpos($key, '.') !== false) {
440
            return false;
441
        }
442
443
        return true;
444
    }
445
446
    /**
447
     * Determine if the Model Admin has Viewing Capabilities.
448
     * 
449
     * @return bool
450
     */
451
    public function hasViewing()
452
    {
453
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelViewing::class);
454
    }
455
456
    /**
457
     * Determine if the Model Admin has Creating Capabilities.
458
     * 
459
     * @return bool
460
     */
461
    public function hasCreating()
462
    {
463
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelCreating::class);
464
    }
465
466
    /**
467
     * Determine if the Model Admin has Cloning Capabilities.
468
     * 
469
     * @return bool
470
     */
471
    public function hasCloning()
472
    {
473
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelCloning::class);
474
    }
475
476
    /**
477
     * Determine if the Model Admin has Editting Capabilities.
478
     * 
479
     * @return bool
480
     */
481
    public function hasEditting()
482
    {
483
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelEditting::class);
484
    }
485
486
    /**
487
     * Determine if the Model Admin has Deleting Capabilities.
488
     * 
489
     * @return bool
490
     */
491
    public function hasDeleting()
492
    {
493
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelDeleting::class);
494
    }
495
496
    /**
497
     * Determine if the Managed Model is using the SoftDeletes Trait.
498
     *
499
     * This is guarded by hasDeleting, since we shouldn't allow SoftDeleting
500
     * without the deleting trait (even though it isn't really required).
501
     *
502
     * @return bool
503
     */
504
    public function hasSoftDeleting()
505
    {
506
        if (!$this->hasDeleting()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->hasDeleting() of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
507
            return false;
508
        }
509
510
        $managedModelClass = $this->getManagedModel();
511
512
        return in_array(
513
            \Illuminate\Database\Eloquent\SoftDeletes::class, class_uses_recursive(get_class(new $managedModelClass()))
514
        ) && in_array(
515
            \LaravelFlare\Flare\Traits\ModelAdmin\ModelSoftDeleting::class, class_uses_recursive(get_class($this))
516
        );
517
    }
518
519
    /**
520
     * Determine if the Model Admin has Validating Capabilities.
521
     * 
522
     * @return bool
523
     */
524
    public function hasValidating()
525
    {
526
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelValidating::class);
527
    }
528
529
    /**
530
     * Determine if the Managed Model has a Trait and Contract
531
     *
532
     * @return bool
533
     */
534
    public function hasTraitAndContract($trait = null, $contract = null)
535
    {
536
        return ($this->hasTrait($trait) && $this->hasContract($contract));
537
    }
538
539
    /**
540
     * Returns whether the current ModelAdmin has a given trait.
541
     * 
542
     * @param  string  $trait  
543
     * 
544
     * @return boolean        
545
     */
546
    public function hasTrait($trait = null)
547
    {
548
        if (!$trait) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $trait of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
549
            return;
550
        }
551
552
        return in_array($trait, class_uses_recursive(get_class($this)));
553
    }
554
555
    /**
556
     * Returns whether the current ModelAdmin has a given contract.
557
     * 
558
     * @param  string  $contract  
559
     * 
560
     * @return boolean        
561
     */
562
    public function hasContract($contract = null)
0 ignored issues
show
Unused Code introduced by
The parameter $contract is not used and could be removed.

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

Loading history...
563
    {
564
        if (!$trait) {
0 ignored issues
show
Bug introduced by
The variable $trait does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
565
            return;
566
        }
567
        
568
        $managedModelClass = $this->getManagedModel();
0 ignored issues
show
Unused Code introduced by
$managedModelClass is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
569
    }
570
}
571