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 — bs4 ( deef93...4509fe )
by Andrey
14:06 queued 08:41
created

FormDefault   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 435
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 115
c 3
b 0
f 0
dl 0
loc 435
rs 6.96
wmc 53

24 Methods

Rating   Name   Duplication   Size   Complexity  
A getButtons() 0 3 1
A __construct() 0 6 1
A withFiles() 0 5 1
A initialize() 0 31 4
A getClass() 0 3 1
A setButtons() 0 5 1
A addItem() 0 3 1
A getAction() 0 3 1
A setItems() 0 7 2
A setAction() 0 7 2
A getRepository() 0 3 1
A getItems() 0 3 1
A setModelClass() 0 7 2
A saveHasOneRelations() 0 8 6
A setModel() 0 2 1
A validModelConfiguration() 0 3 2
A saveBelongsToRelations() 0 6 4
A validateForm() 0 23 3
A getModel() 0 3 1
A getModelConfiguration() 0 9 3
A toArray() 0 12 1
A setId() 0 25 6
A makeModel() 0 5 1
A saveForm() 0 30 6

How to fix   Complexity   

Complex Class

Complex classes like FormDefault 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.

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 FormDefault, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace SleepingOwl\Admin\Form;
4
5
use Illuminate\Database\Eloquent\Model;
6
use KodiComponents\Support\HtmlAttributes;
7
use SleepingOwl\Admin\Form\Element\Upload;
8
use Illuminate\Validation\ValidationException;
9
use SleepingOwl\Admin\Contracts\Form\FormInterface;
10
use SleepingOwl\Admin\Exceptions\Form\FormException;
11
use Illuminate\Database\Eloquent\Relations\BelongsTo;
12
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
13
use SleepingOwl\Admin\Contracts\Display\DisplayInterface;
14
use SleepingOwl\Admin\Contracts\Form\FormButtonsInterface;
15
use SleepingOwl\Admin\Contracts\ModelConfigurationInterface;
16
use SleepingOwl\Admin\Contracts\Repositories\RepositoryInterface;
17
18
class FormDefault extends FormElements implements DisplayInterface, FormInterface
19
{
20
    use HtmlAttributes;
21
22
    /**
23
     * View to render.
24
     * @var string|\Illuminate\View\View
25
     */
26
    protected $view = 'form.default';
27
28
    /**
29
     * Form related class.
30
     * @var string
31
     */
32
    protected $class;
33
34
    /**
35
     * @var FormButtons
36
     */
37
    protected $buttons;
38
39
    /**
40
     * Form related repository.
41
     * @var RepositoryInterface
42
     */
43
    protected $repository;
44
45
    /**
46
     * Form action url.
47
     * @var string
48
     */
49
    protected $action;
50
51
    /**
52
     * Form related model instance.
53
     * @var Model
54
     */
55
    protected $model;
56
57
    /**
58
     * Currently loaded model id.
59
     * @var int
60
     */
61
    protected $id;
62
63
    /**
64
     * Is form already initialized?
65
     * @var bool
66
     */
67
    protected $initialized = false;
68
69
    /**
70
     * FormDefault constructor.
71
     *
72
     * @param array $elements
73
     */
74
    public function __construct(array $elements = [])
75
    {
76
        parent::__construct($elements);
77
78
        $this->setButtons(
79
            app(FormButtonsInterface::class)
80
        );
81
    }
82
83
    /**
84
     * Initialize form.
85
     * @throws \SleepingOwl\Admin\Exceptions\RepositoryException
86
     */
87
    public function initialize()
88
    {
89
        if ($this->initialized) {
90
            return;
91
        }
92
93
        $this->initialized = true;
94
        $this->repository = app(RepositoryInterface::class);
95
        $this->repository->setClass($this->class);
96
97
        $model = $this->makeModel();
98
        parent::setModel($model);
99
        $this->getButtons()->setModel($model);
100
101
        parent::initialize();
102
103
        if (! $this->hasHtmlAttribute('enctype')) {
104
105
            // Recursive iterate subset of form elements
106
            // and if subset contains an upload element then add to for
107
            $this->recursiveIterateElements(function ($element) {
108
                if ($element instanceof Upload) {
109
                    $this->withFiles();
110
111
                    return true;
112
                }
113
            });
114
        }
115
116
        $this->getButtons()->setModelConfiguration(
117
            $this->getModelConfiguration()
118
        );
119
    }
120
121
    /**
122
     * Set enctype multipart/form-data.
123
     *
124
     * @return $this
125
     */
126
    public function withFiles()
127
    {
128
        $this->setHtmlAttribute('enctype', 'multipart/form-data');
129
130
        return $this;
131
    }
132
133
    /**
134
     * @return FormButtons
135
     */
136
    public function getButtons()
137
    {
138
        return $this->buttons;
139
    }
140
141
    /**
142
     * @return $this
143
     */
144
    public function setButtons($buttons)
145
    {
146
        $this->buttons = $buttons;
147
148
        return $this;
149
    }
150
151
    /**
152
     * @return RepositoryInterface
153
     */
154
    public function getRepository()
155
    {
156
        return $this->repository;
157
    }
158
159
    /**
160
     * @return string
161
     */
162
    public function getAction()
163
    {
164
        return $this->action;
165
    }
166
167
    /**
168
     * @param string $action
169
     *
170
     * @return $this
171
     */
172
    public function setAction($action)
173
    {
174
        if (is_null($this->action)) {
0 ignored issues
show
introduced by
The condition is_null($this->action) is always false.
Loading history...
175
            $this->action = $action;
176
        }
177
178
        return $this;
179
    }
180
181
    /**
182
     * @return string
183
     */
184
    public function getClass()
185
    {
186
        return $this->class;
187
    }
188
189
    /**
190
     * @param string $class
191
     *
192
     * @return $this
193
     * @throws FormException
194
     */
195
    public function setModelClass($class)
196
    {
197
        if (is_null($this->class)) {
0 ignored issues
show
introduced by
The condition is_null($this->class) is always false.
Loading history...
198
            $this->class = $class;
199
        }
200
201
        return $this;
202
    }
203
204
    /**
205
     * @return \SleepingOwl\Admin\Form\FormElementsCollection
206
     * @see getElements()
207
     *
208
     * @deprecated 4.5.0
209
     */
210
    public function getItems()
211
    {
212
        return $this->getElements();
213
    }
214
215
    /**
216
     * @param array|\SleepingOwl\Admin\Contracts\Form\FormElementInterface $items
217
     *
218
     * @return $this
219
     * @deprecated 4.5.0
220
     * @see setElements()
221
     */
222
    public function setItems($items)
223
    {
224
        if (! is_array($items)) {
225
            $items = func_get_args();
226
        }
227
228
        return $this->setElements($items);
229
    }
230
231
    /**
232
     * @param \SleepingOwl\Admin\Contracts\Form\FormElementInterface $item
233
     *
234
     * @return $this
235
     * @deprecated 4.5.0
236
     * @see addElement()
237
     */
238
    public function addItem($item)
239
    {
240
        return $this->addElement($item);
241
    }
242
243
    /**
244
     * Set currently loaded model id.
245
     *
246
     * @param int $id
247
     * @throws \SleepingOwl\Admin\Exceptions\Form\FormException
248
     */
249
    public function setId($id)
250
    {
251
        if (is_null($this->id)) {
0 ignored issues
show
introduced by
The condition is_null($this->id) is always false.
Loading history...
252
            /**
253
             * Get Model from ModelConfiguration.
254
             */
255
            $model = null;
256
            $model_configuration = $this->getModelConfiguration();
257
258
            if (method_exists($model_configuration, 'getModelValue')) {
259
                $model = $model_configuration->getModelValue();
260
            }
261
262
            /*
263
              * Get Model from Repository
264
              */
265
            if (! $model && ! is_null($id)) {
266
                $model = $this->getRepository()->find($id);
267
            }
268
269
            if ($model) {
270
                $this->id = $id;
271
                parent::setModel($model);
272
                $this->getButtons()->setModel($model);
273
                $this->setModelClass(get_class($model));
274
            }
275
        }
276
    }
277
278
    /**
279
     * Get related form model configuration.
280
     * @return ModelConfigurationInterface
281
     */
282
    public function getModelConfiguration()
283
    {
284
        $class = $this->class;
285
286
        if (is_null($class) && $this->getModel() instanceof Model) {
0 ignored issues
show
introduced by
The condition is_null($class) is always false.
Loading history...
287
            $class = $this->getModel();
288
        }
289
290
        return app('sleeping_owl')->getModel($class);
0 ignored issues
show
Bug introduced by
The method getModel() does not exist on Illuminate\Contracts\Foundation\Application. ( Ignorable by Annotation )

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

290
        return app('sleeping_owl')->/** @scrutinizer ignore-call */ getModel($class);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
291
    }
292
293
    /**
294
     * @return Model
295
     */
296
    public function getModel()
297
    {
298
        return $this->model;
299
    }
300
301
    /**
302
     * @param Model $model
303
     *
304
     * @return $this
305
     */
306
    public function setModel(Model $model)
307
    {
308
    }
309
310
    /**
311
     * @param ModelConfigurationInterface $modelConfiguration
312
     *
313
     * @return bool
314
     */
315
    public function validModelConfiguration(ModelConfigurationInterface $modelConfiguration = null)
316
    {
317
        return is_null($modelConfiguration) || $modelConfiguration === $this->getModelConfiguration();
318
    }
319
320
    /**
321
     * Save instance.
322
     *
323
     * @param \Illuminate\Http\Request $request
324
     * @param ModelConfigurationInterface $modelConfiguration
325
     *
326
     * @return bool
327
     */
328
    public function saveForm(\Illuminate\Http\Request $request, ModelConfigurationInterface $modelConfiguration = null)
329
    {
330
        if (! $this->validModelConfiguration($modelConfiguration)) {
331
            return;
332
        }
333
334
        $model = $this->getModel();
335
        $loaded = $model->exists;
336
337
        if ($this->getModelConfiguration()->fireEvent($loaded ? 'updating' : 'creating', true, $model) === false) {
0 ignored issues
show
Bug introduced by
The method fireEvent() does not exist on SleepingOwl\Admin\Contra...lConfigurationInterface. Did you maybe mean fireEdit()? ( Ignorable by Annotation )

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

337
        if ($this->getModelConfiguration()->/** @scrutinizer ignore-call */ fireEvent($loaded ? 'updating' : 'creating', true, $model) === false) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
338
            return;
339
        }
340
341
        if ($this->getModelConfiguration()->fireEvent('saving', true, $model) === false) {
342
            return;
343
        }
344
345
        parent::save($request);
346
        $this->saveBelongsToRelations($model);
347
348
        $model->save();
349
350
        $this->saveHasOneRelations($model);
351
352
        parent::afterSave($request);
353
354
        $this->getModelConfiguration()->fireEvent($loaded ? 'updated' : 'created', false, $model);
355
        $this->getModelConfiguration()->fireEvent('saved', false, $model);
356
357
        return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the return type mandated by SleepingOwl\Admin\Contra...rmInterface::saveForm() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
358
    }
359
360
    /**
361
     * @param Model $model
362
     *
363
     * @return void
364
     */
365
    protected function saveBelongsToRelations(Model $model)
366
    {
367
        foreach ($model->getRelations() as $name => $relation) {
368
            if ($model->{$name}() instanceof BelongsTo && ! is_null($relation)) {
369
                $relation->save();
370
                $model->{$name}()->associate($relation);
371
            }
372
        }
373
    }
374
375
    /**
376
     * @param Model $model
377
     *
378
     * @return void
379
     */
380
    protected function saveHasOneRelations(Model $model)
381
    {
382
        foreach ($model->getRelations() as $name => $relation) {
383
            if ($model->{$name}() instanceof HasOneOrMany && ! is_null($relation)) {
384
                if (is_array($relation) || $relation instanceof \Traversable) {
385
                    $model->{$name}()->saveMany($relation);
386
                } else {
387
                    $model->{$name}()->save($relation);
388
                }
389
            }
390
        }
391
    }
392
393
    /**
394
     * @param \Illuminate\Http\Request $request
395
     * @param ModelConfigurationInterface $modelConfiguration
396
     *
397
     * @throws ValidationException
398
     */
399
    public function validateForm(\Illuminate\Http\Request $request, ModelConfigurationInterface $modelConfiguration = null)
400
    {
401
        if (! $this->validModelConfiguration($modelConfiguration)) {
402
            return;
403
        }
404
405
        $verifier = app('validation.presence');
406
407
        $verifier->setConnection($this->getModel()->getConnectionName());
408
409
        $validator = \Validator::make(
410
            $request->all(),
411
            $this->getValidationRules(),
412
            $this->getValidationMessages(),
413
            $this->getValidationLabels()
414
        );
415
416
        $validator->setPresenceVerifier($verifier);
417
418
        $this->getModelConfiguration()->fireEvent('validate', false, $this->getModel(), $validator);
419
420
        if ($validator->fails()) {
421
            throw new ValidationException($validator);
422
        }
423
    }
424
425
    /**
426
     * Get the instance as an array.
427
     *
428
     * @return array
429
     */
430
    public function toArray()
431
    {
432
        // This element needs only in template
433
        $this->setHtmlAttribute('method', 'POST');
434
        $this->setHtmlAttribute('action', $this->getAction());
435
436
        return [
437
            'items' => $this->getElements()->onlyVisible(),
438
            'instance' => $this->getModel(),
439
            'attributes' => $this->htmlAttributesToString(),
440
            'buttons' => $this->getButtons(),
441
            'backUrl' => session('_redirectBack', \URL::previous()),
442
        ];
443
    }
444
445
    /**
446
     * @return Model
447
     */
448
    protected function makeModel()
449
    {
450
        $class = $this->getClass();
451
452
        return new $class();
453
    }
454
}
455