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 ( ce7a57...96525c )
by Aden
03:03
created

ModelAdmin   C

Complexity

Total Complexity 58

Size/Duplication

Total Lines 509
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 16
Bugs 3 Features 3
Metric Value
wmc 58
c 16
b 3
f 3
lcom 1
cbo 5
dl 0
loc 509
rs 6.3005

28 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A model() 0 10 2
A newModel() 0 6 1
A getManagedModel() 0 8 3
A setManagedModel() 0 4 1
A routeParameters() 0 6 1
D getColumns() 0 41 9
A getAttribute() 0 18 4
A hasGetAccessor() 0 4 1
A hasRelatedKey() 0 15 4
B relatedKey() 0 23 6
A setAttribute() 0 10 2
A hasSetMutator() 0 4 1
A hasGetMutator() 0 4 1
A outputFields() 0 4 1
A getFields() 0 4 1
A setFields() 0 4 1
A isSortable() 0 4 3
A hasViewing() 0 4 1
A hasCreating() 0 4 1
A hasCloning() 0 4 1
A hasEditting() 0 4 1
A hasDeleting() 0 4 1
A hasSoftDeleting() 0 14 3
A hasValidating() 0 4 1
A hasTraitAndContract() 0 4 2
A hasTrait() 0 8 2
A hasContract() 0 8 2

How to fix   Complexity   

Complex Class

Complex classes like ModelAdmin often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ModelAdmin, and based on these observations, apply Extract Interface, too.

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
12
class ModelAdmin extends Admin implements ModelQueryable
13
{
14
    use ModelQuerying;
15
    use ModelSaving;
16
17
    /**
18
     * Class of Model to Manage.
19
     * 
20
     * @var string
21
     */
22
    protected $managedModel;
23
24
    /**
25
     * ModelAdmin Icon.
26
     *
27
     * Font Awesome Defined Icon, eg 'user' = 'fa-user'
28
     *
29
     * @var string
30
     */
31
    protected $icon = '';
32
33
    /**
34
     * Validation Rules for onCreate, onEdit actions.
35
     * 
36
     * @var array
37
     */
38
    protected $rules = [];
39
40
    /**
41
     * Columns for Model.
42
     *
43
     * Defines which fields to show in the listing tables output.
44
     * 
45
     * @var array
46
     */
47
    protected $columns = [];
48
49
    /**
50
     * Map Model Attributes to AttributeTypes with
51
     * additional parameters which will be output
52
     * as fields when viewing, editting or adding
53
     * a new model entry.
54
     * 
55
     * @var array
56
     */
57
    protected $fields = [];
58
59
    /**
60
     * Columns for Model are Sortable.
61
     *
62
     * @var bool
63
     */
64
    protected $sortable = true;
65
66
    /**
67
     * The Controller to be used by the Model Admin.
68
     *
69
     * This defaults to parent::getController()
70
     * if it has been left undefined. 
71
     * 
72
     * @var string
73
     */
74
    protected $controller = '\LaravelFlare\Flare\Admin\Models\ModelAdminController';
75
76
    /**
77
     * The Policy used for the Model Authorization logic.
78
     *
79
     * This class should implement the ModelAdminPoliceable which
80
     * includes authorization checks for the create, view, edit and delete actions.
81
     * 
82
     * @var string
83
     */
84
    protected $policy = '\LaravelFlare\Flare\Permissions\ModelAdminPolicy';
85
86
    /**
87
     * The current model to be managed.
88
     * 
89
     * @var Model
90
     */
91
    public $model;
92
93
    /**
94
     * __construct.
95
     */
96
    public function __construct()
97
    {
98
        $this->getManagedModel();
99
100
        $this->model = $this->model();
101
    }
102
103
    /**
104
     * Returns a Model Instance.
105
     * 
106
     * @return Model
107
     */
108
    public function model()
109
    {
110
        if (!$this->model) {
111
            $class = $this->getManagedModel();
112
113
            return $this->model = new $class();
114
        }
115
116
        return $this->model;
117
    }
118
119
    /**
120
     * Returns a New Model Instance.
121
     *
122
     * @return Model
123
     */
124
    public function newModel()
125
    {
126
        $class = self::getManagedModel();
127
128
        return new $class();
129
    }
130
131
    /**
132
     * Returns the Managed Model Class.
133
     * 
134
     * @return string
135
     */
136
    public function getManagedModel()
137
    {
138
        if (!isset($this->managedModel) || $this->managedModel === null) {
139
            throw new ModelAdminException('You have a ModelAdmin which does not have a model assigned to it. ModelAdmins must include a model to manage.', 1);
140
        }
141
142
        return $this->managedModel;
143
    }
144
145
    /**
146
     * Set the Managed Model Class.
147
     * 
148
     * @param string $managedModel
149
     */
150
    public function setManagedModel($managedModel = null)
151
    {
152
        $this->managedModel = $managedModel;
153
    }
154
155
    /**
156
     * Returns the Route Paramets.
157
     * 
158
     * @return array
159
     */
160
    public function routeParameters()
161
    {
162
        return array_merge(parent::routeParameters(), [
163
                                                    'model' => $this->managedModel,
164
                                                ]);
165
    }
166
167
    /**
168
     * Formats and returns the Columns.
169
     *
170
     * This is really gross, I'm removing it soon.
171
     * 
172
     * @return
173
     */
174
    public function getColumns()
175
    {
176
        $columns = [];
177
178
        foreach ($this->columns as $field => $fieldTitle) {
179
            if (in_array($field, $this->model->getFillable())) {
180
                if (!$field) {
181
                    $field = $fieldTitle;
182
                    $fieldTitle = Str::title($fieldTitle);
183
                }
184
                $columns[$field] = $fieldTitle;
185
                continue;
186
            }
187
188
            // We can replace this with data_get() I believe.
189
            if (($methodBreaker = strpos($field, '.')) !== false) {
190
                $method = substr($field, 0, $methodBreaker);
191
                if (method_exists($this->model, $method)) {
192
                    if (method_exists($this->model->$method(), $submethod = str_replace($method.'.', '', $field))) {
193
                        $this->model->$method()->$submethod();
194
195
                        $columns[$field] = $fieldTitle;
196
                        continue;
197
                    }
198
                }
199
            }
200
201
            if (is_numeric($field)) {
202
                $field = $fieldTitle;
203
                $fieldTitle = Str::title($fieldTitle);
204
            }
205
206
            $columns[$field] = $fieldTitle;
207
        }
208
209
        if (count($columns)) {
210
            return $columns;
211
        }
212
213
        return [$this->model->getKeyName() => $this->model->getKeyName()];
214
    }
215
216
    /**
217
     * Gets an Attribute by the provided key
218
     * on either the current model or a provided model instance.
219
     * 
220
     * @param string $key
221
     * @param mixed  $model
222
     * 
223
     * @return mixed
224
     */
225
    public function getAttribute($key, $model = false)
226
    {
227
        if (!$model) {
228
            $model = $this->model;
229
        }
230
231
        if ($this->hasGetAccessor($key)) {
232
            $method = 'get'.Str::studly($key).'Attribute';
233
234
            return $this->{$method}($model);
235
        }
236
237
        if ($this->hasRelatedKey($key, $model)) {
238
            return $this->relatedKey($key, $model);
239
        }
240
241
        return $model->getAttribute($key);
242
    }
243
244
    /**
245
     * Determine if a get accessor exists for an attribute.
246
     *
247
     * @param string $key
248
     * 
249
     * @return bool
250
     */
251
    public function hasGetAccessor($key)
252
    {
253
        return method_exists($this, 'get'.Str::studly($key).'Attribute');
254
    }
255
256
    /**
257
     * Determines if a key resolved a related Model.
258
     * 
259
     * @param string $key
260
     * @param mixed  $model
261
     * 
262
     * @return bool
263
     */
264
    public function hasRelatedKey($key, $model = false)
265
    {
266
        if (!$model) {
267
            $model = $this->model;
268
        }
269
270
        if (($methodBreaker = strpos($key, '.')) !== false) {
271
            $method = substr($key, 0, $methodBreaker);
272
            if (method_exists($model, $method)) {
273
                return true;
274
            }
275
        }
276
277
        return false;
278
    }
279
280
    /**
281
     * Resolves a relation based on the key provided,
282
     * either on the current model or a provided model instance.
283
     * 
284
     * @param string $key
285
     * @param mixed  $model
286
     * 
287
     * @return mixed
288
     */
289
    public function relatedKey($key, $model = false)
290
    {
291
        if (!$model) {
292
            $model = $this->model;
293
        }
294
295
        if (($methodBreaker = strpos($key, '.')) !== false) {
296
            $method = substr($key, 0, $methodBreaker);
297
            if (method_exists($model, $method)) {
298
                if (method_exists($model->$method, $submethod = str_replace($method.'.', '', $key))) {
299
                    return $model->$method->$submethod();
300
                }
301
302
                if (isset($model->$method->$submethod)) {
303
                    return $model->$method->$submethod;
304
                }
305
306
                return $model->getRelationValue($method);
307
            }
308
        }
309
310
        return false;
311
    }
312
313
    /**
314
     * Set a given attribute on the model.
315
     *
316
     * @param string $key
317
     * @param mixed  $value
318
     */
319
    public function setAttribute($key, $value)
320
    {
321
        if ($this->hasSetMutator($key)) {
322
            $method = 'set'.Str::studly($key).'Attribute';
323
324
            return $this->{$method}($value);
325
        }
326
327
        $this->model->attributes[$key] = $value;
328
    }
329
330
    /**
331
     * Determine if a set mutator exists for an attribute.
332
     *
333
     * @param string $key
334
     * 
335
     * @return bool
336
     */
337
    public function hasSetMutator($key)
338
    {
339
        return method_exists($this, 'set'.Str::studly($key).'Attribute');
340
    }
341
342
    /**
343
     * Determine if a get mutator exists for an attribute.
344
     *
345
     * @param string $key
346
     * 
347
     * @return bool
348
     */
349
    public function hasGetMutator($key)
350
    {
351
        return method_exists($this, 'get'.Str::studly($key).'Attribute');
352
    }
353
354
    /**
355
     * Returns an array of Attribute Fields ready for output.
356
     *
357
     * @param  string $type 
358
     * 
359
     * @return array
360
     */
361
    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...
362
    {
363
        return $this->getFields();
364
    }
365
366
    /**
367
     * Gets the Managed Model Mapping.
368
     * 
369
     * @return array
370
     */
371
    public function getFields()
372
    {
373
        return $this->fields;
374
    }
375
376
    /**
377
     * Gets the Managed Model Mapping.
378
     * 
379
     * @param array $fields
380
     */
381
    public function setFields($fields = [])
382
    {
383
        $this->fields = $fields;
384
    }
385
386
    /**
387
     * Determine if the Model Admin is sortable in it's list view.
388
     * 
389
     * @return bool
390
     */
391
    public function isSortable()
392
    {
393
        return isset($this->sortable) && $this->sortable ? true : false;
394
    }
395
396
    /**
397
     * Determine if the Model Admin has Viewing Capabilities.
398
     * 
399
     * @return bool
400
     */
401
    public function hasViewing()
402
    {
403
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelViewing::class);
404
    }
405
406
    /**
407
     * Determine if the Model Admin has Creating Capabilities.
408
     * 
409
     * @return bool
410
     */
411
    public function hasCreating()
412
    {
413
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelCreating::class);
414
    }
415
416
    /**
417
     * Determine if the Model Admin has Cloning Capabilities.
418
     * 
419
     * @return bool
420
     */
421
    public function hasCloning()
422
    {
423
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelCloning::class);
424
    }
425
426
    /**
427
     * Determine if the Model Admin has Editting Capabilities.
428
     * 
429
     * @return bool
430
     */
431
    public function hasEditting()
432
    {
433
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelEditting::class);
434
    }
435
436
    /**
437
     * Determine if the Model Admin has Deleting Capabilities.
438
     * 
439
     * @return bool
440
     */
441
    public function hasDeleting()
442
    {
443
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelDeleting::class);
444
    }
445
446
    /**
447
     * Determine if the Managed Model is using the SoftDeletes Trait.
448
     *
449
     * This is guarded by hasDeleting, since we shouldn't allow SoftDeleting
450
     * without the deleting trait (even though it isn't really required).
451
     *
452
     * @return bool
453
     */
454
    public function hasSoftDeleting()
455
    {
456
        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...
457
            return false;
458
        }
459
460
        $managedModelClass = $this->getManagedModel();
461
462
        return in_array(
463
            \Illuminate\Database\Eloquent\SoftDeletes::class, class_uses_recursive(get_class(new $managedModelClass()))
464
        ) && in_array(
465
            \LaravelFlare\Flare\Traits\ModelAdmin\ModelSoftDeleting::class, class_uses_recursive(get_class($this))
466
        );
467
    }
468
469
    /**
470
     * Determine if the Model Admin has Validating Capabilities.
471
     * 
472
     * @return bool
473
     */
474
    public function hasValidating()
475
    {
476
        return $this->hasTrait(\LaravelFlare\Flare\Traits\ModelAdmin\ModelValidating::class);
477
    }
478
479
    /**
480
     * Determine if the Managed Model has a Trait and Contract
481
     *
482
     * @return bool
483
     */
484
    public function hasTraitAndContract($trait = null, $contract = null)
485
    {
486
        return ($this->hasTrait($trait) && $this->hasContract($contract));
487
    }
488
489
    /**
490
     * Returns whether the current ModelAdmin has a given trait.
491
     * 
492
     * @param  string  $trait  
493
     * 
494
     * @return boolean        
495
     */
496
    public function hasTrait($trait = null)
497
    {
498
        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...
499
            return;
500
        }
501
502
        return in_array($trait, class_uses_recursive(get_class($this)));
503
    }
504
505
    /**
506
     * Returns whether the current ModelAdmin has a given contract.
507
     * 
508
     * @param  string  $contract  
509
     * 
510
     * @return boolean        
511
     */
512
    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...
513
    {
514
        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...
515
            return;
516
        }
517
        
518
        $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...
519
    }
520
}
521