Passed
Push — master ( 869b54...918a00 )
by Arnold
03:06
created

With::withoutPropertyItem()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 4
nop 2
dl 0
loc 19
ccs 11
cts 11
cp 1
crap 4
rs 9.9332
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Jasny\Immutable;
4
5
use ArrayAccess;
6
7
/**
8
 * Trait with the `withProperty` methods that can be used by classes of immutable objects.
9
 *
10
 * {@internal Some lines are expected to be covered, which should be ignored. Added codeCoverageIgnore. }}
11
 */
12
trait With
13
{
14
    /**
15
     * Return a copy with a changed property.
16
     * Returns this object if the resulting object would be the same as the current one.
17
     *
18
     * @param string  $property
19
     * @param mixed   $value
20
     * @return static
21
     * @throws \BadMethodCallException if property doesn't exist
22
     */
23 2
    protected function withProperty(string $property, $value)
24
    {
25 2
        if (!property_exists($this, $property)) {
26 1
            throw new \BadMethodCallException(sprintf('%s has no property "%s"', get_class($this), $property));
27
        }
28
29 1
        if ($this->{$property} === $value) {
30 1
            return $this;
31
        }
32
33 1
        $clone = clone $this;
34 1
        $clone->{$property} = $value;
35
36 1
        return $clone;
37
    }
38
39
    /**
40
     * Return a copy with a property unset.
41
     * Returns this object if the resulting object would be the same as the current one.
42
     *
43
     * @param string  $property
44
     * @return static
45
     * @throws \BadMethodCallException if property doesn't exist
46
     */
47 2
    protected function withoutProperty(string $property)
48
    {
49 2
        if (!property_exists($this, $property)) {
50 1
            throw new \BadMethodCallException(sprintf('%s has no property "%s"', get_class($this), $property));
51
        }
52
53 1
        if (!isset($this->{$property})) {
54 1
            return $this;
55
        }
56
57 1
        $clone = clone $this;
58 1
        unset($clone->{$property});
59
60 1
        return $clone;
61
    }
62
63
64
    /**
65
     * Return a copy with an added item for a property.
66
     * Returns this object if the resulting object would be the same as the current one.
67
     *
68
     * @param string  $property
69
     * @param string  $key
70
     * @param mixed   $value
71
     * @return static
72
     * @throws \BadMethodCallException if property doesn't exist
73
     */
74 2
    protected function withPropertyKey(string $property, string $key, $value)
75
    {
76 2
        if (!property_exists($this, $property)) {
77
            throw new \BadMethodCallException(sprintf('%s has no property "%s"', get_class($this), $property));
78
        } // @codeCoverageIgnore
79 2
        if (!is_array($this->{$property}) && !$this->{$property} instanceof ArrayAccess) {
80 1
            throw new \BadMethodCallException(sprintf('%s::$%s is not an array', get_class($this), $property));
81
        }
82
83 1
        if (isset($this->{$property}[$key]) && $this->{$property}[$key] === $value) {
84 1
            return $this;
85
        }
86
87 1
        $clone = clone $this;
88 1
        $clone->{$property}[$key] = $value;
89
90 1
        return $clone;
91
    }
92
93
    /**
94
     * Return a copy with a removed item from a property.
95
     * Returns this object if the resulting object would be the same as the current one.
96
     *
97
     * @param string  $property
98
     * @param string  $key
99
     * @return static
100
     * @throws \BadMethodCallException if property doesn't exist or isn't an array
101
     */
102 3
    protected function withoutPropertyKey(string $property, string $key)
103
    {
104 3
        if (!property_exists($this, $property)) {
105 1
            throw new \BadMethodCallException(sprintf('%s has no property "%s"', get_class($this), $property));
106
        } // @codeCoverageIgnore
107 2
        if (!is_array($this->{$property}) && !$this->{$property} instanceof ArrayAccess) {
108 1
            throw new \BadMethodCallException(sprintf('%s::$%s is not an array', get_class($this), $property));
109
        }
110
111 1
        if (!isset($this->{$property}[$key])) {
112 1
            return $this;
113
        }
114
115 1
        $clone = clone $this;
116 1
        unset($clone->{$property}[$key]);
117
118 1
        return $clone;
119
    }
120
121
122
    /**
123
     * Return a copy with a value added to a sequential array.
124
     *
125
     * @param string  $property
126
     * @param mixed   $value
127
     * @param mixed   $unique    Don't add if the array already has a copy of the value.
128
     * @return static
129
     * @throws \BadMethodCallException if property doesn't exist or isn't an array
130
     */
131 2
    protected function withPropertyItem(string $property, $value, bool $unique = false)
132
    {
133 2
        if (!property_exists($this, $property)) {
134
            throw new \BadMethodCallException(sprintf('%s has no property "%s"', get_class($this), $property));
135
        } // @codeCoverageIgnore
136 2
        if (!is_array($this->{$property})) {
137 1
            throw new \BadMethodCallException(sprintf('%s::$%s is not an array', get_class($this), $property));
138
        }
139
140 1
        if ($unique && in_array($value, $this->{$property}, true)) {
141 1
            return $this;
142
        }
143
144 1
        $clone = clone $this;
145 1
        $clone->{$property}[] = $value;
146
147 1
        return $clone;
148
    }
149
150
    /**
151
     * Return a copy with a value removed from a sequential array.
152
     * Returns this object if the resulting object would be the same as the current one.
153
     *
154
     * @param string  $property
155
     * @param mixed   $value
156
     * @return static
157
     * @throws \BadMethodCallException if property doesn't exist or isn't an array
158
     */
159 3
    protected function withoutPropertyItem(string $property, $value)
160
    {
161 3
        if (!property_exists($this, $property)) {
162 1
            throw new \BadMethodCallException(sprintf('%s has no property "%s"', get_class($this), $property));
163
        }
164 2
        if (!is_array($this->{$property})) {
165 1
            throw new \BadMethodCallException(sprintf('%s::$%s is not an array', get_class($this), $property));
166
        }
167
168 1
        $keys = array_keys($this->{$property}, $value, true);
169
170 1
        if ($keys === []) {
171 1
            return $this;
172
        }
173
174 1
        $clone = clone $this;
175 1
        $clone->{$property} = array_values(array_diff_key($clone->{$property}, array_fill_keys($keys, null)));
176
177 1
        return $clone;
178
    }
179
}
180