Completed
Push — master ( 06b292...adafac )
by Nicolai
02:22
created

BacksUpItems.php ➔ is_iterable()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
4
namespace SmartWeb\ModuleTesting\Util;
5
6
use DeepCopy\DeepCopy;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Collection;
9
use InvalidArgumentException;
10
use SmartWeb\ModuleTesting\Support\Concerns\MutatesAttributes;
11
use Traversable;
12
13
14
if (!function_exists('is_iterable')) {
15
    /**
16
     * true if a value is iterable and will be accepted by the iterable pseudo-type, false for other values.
17
     *
18
     * @param mixed $value
19
     *
20
     * @return bool
21
     *
22
     * @see  \is_iterable()
23
     * @link https://wiki.php.net/rfc/iterable
24
     */
25
    function is_iterable($value)
0 ignored issues
show
Best Practice introduced by
The function SmartWeb\ModuleTesting\Util\is_iterable() has been defined more than once; this definition is ignored, only the first definition in src/Helpers/helpers.php (L14-17) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
26
    {
27
        return (is_array($value) or ($value instanceof Traversable));
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or 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...
28
    }
29
}
30
31
32
/**
33
 * Trait BacksUpItems
34
 *
35
 * @package SmartWeb\Testing\Util
36
 */
37
trait BacksUpItems
38
{
39
    
40
    use MutatesAttributes;
41
    
42
    /**
43
     * @var Collection
44
     */
45
    protected $items;
46
    
47
    /**
48
     * @var Collection
49
     */
50
    private $itemsBackup;
51
    
52
    /**
53
     * @var DeepCopy
54
     */
55
    private $copier;
56
    
57
    /**
58
     * @ignore
59
     *
60
     * @param $name
61
     *
62
     * @return mixed
63
     */
64
    final public function __get($name)
65
    {
66
        if ($this->hasGetMutator($name)) {
67
            return $this->getMutatedAttribute($name);
68
        }
69
        
70
        return $this->items[$name];
71
    }
72
    
73
    /**
74
     * @ignore
75
     *
76
     * @param $name
77
     * @param $value
78
     */
79
    final public function __set($name, $value)
80
    {
81
        $this->items[$name] = $value;
82
    }
83
    
84
    /**
85
     * @param mixed[] ...$items
86
     */
87
    final protected function inject(...$items)
88
    {
89
        $this->items = new Collection();
90
        
91
        foreach ($items as $item) {
92
            if (is_iterable($item) && Arr::isAssoc($item)) {
93
                $this->items = $this->items->merge($item);
94
            } else {
95
                throw new InvalidArgumentException("\$items must be an associative array.");
96
            }
97
        }
98
        
99
        $this->itemsBackup = $this->items ?? new Collection();
100
    }
101
    
102
    final protected function backupItems()
103
    {
104
        $this->itemsBackup = $this->getCopier()->copy($this->items ?? new Collection());
105
    }
106
    
107
    final protected function restoreItems()
108
    {
109
        $this->items = $this->getCopier()->copy($this->itemsBackup);
110
        $this->itemsBackup = null;
111
    }
112
    
113
    /**
114
     * @return DeepCopy
115
     */
116
    private function getCopier() : DeepCopy
117
    {
118
        return ($this->copier = $this->copier ?? new DeepCopy(true))->skipUncloneable();
119
    }
120
}