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 ( cc3baf...54684c )
by Aden
04:25
created

ModelAdmin::getAttribute()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 22
rs 8.6737
cc 5
eloc 11
nc 7
nop 2
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 (!$key) {
231
            return;
232
        }
233
234
        if (!$model) {
235
            $model = $this->model;
236
        }
237
238
        if ($this->hasGetAccessor($key)) {
239
            $method = 'get'.Str::studly($key).'Attribute';
240
241
            return $this->{$method}($model);
242
        }
243
244
        if ($this->hasRelatedKey($key, $model)) {
245
            return $this->relatedKey($key, $model);
246
        }    
247
248
        return $model->getAttribute($key);
249
    }
250
251
    /**
252
     * Determine if a get accessor exists for an attribute.
253
     *
254
     * @param string $key
255
     * 
256
     * @return bool
257
     */
258
    public function hasGetAccessor($key)
259
    {
260
        return method_exists($this, 'get'.Str::studly($key).'Attribute');
261
    }
262
263
    /**
264
     * Determines if a key resolved a related Model.
265
     * 
266
     * @param string $key
267
     * @param mixed  $model
268
     * 
269
     * @return bool
270
     */
271
    public function hasRelatedKey($key, $model = false)
272
    {
273
        if (!$model) {
274
            $model = $this->model;
275
        }
276
277
        if (($methodBreaker = strpos($key, '.')) !== false) {
278
            $method = substr($key, 0, $methodBreaker);
279
            if (method_exists($model, $method)) {
280
                return true;
281
            }
282
        }
283
284
        return false;
285
    }
286
287
    /**
288
     * Resolves a relation based on the key provided,
289
     * either on the current model or a provided model instance.
290
     * 
291
     * @param string $key
292
     * @param mixed  $model
293
     * 
294
     * @return mixed
295
     */
296
    public function relatedKey($key, $model = false)
297
    {
298
        if (!$model) {
299
            $model = $this->model;
300
        }
301
302
        if (($methodBreaker = strpos($key, '.')) !== false) {
303
            $method = substr($key, 0, $methodBreaker);
304
            if (method_exists($model, $method)) {
305
                if (method_exists($model->$method, $submethod = str_replace($method.'.', '', $key))) {
306
                    return $model->$method->$submethod();
307
                }
308
309
                if (isset($model->$method->$submethod)) {
310
                    return $model->$method->$submethod;
311
                }
312
313
                return $model->getRelationValue($method);
314
            }
315
        }
316
317
        return false;
318
    }
319
320
    /**
321
     * Set a given attribute on the model.
322
     *
323
     * @param string $key
324
     * @param mixed  $value
325
     */
326
    public function setAttribute($key, $value)
327
    {
328
        if ($this->hasSetMutator($key)) {
329
            $method = 'set'.Str::studly($key).'Attribute';
330
331
            return $this->{$method}($value);
332
        }
333
334
        $this->model->attributes[$key] = $value;
335
    }
336
337
    /**
338
     * Determine if a set mutator exists for an attribute.
339
     *
340
     * @param string $key
341
     * 
342
     * @return bool
343
     */
344
    public function hasSetMutator($key)
345
    {
346
        return method_exists($this, 'set'.Str::studly($key).'Attribute');
347
    }
348
349
    /**
350
     * Determine if a get mutator exists for an attribute.
351
     *
352
     * @param string $key
353
     * 
354
     * @return bool
355
     */
356
    public function hasGetMutator($key)
357
    {
358
        return method_exists($this, 'get'.Str::studly($key).'Attribute');
359
    }
360
361
    /**
362
     * Returns an array of Attribute Fields ready for output.
363
     *
364
     * @param  string $type 
365
     * 
366
     * @return array
367
     */
368
    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...
369
    {
370
        return $this->getFields();
371
    }
372
373
    /**
374
     * Gets the Managed Model Mapping.
375
     * 
376
     * @return array
377
     */
378
    public function getFields()
379
    {
380
        $this->setFields($this->fields);
381
382
        return $this->fields;
383
    }
384
385
    /**
386
     * Sets the Managed Model Mapping.
387
     * 
388
     * @param array $fields
389
     */
390
    public function setFields($fields = [])
391
    {
392
        $this->fields = $fields;
393
394
        $this->formatFields();
395
    }
396
397
    /**
398
     * Format the provided Attribute Fields into a more usable format.
399
     * 
400
     * @return void
401
     */
402
    protected function formatFields()
403
    {
404
        $fields = $this->fields;
405
406
        if (!$fields instanceof AttributeCollection) {
407
            $fields = new AttributeCollection($fields, $this);
408
        }
409
410
        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...
411
    }
412
413
    /**
414
     * Determine if the Model Admin is sortable in it's list view.
415
     * 
416
     * @return bool
417
     */
418
    public function isSortable()
419
    {
420
        return isset($this->sortable) && $this->sortable ? true : false;
421
    }
422
423
    /**
424
     * Determine if the Model Admin is sortable by a defined key / column.
425
     *
426
     * @param string $key
427
     * 
428
     * @return bool
429
     */
430
    public function isSortableBy($key)
431
    {
432
        // Sorting is not allowed on Model Admin
433
        if (!$this->isSortable()) {
434
            return false;
435
        }
436
437
        // Key results are mutated, so sorting is not available
438
        if ($this->model()->hasGetMutator($key) || $this->hasGetMutator($key)) {
439
            return false;
440
        }
441
442
        // Key is a relation, so sorting is not available 
443
        if (strpos($key, '.') !== false) {
444
            return false;
445
        }
446
447
        return true;
448
    }
449
450
    /**
451
     * Determine if the Model Admin has Viewing Capabilities.
452
     * 
453
     * @return bool
454
     */
455
    public function hasViewing()
456
    {
457
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelViewing::class);
458
    }
459
460
    /**
461
     * Determine if the Model Admin has Creating Capabilities.
462
     * 
463
     * @return bool
464
     */
465
    public function hasCreating()
466
    {
467
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelCreating::class);
468
    }
469
470
    /**
471
     * Determine if the Model Admin has Cloning Capabilities.
472
     * 
473
     * @return bool
474
     */
475
    public function hasCloning()
476
    {
477
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelCloning::class);
478
    }
479
480
    /**
481
     * Determine if the Model Admin has Editting Capabilities.
482
     * 
483
     * @return bool
484
     */
485
    public function hasEditting()
486
    {
487
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelEditting::class);
488
    }
489
490
    /**
491
     * Determine if the Model Admin has Deleting Capabilities.
492
     * 
493
     * @return bool
494
     */
495
    public function hasDeleting()
496
    {
497
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelDeleting::class);
498
    }
499
500
    /**
501
     * Determine if the Managed Model is using the SoftDeletes Trait.
502
     *
503
     * This is guarded by hasDeleting, since we shouldn't allow SoftDeleting
504
     * without the deleting trait (even though it isn't really required).
505
     *
506
     * @return bool
507
     */
508
    public function hasSoftDeleting()
509
    {
510
        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...
511
            return false;
512
        }
513
514
        $managedModelClass = $this->getManagedModel();
515
516
        return in_array(
517
            \Illuminate\Database\Eloquent\SoftDeletes::class, class_uses_recursive(get_class(new $managedModelClass()))
518
        ) && in_array(
519
            \LaravelFlare\Flare\Traits\ModelAdmin\ModelSoftDeleting::class, class_uses_recursive(get_class($this))
520
        );
521
    }
522
523
    /**
524
     * Determine if the Model Admin has Validating Capabilities.
525
     * 
526
     * @return bool
527
     */
528
    public function hasValidating()
529
    {
530
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelValidating::class);
531
    }
532
533
    /**
534
     * Determine if the Managed Model has a Trait and Contract
535
     *
536
     * @return bool
537
     */
538
    public function hasTraitAndContract($trait = null, $contract = null)
539
    {
540
        return ($this->hasTrait($trait) && $this->hasContract($contract));
541
    }
542
543
    /**
544
     * Returns whether the current ModelAdmin has a given trait.
545
     * 
546
     * @param  string  $trait  
547
     * 
548
     * @return boolean        
549
     */
550
    public function hasTrait($trait = null)
551
    {
552
        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...
553
            return;
554
        }
555
556
        return in_array($trait, class_uses_recursive(get_class($this)));
557
    }
558
559
    /**
560
     * Returns whether the current ModelAdmin has a given contract.
561
     * 
562
     * @param  string  $contract  
563
     * 
564
     * @return boolean        
565
     */
566
    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...
567
    {
568
        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...
569
            return;
570
        }
571
        
572
        $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...
573
    }
574
}
575