Issues (22)

src/Collections/ArrayCollection.php (2 issues)

1
<?php
2
/**
3
 * Created by gerk on 13.11.16 10:53
4
 */
5
6
namespace PeekAndPoke\Component\Collections;
7
8
use PeekAndPoke\Component\Psi\BinaryFunction;
9
use PeekAndPoke\Component\Psi\UnaryFunction;
10
11
/**
12
 * @author Karsten J. Gerber <[email protected]>
13
 */
14
class ArrayCollection extends AbstractCollection implements \ArrayAccess
15
{
16
    /**
17
     * @param $item
18
     *
19
     * @return $this
20
     */
21 16
    public function append($item)
22
    {
23 16
        $this->data[] = $item;
24
25 16
        return $this;
26
    }
27
28
    /**
29
     * Add or replace by condition
30
     *
31
     * The first item that meets the condition is replaced.
32
     * When the condition is not met the subject will be added to the end.
33
     *
34
     * @param mixed                  $subject     The subject to append or replace with
35
     * @param UnaryFunction|callable $replaceWhen The condition to check (gets each entry passed in individually)
36
     *
37
     * @return ArrayCollection
38
     */
39 2
    public function appendOrReplace($subject, callable $replaceWhen)
40
    {
41 2
        foreach ($this as $k => $item) {
42
43 2
            if ($replaceWhen($item)) {
44 1
                $this[$k] = $subject;
45
46 2
                return $this;
47
            }
48
        }
49
50 1
        return $this->append($subject);
51
    }
52
53
    /**
54
     * @param array|\Traversable $items
55
     *
56
     * @return $this
57
     */
58 9
    public function appendAll($items)
59
    {
60 9
        if (! \is_array($items) && ! $items instanceof \Traversable) {
0 ignored issues
show
$items is always a sub-type of Traversable.
Loading history...
61 3
            return $this;
62
        }
63
64 6
        foreach ($items as $item) {
65 4
            $this->append($item);
66
        }
67
68 6
        return $this;
69
    }
70
71
    /**
72
     * Append an item if it does not yet exist in the collection.
73
     *
74
     * @see contains()
75
     *
76
     * @param mixed                        $item
77
     * @param BinaryFunction|callable|null $comparator
78
     *
79
     * @return $this
80
     */
81 10
    public function appendIfNotExists($item, $comparator = null)
82
    {
83 10
        if (! $this->contains($item, $comparator)) {
84 6
            $this->append($item);
85
        }
86
87 10
        return $this;
88
    }
89
90
    /**
91
     * Check if an item is in the list
92
     *
93
     * By default type safe comparison is used.
94
     *
95
     * You can provide $comparator for customer comparison.
96
     *
97
     * @param mixed                        $item
98
     * @param BinaryFunction|callable|null $comparator
99
     *
100
     * @return bool
101
     */
102 20
    public function contains($item, $comparator = null)
103
    {
104 20
        if ($comparator === null) {
105 10
            return $this->containsPure($item);
106
        }
107
108 10
        return $this->containsWithComparator($item, $comparator);
109
    }
110
111
    /**
112
     * Perform pure contains with type safe comparison
113
     *
114
     * @param mixed $item
115
     *
116
     * @return bool
117
     */
118 10
    private function containsPure($item)
119
    {
120 10
        foreach ($this as $storedItem) {
121 8
            if ($storedItem === $item) {
122 8
                return true;
123
            }
124
        }
125
126 6
        return false;
127
    }
128
129
    /**
130
     * Perform contains with comparator
131
     *
132
     * @param mixed                        $item
133
     * @param BinaryFunction|callable|null $comparator
134
     *
135
     * @return bool
136
     */
137 10
    private function containsWithComparator($item, $comparator)
138
    {
139 10
        foreach ($this as $storedItem) {
140 8
            if ($comparator($storedItem, $item)) {
141 8
                return true;
142
            }
143
        }
144
145 6
        return false;
146
    }
147
148
    /**
149
     * @return mixed|null
150
     */
151 4
    public function getFirst()
152
    {
153 4
        return $this->count() > 0 ? $this[0] : null;
154
    }
155
156
    /**
157
     * @return mixed|null
158
     */
159 4
    public function getLast()
160
    {
161 4
        return $this->count() > 0 ? $this[$this->count() - 1] : null;
162
    }
163
164
    /**
165
     * Remove items by type safe comparison
166
     *
167
     * @see removeWhen()
168
     *
169
     * @param $item
170
     */
171 12
    public function remove($item)
172
    {
173 12
        return $this->removeWhen(
0 ignored issues
show
Are you sure the usage of $this->removeWhen(function(...) { /* ... */ }) targeting PeekAndPoke\Component\Co...ollection::removeWhen() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
174 12
            function ($storedItem) use ($item) {
175 11
                return $storedItem === $item;
176 12
            }
177
        );
178
    }
179
180
    /**
181
     * Remove all items that meet the condition
182
     *
183
     * @param callable $removeWhen
184
     */
185 12
    public function removeWhen(callable $removeWhen)
186
    {
187 12
        $result = [];
188
189 12
        foreach ($this as $storedItem) {
190 11
            if (false === (bool) $removeWhen($storedItem)) {
191 11
                $result[] = $storedItem;
192
            }
193
        }
194
195 12
        $this->data = $result;
196 12
    }
197
198
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
199
200
    /**
201
     * @return \Iterator
202
     */
203 43
    public function getIterator()
204
    {
205 43
        return new \ArrayIterator($this->data);
206
    }
207
208
    /**
209
     * Whether a offset exists
210
     *
211
     * @link  http://php.net/manual/en/arrayaccess.offsetexists.php
212
     *
213
     * @param mixed $offset An offset to check for.
214
     *
215
     * @return boolean true on success or false on failure.
216
     */
217 9
    public function offsetExists($offset)
218
    {
219 9
        return isset($this->data[$offset]);
220
    }
221
222
    /**
223
     * Offset to retrieve
224
     *
225
     * @link  http://php.net/manual/en/arrayaccess.offsetget.php
226
     *
227
     * @param mixed $offset The offset to retrieve.
228
     *
229
     * @return mixed Can return all value types.
230
     */
231 7
    public function offsetGet($offset)
232
    {
233 7
        return $this->data[$offset] ?? null;
234
    }
235
236
    /**
237
     * Offset to set
238
     *
239
     * @link  http://php.net/manual/en/arrayaccess.offsetset.php
240
     *
241
     * @param mixed $offset The offset to assign the value to.
242
     * @param mixed $value  The value to set.
243
     */
244 4
    public function offsetSet($offset, $value)
245
    {
246 4
        if ($offset !== null) {
247
            // insert with key: $collection['key'] = $value
248
            // insert key 0:    $collection[0]     = $value;
249 2
            $this->data[$offset] = $value;
250
        } else {
251
            // append to end: $collection[] = $value
252 3
            $this->append($value);
253
        }
254 4
    }
255
256
    /**
257
     * Offset to unset
258
     *
259
     * @link  http://php.net/manual/en/arrayaccess.offsetunset.php
260
     *
261
     * @param mixed $offset The offset to unset.
262
     */
263 1
    public function offsetUnset($offset)
264
    {
265 1
        unset($this->data[$offset]);
266 1
    }
267
}
268