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 ( a9bc98...b864c9 )
by butschster
10:50
created

FormDefault::setModel()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace SleepingOwl\Admin\Form;
4
5
use Request;
6
use Validator;
7
use Illuminate\Support\Collection;
8
use Illuminate\Database\Eloquent\Model;
9
use KodiComponents\Support\HtmlAttributes;
10
use SleepingOwl\Admin\Form\Element\Upload;
11
use SleepingOwl\Admin\Contracts\FormInterface;
12
use SleepingOwl\Admin\Contracts\DisplayInterface;
13
use SleepingOwl\Admin\Contracts\RepositoryInterface;
14
use Illuminate\Database\Eloquent\Relations\BelongsTo;
15
use SleepingOwl\Admin\Contracts\FormButtonsInterface;
16
use SleepingOwl\Admin\Contracts\FormElementInterface;
17
use Illuminate\Database\Eloquent\Relations\HasOneOrMany;
18
use SleepingOwl\Admin\Contracts\ModelConfigurationInterface;
19
20
class FormDefault extends FormElements implements DisplayInterface, FormInterface
21
{
22
    use HtmlAttributes;
23
24
    /**
25
     * View to render.
26
     * @var string|\Illuminate\View\View
27
     */
28
    protected $view = 'form.default';
29
30
    /**
31
     * Form related class.
32
     * @var string
33
     */
34
    protected $class;
35
36
    /**
37
     * @var FormButtons
38
     */
39
    protected $buttons;
40
41
    /**
42
     * Form related repository.
43
     * @var RepositoryInterface
44
     */
45
    protected $repository;
46
47
    /**
48
     * Form action url.
49
     * @var string
50
     */
51
    protected $action;
52
53
    /**
54
     * Form related model instance.
55
     * @var Model
56
     */
57
    protected $model;
58
59
    /**
60
     * Currently loaded model id.
61
     * @var int
62
     */
63
    protected $id;
64
65
    /**
66
     * Is form already initialized?
67
     * @var bool
68
     */
69
    protected $initialized = false;
70
71
    /**
72
     * FormDefault constructor.
73
     *
74
     * @param array $elements
75
     */
76
    public function __construct(array $elements = [])
77
    {
78
        parent::__construct($elements);
79
80
        $this->setButtons(
81
            app(FormButtonsInterface::class)
82
        );
83
84
        $this->initializePackage();
85
    }
86
87
    /**
88
     * Initialize form.
89
     */
90
    public function initialize()
91
    {
92
        if ($this->initialized) {
93
            return;
94
        }
95
96
        $this->initialized = true;
97
        $this->repository = app(RepositoryInterface::class, [$this->class]);
98
99
        $this->setModel(app($this->class));
100
101
        parent::initialize();
102
103
        $this->getElements()->each(function ($element) {
104
            if ($element instanceof Upload and ! $this->hasHtmlAttribute('enctype')) {
0 ignored issues
show
Documentation introduced by
'enctype' is of type string, but the function expects a object<KodiComponents\Support\srtring>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
105
                $this->setHtmlAttribute('enctype', 'multipart/form-data');
106
            }
107
        });
108
109
        $this->setHtmlAttribute('method', 'POST');
110
111
        $this->getButtons()->setModelConfiguration(
112
            $this->getModelConfiguration()
113
        );
114
115
        $this->includePackage();
116
    }
117
118
    /**
119
     * @return FormButtons
120
     */
121
    public function getButtons()
122
    {
123
        return $this->buttons;
124
    }
125
126
    /**
127
     * @param FormButtonsInterface $buttons
128
     *
129
     * @return $this
130
     */
131
    public function setButtons(FormButtonsInterface $buttons)
132
    {
133
        $this->buttons = $buttons;
0 ignored issues
show
Documentation Bug introduced by
$buttons is of type object<SleepingOwl\Admin...s\FormButtonsInterface>, but the property $buttons was declared to be of type object<SleepingOwl\Admin\Form\FormButtons>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
134
135
        return $this;
136
    }
137
138
    /**
139
     * @return RepositoryInterface
140
     */
141
    public function getRepository()
142
    {
143
        return $this->repository;
144
    }
145
146
    /**
147
     * @return string|\Illuminate\View\View
148
     */
149
    public function getView()
150
    {
151
        return $this->view;
152
    }
153
154
    /**
155
     * @param \Illuminate\View\View|string $view
156
     *
157
     * @return $this
158
     */
159
    public function setView($view)
160
    {
161
        $this->view = $view;
162
163
        return $this;
164
    }
165
166
    /**
167
     * @return string
168
     */
169
    public function getAction()
170
    {
171
        return $this->action;
172
    }
173
174
    /**
175
     * @param string $action
176
     *
177
     * @return $this
178
     */
179
    public function setAction($action)
180
    {
181
        if (is_null($this->action)) {
182
            $this->action = $action;
183
        }
184
185
        $this->setHtmlAttribute('action', $this->action);
186
187
        return $this;
188
    }
189
190
    /**
191
     * @return string
192
     */
193
    public function getClass()
194
    {
195
        return $this->class;
196
    }
197
198
    /**
199
     * @param string $class
200
     *
201
     * @return $this
202
     */
203
    public function setModelClass($class)
204
    {
205
        if (is_null($this->class)) {
206
            $this->class = $class;
207
        }
208
209
        return $this;
210
    }
211
212
    /**
213
     * @deprecated 4.5.0
214
     * @see getElements()
215
     *
216
     * @return Collection[]
217
     */
218
    public function getItems()
219
    {
220
        return $this->getElements();
221
    }
222
223
    /**
224
     * @deprecated 4.5.0
225
     * @see setElements()
226
     *
227
     * @param array|FormElementInterface $items
228
     *
229
     * @return $this
230
     */
231
    public function setItems($items)
232
    {
233
        if (! is_array($items)) {
234
            $items = func_get_args();
235
        }
236
237
        return $this->setElements($items);
238
    }
239
240
    /**
241
     * @deprecated 4.5.0
242
     * @see addElement()
243
     *
244
     * @param FormElementInterface $item
245
     *
246
     * @return $this
247
     */
248
    public function addItem($item)
249
    {
250
        return $this->addElement($item);
251
    }
252
253
    /**
254
     * Set currently loaded model id.
255
     *
256
     * @param int $id
257
     */
258
    public function setId($id)
259
    {
260
        if (is_null($this->id) and ! is_null($id) and ($model = $this->getRepository()->find($id))) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
261
            $this->id = $id;
262
            $this->setModel($model);
263
        }
264
    }
265
266
    /**
267
     * Get related form model configuration.
268
     * @return ModelConfigurationInterface
269
     */
270
    public function getModelConfiguration()
271
    {
272
        return app('sleeping_owl')->getModel($this->class);
273
    }
274
275
    /**
276
     * @return Model
277
     */
278
    public function getModel()
279
    {
280
        return $this->model;
281
    }
282
283
    /**
284
     * @param Model $model
285
     *
286
     * @return $this
287
     */
288
    public function setModel(Model $model)
289
    {
290
        $this->model = $model;
291
292
        parent::setModel($model);
293
294
        $this->getButtons()->setModel($this->getModel());
295
296
        return $this;
297
    }
298
299
    /**
300
     * Save instance.
301
     *
302
     * @param ModelConfigurationInterface $modelConfiguration
303
     *
304
     * @return bool
305
     */
306
    public function saveForm(ModelConfigurationInterface $modelConfiguration)
307
    {
308
        if ($modelConfiguration !== $this->getModelConfiguration()) {
309
            return;
310
        }
311
312
        parent::save();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (save() instead of saveForm()). Are you sure this is correct? If so, you might want to change this to $this->save().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
313
314
        $this->saveBelongsToRelations();
315
316
        $loaded = $this->getModel()->exists;
317
318
        if ($modelConfiguration->fireEvent($loaded ? 'updating' : 'creating', true, $this->getModel()) === false) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface SleepingOwl\Admin\Contra...lConfigurationInterface as the method fireEvent() does only exist in the following implementations of said interface: SleepingOwl\Admin\Model\ModelConfiguration, SleepingOwl\Admin\Model\ModelConfigurationManager, SleepingOwl\Admin\Model\SectionModelConfiguration, SleepingOwl\Admin\Section.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
319
            return false;
320
        }
321
322
        if ($modelConfiguration->fireEvent('saving', true, $this->getModel()) === false) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface SleepingOwl\Admin\Contra...lConfigurationInterface as the method fireEvent() does only exist in the following implementations of said interface: SleepingOwl\Admin\Model\ModelConfiguration, SleepingOwl\Admin\Model\ModelConfigurationManager, SleepingOwl\Admin\Model\SectionModelConfiguration, SleepingOwl\Admin\Section.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
323
            return false;
324
        }
325
326
        $this->getModel()->save();
327
328
        $this->saveHasOneRelations();
329
330
        parent::afterSave();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (afterSave() instead of saveForm()). Are you sure this is correct? If so, you might want to change this to $this->afterSave().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
331
332
        $modelConfiguration->fireEvent($loaded ? 'updated' : 'created', false, $this->getModel());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface SleepingOwl\Admin\Contra...lConfigurationInterface as the method fireEvent() does only exist in the following implementations of said interface: SleepingOwl\Admin\Model\ModelConfiguration, SleepingOwl\Admin\Model\ModelConfigurationManager, SleepingOwl\Admin\Model\SectionModelConfiguration, SleepingOwl\Admin\Section.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
333
        $modelConfiguration->fireEvent('saved', false, $this->getModel());
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface SleepingOwl\Admin\Contra...lConfigurationInterface as the method fireEvent() does only exist in the following implementations of said interface: SleepingOwl\Admin\Model\ModelConfiguration, SleepingOwl\Admin\Model\ModelConfigurationManager, SleepingOwl\Admin\Model\SectionModelConfiguration, SleepingOwl\Admin\Section.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
334
335
        return true;
336
    }
337
338
    protected function saveBelongsToRelations()
339
    {
340
        $model = $this->getModel();
341
342
        foreach ($model->getRelations() as $name => $relation) {
343
            if ($model->{$name}() instanceof BelongsTo && ! is_null($relation)) {
344
                $relation->save();
345
                $model->{$name}()->associate($relation);
346
            }
347
        }
348
    }
349
350
    protected function saveHasOneRelations()
351
    {
352
        $model = $this->getModel();
353
354
        foreach ($model->getRelations() as $name => $relation) {
355
            if ($model->{$name}() instanceof HasOneOrMany && ! is_null($relation)) {
356
                if (is_array($relation) || $relation instanceof \Traversable) {
357
                    $model->{$name}()->saveMany($relation);
358
                } else {
359
                    $model->{$name}()->save($relation);
360
                }
361
            }
362
        }
363
    }
364
365
    /**
366
     * @param ModelConfigurationInterface $modelConfiguration
367
     *
368
     * @return \Illuminate\Contracts\Validation\Validator|null|bool
369
     */
370
    public function validateForm(ModelConfigurationInterface $modelConfiguration)
371
    {
372
        if ($modelConfiguration !== $this->getModelConfiguration()) {
373
            return;
374
        }
375
376
        $data = Request::all();
377
378
        $verifier = app('validation.presence');
379
        $verifier->setConnection($this->getModel()->getConnectionName());
380
381
        $validator = Validator::make(
382
            $data,
383
            $this->getValidationRules(),
384
            $this->getValidationMessages(),
385
            $this->getValidationLabels()
386
        );
387
388
        $validator->setPresenceVerifier($verifier);
389
390
        return $validator->fails() ? $validator : true;
391
    }
392
393
    /**
394
     * Get the instance as an array.
395
     *
396
     * @return array
397
     */
398
    public function toArray()
399
    {
400
        return [
401
            'items' => $this->getElements()->onlyVisible(),
402
            'instance' => $this->getModel(),
403
            'attributes' => $this->htmlAttributesToString(),
404
            'buttons' => $this->getButtons(),
405
            'backUrl' => session('_redirectBack', \URL::previous()),
406
        ];
407
    }
408
409
    /**
410
     * @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory
411
     */
412
    public function render()
413
    {
414
        return app('sleeping_owl.template')->view($this->getView(), $this->toArray());
415
    }
416
417
    /**
418
     * @return string
419
     */
420
    public function __toString()
421
    {
422
        return (string) $this->render();
423
    }
424
}
425