Completed
Push — master ( 53e7f7...cca25f )
by Luís
15:22 queued 11:09
created

SaveAll::mergeErrors()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 14
cts 14
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 10
nc 6
nop 2
crap 4
1
<?php
2
3
namespace Sigep\EloquentEnhancements\Traits;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
7
use Illuminate\Database\Eloquent\Relations\HasMany;
8
use Illuminate\Database\Eloquent\Relations\MorphMany;
9
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
10
use Illuminate\Database\Eloquent\Relations\BelongsTo;
11
12
trait SaveAll
13
{
14
    /**
15
     * @see Model::fill
16
     * @param array $attributes
17
     * @return mixed
18
     */
19
    abstract function fill(array $attributes);
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
20
21
    /**
22
     * @see Model::save
23
     * @param array $options
24
     * @return mixed
25
     */
26
    abstract function save(array $options);
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
27
28
    /**
29
     * Get the default foreign key name for the model.
30
     *
31
     * @return string
32
     */
33
    abstract function getForeignKey();
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
34
35
    /**
36
     * Checks if $options has a callable to do the validation.
37
     * If is provided, call the function and merge erros, if any
38
     * @param array $options
39
     * @param string $path
40
     * @return bool
41
     */
42 22
    private function __handleValidator(array $options, $path)
43
    {
44 22
        $modelName = get_class($this);
45 22
        $validator = null;
46 22
        $response = true;
47
48 22
        if (!empty($options[$modelName]['validator']) && is_callable($options[$modelName]['validator'])) {
49 1
            $validator = $options[$modelName]['validator'];
50 22
        } elseif (!empty($options['validator']) && is_callable($options['validator'])) {
51 1
            $validator = $options['validator'];
52 1
        }
53
54 22
        if ($validator) {
55 2
            $isValid = call_user_func($validator, $this);
56 2
            if ($isValid !== true) {
57 2
                $this->mergeErrors($isValid->toArray(), $path);
58 2
                $response = false;
59 2
            }
60 2
        }
61
62 22
        return $response;
63
    }
64
65
    /**
66
     * Checks if $options has restrictions about what can be filled and
67
     * filters $data
68
     * @param array $options
69
     * @param array $data
70
     */
71 22
    private function __handleFill(array $options, array $data)
72
    {
73 22
        $modelName = get_class($this);
74 22
        if (!empty($options[$modelName]['fillable'])) {
75 1
            $newData = [];
76 1
            foreach ($options[$modelName]['fillable'] as $field) {
77 1
                if (isset($data[$field])) {
78 1
                    $newData[$field] = $data[$field];
79 1
                }
80 1
            }
81 1
            $data = $newData;
82 1
        }
83
84 22
        $this->fill($data);
85 22
    }
86
87
    /**
88
     * create a new object and calls saveAll() method to save its relationships
89
     *
90
     * @param array $data
91
     * @param string $path used to control where put the error messages
92
     *
93
     * @return boolean
94
     */
95 20
    public function createAll(array $data = [], $options = [], $path = '')
96
    {
97 20
        $this->__handleFill($options, $data);
98 20
        $data = $this->checkBelongsTo($data, $options, $path);
99
100 20
        if ($this->errors()->count()) {
0 ignored issues
show
Bug introduced by
The method errors() does not exist on Sigep\EloquentEnhancements\Traits\SaveAll. Did you maybe mean mergeErrors()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
101 1
            return false;
102
        }
103
104 20
        if (!$this->__handleValidator($options, $path) || !$this->save()) {
0 ignored issues
show
Bug introduced by
The call to save() misses a required argument $options.

This check looks for function calls that miss required arguments.

Loading history...
105 4
            return false;
106
        }
107
108 20
        $data = $this->fillForeignKeyRecursively($data);
109
110 20
        return $this->saveAll($data, $options, true, $path);
111
    }
112
113
    /**
114
     * Update current record and create/update its related data
115
     * The related data must be array and the key is the name of the relationship
116
     * We support relationships from relationships too.
117
     *
118
     * @param  array $data
119
     * @param  boolean $skipUpdate if true, current model will not be updated
120
     * @return boolean
121
     */
122 22
    public function saveAll(array $data = [], array $options = [], $skipUpdate = false, $path = '')
123
    {
124 22
        $this->__handleFill($options, $data);
125 22
        $data = $this->checkBelongsTo($data, $options, $path); // @is really necessary?
126
127 22
        if ($this->errors()->count()) {
0 ignored issues
show
Bug introduced by
The method errors() does not exist on Sigep\EloquentEnhancements\Traits\SaveAll. Did you maybe mean mergeErrors()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
128
            return false;
129
        }
130
131 22
        if (!$skipUpdate) {
132 8
            if ($this->__handleValidator($options, $path) === false || $this->save() === false) {
0 ignored issues
show
Bug introduced by
The call to save() misses a required argument $options.

This check looks for function calls that miss required arguments.

Loading history...
133 1
                return false;
134
            }
135 8
        }
136
137 22
        $relationships = $this->getRelationshipsFromData($data);
138
139
        // save relationships
140 22
        foreach ($relationships as $relationship => $values) {
141 20
            $currentPath = $path ? "{$path}." : '';
142 20
            $currentPath .= $relationship;
143
144
            // check allowed amount of related objects
145
            // @todo this is the best way? maybe this must be on validation rules...?
146 20
            if ($this->checkRelationshipLimit($relationship, $values, $currentPath) === false) {
147 1
                return false;
148
            }
149
150 20
            if ($this->shouldDetachModels($relationship, $values)) {
151 1
                $this->$relationship()->withTimestamps()->detach();
152 1
            }
153
154 20
            if (!$this->addRelated($relationship, $values, $options, $currentPath)) {
155 4
                return false;
156
            }
157 21
        }
158
159
        // search for relationships that has limit and no data was send, to apply the minimum validation
160 21
        if (isset($this->relationshipsLimits)) {
161 10
            $relationshipsLimits = $this->relationshipsLimits;
0 ignored issues
show
Bug introduced by
The property relationshipsLimits does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
162 10
            $checkRelationships = array_diff(array_keys($relationshipsLimits), array_keys($relationships));
163
164 10
            foreach ($checkRelationships as $checkRelationship) {
165 1
                $currentPath = $path ? "{$path}." : '';
166 1
                $currentPath .= $checkRelationship;
167
168 1
                if (!$this->checkRelationshipLimit($checkRelationship, [], $currentPath)) {
169 1
                    return false;
170
                }
171 10
            }
172 10
        }
173
174 21
        return true;
175
    }
176
177
    /**
178
     * Put the id of current object as foreign key in all arrays inside $data
179
     * Util when a relationship of a relationship depends of the id from current
180
     * model as foreign key to.
181
     * To avoid problems, data must to have the foreign key with "auto" value.
182
     * Just in case that the records belongs, for any reason, to another object
183
     *
184
     * @param array $data changed data
185
     *
186
     * @return array
187
     */
188 20
    private function fillForeignKeyRecursively(array $data)
189
    {
190 20
        $foreign = $this->getForeignKey();
191
192 20
        foreach ($data as &$piece) {
193 20
            if (is_array($piece)) {
194 17
                $piece = $this->fillForeignKeyRecursively($piece);
195 17
            }
196 20
        }
197
198 20
        if (isset($data[$foreign]) && $data[$foreign] == 'auto' && $this->id) {
199
            $data[$foreign] = $this->id;
0 ignored issues
show
Bug introduced by
The property id does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
200
        }
201
202 20
        return $data;
203
    }
204
205
    /**
206
 * Determines if sync() should be used to create records on belongsToMany relationships
207
 *
208
 * @param string $relationship name of relationship
209
 * @param array $data data to check
210
 *
211
 * @return bool
212
 */
213 20
    private function shouldUseSync($relationship, $data)
214
    {
215 20
        $relationship = $this->$relationship();
216 20
        if ($relationship instanceof BelongsToMany && count($data) === 1) {
217
            // check foreign key
218 5
            $foreignKey = last(explode('.', $relationship->getOtherKey()));
219 5
            if (isset($data[$foreignKey]) && is_array($data[$foreignKey])) {
220 1
                return true;
221
            }
222 4
        }
223
224 19
        return false;
225
    }
226
227
    /**
228
     * Determines if sync() should be used to create records on belongsToMany relationships
229
     *
230
     * @param string $relationship name of relationship
231
     * @param array $data data to check
232
     *
233
     * @return bool
234
     */
235 20
    private function shouldDetachModels($relationship, $data)
236 1
    {
237 20
        $relationship = $this->$relationship();
238 20
        if ($relationship instanceof BelongsToMany && count($data) >= 1 && is_array($data)) {
239 9
            foreach ($data as $element) {
240 8
                if (!is_array($element) || empty($element) || empty($element['id'])) {
241 7
                    return false;
242
                }
243 2
            }
244 1
            return true;
245
        }
246
247 12
        return false;
248
    }
249
250
    /**
251
     * This method is specific to create objects that are related with the current model on a
252
     * belongsTo relationship.
253
     * Useful to create a record that belongs to another record that don't exists yet.
254
     * This method will remove from $data data relative to belongsTo elements
255
     *
256
     * @param array $data
257
     * @param string $path
258
     * @return array
259
     */
260 22
    private function checkBelongsTo($data, array $options = [], $path = '') {
261 22
        $relationships = $this->getRelationshipsFromData($data);
262
263 22
        foreach ($relationships as $relationship => $values) {
264 21
            $relationshipObject = $this->$relationship();
265
266 21
            if ($relationshipObject instanceof BelongsTo === false) {
267 20
                continue;
268
            }
269
270 3
            $currentPath = $path ? "{$path}." : '';
271 3
            $currentPath .= $relationship;
272
            
273 3
            $foreignKey = $relationshipObject->getForeignKey();
274 3
            if (!empty($values['id'])) {
275 1
                $this->$foreignKey = (int) $values['id'];
276 1
            } else {
277 2
                $object = $relationshipObject->getRelated();
278 2
                if (!$object->createAll($values, $options)) {
279 2
                    $this->mergeErrors($object->errors()->toArray(), $currentPath);
280 1
                } else {
281 1
                    $this->$foreignKey = $object->id;
282 1
                }
283
            }
284
285 3
            unset($data[$relationship]);
286 22
        }
287
288 22
        return $data;
289
    }
290
291
    /**
292
     * Get the specified limit for $relationship or false if not exists
293
     * @param $relationship name of the relationship
294
     * @return mixed
295
     */
296 20
    protected function getRelationshipLimit($relationship)
297
    {
298 20
        if (isset($this->relationshipsLimits[$relationship])) {
299 14
            return array_map (
300 14
                'intval',
301 14
                explode(':', $this->relationshipsLimits[$relationship])
302 14
            );
303
        }
304
305 9
        return false;
306
    }
307
308
    /**
309
     * Checks if amount of related objects are allowed
310
     * @param string $relationship relationship name
311
     * @param array $values
312
     * @param string $path
313
     * @return array modified $values
314
     */
315 20
    protected function checkRelationshipLimit($relationship, $values, $path)
316
    {
317 20
        $relationshipLimit = $this->getRelationshipLimit($relationship);
318 20
        if (!$relationshipLimit) {
319 9
            return $values;
320
        }
321
322 14
        if (count($values) === 1 && $this->shouldUseSync($relationship, $values)) {
323 1
            $sumRelationships = count(end($values));
324 1
        } else {
325 13
            $this->load($relationship);
0 ignored issues
show
Bug introduced by
It seems like load() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
326 13
            $currentRelationships = $this->$relationship->count();
327 13
            $newRelationships = 0;
328 13
            $removeRelationships = [];
329
330
            // check if is associative
331 13
            if ($values && $values !== array_values($values)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $values of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
332 1
                return true; // @todo prevent this
333
            }
334
335 12
            foreach ($values as $key => $value) {
336 12
                $arrayIsEmpty = array_filter($value);
337 12
                if (empty($arrayIsEmpty)) {
338 1
                    unset($values[$key]);
339 1
                    continue;
340
                }
341
342 12
                if (!isset($value['id'])) {
343 12
                    $newRelationships++;
344 12
                    $removeRelationships[] = $key;
345 12
                }
346 12
            }
347
348 12
            $sumRelationships = $currentRelationships + $newRelationships;
349
        }
350
351 13
        $this->errors();
0 ignored issues
show
Bug introduced by
The method errors() does not exist on Sigep\EloquentEnhancements\Traits\SaveAll. Did you maybe mean mergeErrors()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
352 13
        if ($sumRelationships < $relationshipLimit[0]) {
353 1
            $this->errors->add($path, 'validation.min', $relationshipLimit[0]);
0 ignored issues
show
Bug introduced by
The property errors does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
354 1
        }
355
356 13
        if ($sumRelationships > $relationshipLimit[1]) {
357 1
            $this->errors->add($path, 'validation.max', $relationshipLimit[1]);
358 1
        }
359
360 13
        if ($this->errors->has($path)) {
361 1
            return false;
362
        }
363
364 13
        return true;
365
    }
366
367
    /**
368
     * Add related data to the current model recursively
369
     * @param string $relationshipName
370
     * @param array $values
371
     * @return bool
372
     */
373 20
    public function addRelated($relationshipName, array $values, array $options = [], $path = '')
374
    {
375 20
        $relationship = $this->$relationshipName();
376
377
        // if is a numeric array, recursive calls to add multiple related
378 20
        if (ctype_digit(implode('', array_keys($values))) === true) {
379 18
            $position = 0;
380 18
            foreach ($values as $value) {
381 18
                if (!$this->addRelated($relationshipName, $value, $options, $path . '.' . $position++)) {
382 4
                    return false;
383
                }
384 17
            }
385
386 16
            return true;
387
        }
388
389
        // if has not data, skip
390 20
        $arrayIsEmpty = array_filter($values);
391 20
        if (empty($arrayIsEmpty)) {
392 1
            return true;
393
        }
394
395 20
        if ($this->shouldUseSync($relationshipName, $values)) {
396 1
            $this->$relationshipName()->sync(end($values));
397 1
            return true;
398
        }
399
400
        // set foreign for hasMany relationships
401 19
        if ($relationship instanceof HasMany) {
402 12
            $values[last(explode('.', $relationship->getForeignKey()))] = $this->id;
403 12
        }
404
405
        // if is MorphToMany, put other foreign and fill the type
406 19
        if ($relationship instanceof MorphMany) {
407 1
            $values[$relationship->getPlainForeignKey()] = $this->id;
408 1
            $values[$relationship->getPlainMorphType()] = get_class($this);
409 1
        }
410
411
        // if BelongsToMany, put current id in place
412 19
        if ($relationship instanceof BelongsToMany) {
413 7
            $values[last(explode('.', $relationship->getForeignKey()))] = $this->id;
414 7
            $belongsToManyOtherKey = last(explode('.', $relationship->getOtherKey()));
415 7
        }
416
417
        // get target Model
418 19
        if ($relationship instanceof HasManyThrough) {
419
            $model = $relationship->getParent();
420
        } else {
421 19
            $model = $relationship->getRelated();
422
        }
423
424
        // if has ID, delete or update
425 19
        if (!empty($values['id']) && $relationship instanceof BelongsToMany === false) {
426 2
            $obj = $model->find($values['id']);
427 2
            if (!$obj) {
428
                return false; // @todo transport error
429
            }
430
431
            // delete or update?
432 2
            if (!empty($values['_delete'])) {
433
                return $obj->delete();
434
            }
435
436 2
            if (!$obj->saveAll($values, $options)) {
437
                $this->mergeErrors($obj->errors()->toArray(), $path);
438
                return true;
439
            }
440
441 2
            return true;
442
        }
443
444
        // only BelongsToMany :)
445 19
        if (!empty($values['_delete'])) {
446 1
            $this->$relationshipName()->detach($values[last(explode('.', $relationship->getOtherKey()))]);
447 1
            return true;
448
        }
449
450
451 19
        if ((isset($belongsToManyOtherKey) && empty($values[$belongsToManyOtherKey]))) {
452 3
            $obj = $relationship->getRelated();
453
            // if has conditions, fill the values
454
            // this helps to add static values in relationships using its conditions
455
            // @todo experimental
456 3
            foreach ($relationship->getQuery()->getQuery()->wheres as $where) {
457 3
                $column = last(explode('.', $where['column']));
458 3
                if (!empty($where['value']) && empty($values[$column])) {
459
                    $values[$column] = $where['value'];
460
                }
461 3
            }
462
463 3
            if (empty($values['id'])) {
464 2
                if (!$obj->createAll($values, $options)) {
465
                    $this->mergeErrors($obj->errors()->toArray(), $path);
466
                    return false;
467
                }
468 2
                $values[$belongsToManyOtherKey] = $obj->id;
469 2
            }
470
471 3
        }
472
473 19
        if ($relationship instanceof HasMany || $relationship instanceof MorphMany) {
474 12
            $relationshipObject = $relationship->getRelated();
475 19
        } elseif ($relationship instanceof BelongsToMany) {
476
            // if has a relationshipModel, use the model. Else, use attach
477
            // attach doesn't return nothing :(
478 7
            if (empty($this->relationshipsModels[$relationshipName])) {
0 ignored issues
show
Bug introduced by
The property relationshipsModels does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
479 4
                $field = last(explode('.', $relationship->getOtherKey()));
480 4
                if (!isset($values[$field])) {
481 1
                    $field = 'id';
482 1
                }
483 4
                $related = $this->$relationshipName->contains($values[$field]);
484 4
                if (empty($related)) {
485 4
                    $this->$relationshipName()->attach($values[$field]);
486 4
                }
487
488 4
                return true;
489
            }
490
491 3
            $relationshipObjectName = $this->relationshipsModels[$relationshipName];
492
493 3
            if (empty($values['id']) || !is_numeric($values['id'])) {
494 2
                $relationshipObject = new $relationshipObjectName;
495 2
            } else {
496 2
                if (!empty($values[$belongsToManyOtherKey])) {
497 1
                    $relationshipObject = $relationshipObjectName::find($values['id']);
498 1
                } else {
499 1
                    $relationshipObject = $relationship->getRelated()->find($values['id']);
500
501 1
                    if (!empty($relationshipObject)) {
502
                        //if (!$this->$relationshipName->contains($values['id'])) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
503 1
                            $this->$relationshipName()->withTimestamps()->attach($values['id']);
504
                        //}
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
505
//                        return true;
506 1
                    }
507
                }
508
509 2
                if (!$relationshipObject) {
510
                    $relationshipObject = new $relationshipObjectName; // @todo check this out
511
                }
512
            }
513 3
        } elseif ($relationship instanceof HasManyThrough) {
514
            $relationshipObject = $model;
515
        }
516
517 15
        $useMethod = (empty($values['id'])) ? 'createAll' : 'saveAll';
518 15
        if (!$relationshipObject->$useMethod($values, $options)) {
519 4
            $this->mergeErrors($relationshipObject->errors()->toArray(), $path);
0 ignored issues
show
Bug introduced by
The variable $relationshipObject does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
520 4
            return false;
521
        }
522
523 14
        return true;
524
    }
525
526
    /**
527
     * get values that are array in $data
528
     * use this function to extract relationships from Input::all(), for example
529
     * @param  array $data
530
     * @return array
531
     */
532 22
    public function getRelationshipsFromData(array $data = [])
533
    {
534 22
        $relationships = [];
535
536 22
        foreach ($data as $key => $value) {
537 22
            if (is_array($value) && !is_numeric($key) && method_exists($this, $key)) {
538 21
                $relationships[$key] = $value;
539 21
            }
540 22
        }
541
542 22
        return $relationships;
543
    }
544
545
    /**
546
     * Merge $objErrors with $this->errors using $path
547
     *
548
     * @param array $objErrors
549
     * @param string $path
550
     */
551 4
    protected function mergeErrors(array $objErrors, $path)
552
    {
553 4
        $thisErrors = $this->errors();
0 ignored issues
show
Bug introduced by
The method errors() does not exist on Sigep\EloquentEnhancements\Traits\SaveAll. Did you maybe mean mergeErrors()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
554 4
        if ($path) {
555 4
            $path .= '.';
556 4
        }
557 4
        foreach ($objErrors as $field => $errors) {
558 4
            foreach ($errors as $error) {
559 4
                $thisErrors->add(
560 4
                    "{$path}{$field}",
561
                    $error
562 4
                );
563 4
            }
564 4
        }
565 4
        $this->setErrors($thisErrors);
0 ignored issues
show
Bug introduced by
It seems like setErrors() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
566 4
    }
567
}
568