Passed
Push — master ( 1afdc5...93f20a )
by
unknown
01:15 queued 13s
created

SerialStream::toArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Maxim Sokolovsky
4
 */
5
6
namespace WS\Utils\Collections;
7
8
use RuntimeException;
9
10
class SerialStream implements Stream
11
{
12
    /**
13
     * @var ListSequence
14
     */
15
    private $list;
16
17 161
    public function __construct(Collection $collection)
18
    {
19 161
        if ($collection instanceof ListSequence) {
20 158
            $this->list = $collection->copy();
21
        } else {
22 3
            $this->list = $this->emptyList();
23 3
            $this->list->addAll($collection->toArray());
24
        }
25 161
    }
26
27
    /**
28
     * @inheritDoc
29
     */
30 21
    public function each(callable $consumer): Stream
31
    {
32 21
        $i = 0;
33 21
        foreach ($this->list as $item) {
34 20
            $consumer($item, $i++);
35
        }
36 20
        return $this;
37
    }
38
39
    /**
40
     * @inheritDoc
41
     */
42 29
    public function filter(callable $predicate): Stream
43
    {
44 29
        $collection = $this->list;
45 29
        $this->list = $this->emptyList();
46
47 29
        foreach ($collection as $item) {
48 28
            if ($predicate($item)) {
49 28
                $this->list->add($item);
50
            }
51
        }
52
53 29
        return $this;
54
    }
55
56 14
    public function reorganize(callable $reorganizer): Stream
57
    {
58 14
        $reorganizedCollection = $reorganizer($this->list->copy());
59 14
        if (! $reorganizedCollection instanceof Collection) {
60 1
            throw new RuntimeException('Result set of reorganizer call must be instance of Collection interface');
61
        }
62 13
        $this->list = $reorganizedCollection;
63
64 13
        return $this;
65
    }
66
67
    /**
68
     * @inheritDoc
69
     */
70 3
    public function allMatch(callable $predicate): bool
71
    {
72 3
        foreach ($this->list as $item) {
73 2
            if (!$predicate($item)) {
74 2
                return false;
75
            }
76
        }
77 2
        return true;
78
    }
79
80
    /**
81
     * @inheritDoc
82
     */
83 5
    public function anyMatch(callable $predicate): bool
84
    {
85 5
        foreach ($this->list as $item) {
86 4
            if ($predicate($item)) {
87 4
                return true;
88
            }
89
        }
90
91 3
        return false;
92
    }
93
94
    /**
95
     * @inheritDoc
96
     */
97 13
    public function map(callable $converter): Stream
98
    {
99 13
        $collection = $this->list;
100 13
        $this->list = $this->emptyList();
101
102 13
        foreach ($collection as $item) {
103 12
            $this->list->add($converter($item));
104
        }
105 13
        return $this;
106
    }
107
108
    /**
109
     * @inheritDoc
110
     */
111 15
    public function sort(callable $comparator): Stream
112
    {
113 15
        $collection = $this->getCollection();
114 15
        $this->list = $this->emptyList();
115
116 15
        $array = $collection->toArray();
117 15
        usort($array, $comparator);
118 15
        foreach ($array as $item) {
119 13
            $this->list->add($item);
120
        }
121
122 15
        return $this;
123
    }
124
125 9
    public function sortBy(callable $extractor): Stream
126
    {
127 9
        $values = [];
128 9
        $map = [];
129
        $this->each(static function ($el) use ($extractor, & $map, & $values) {
130 9
            $value = $extractor($el);
131 9
            if (!is_scalar($value)) {
132 1
                throw new RuntimeException('Only scalar value can be as result of sort extractor');
133
            }
134 8
            $values[] = $value;
135 8
            $map[$value.''][] = $el;
136 9
        });
137 8
        sort($values);
138 8
        $newList = $this->emptyList();
139 8
        foreach ($values as $value) {
140 8
            $els = $map[$value] ?? [];
141 8
            $newList->addAll($els);
142
        }
143 8
        $this->list = $newList;
144
145 8
        return $this;
146
    }
147
148 4
    public function sortByDesc(callable $extractor): Stream
149
    {
150 4
        $this->sortBy($extractor)
151 4
            ->reverse();
152
153 4
        return $this;
154
    }
155
156
    /**
157
     * @inheritDoc
158
     */
159 4
    public function sortDesc(callable $comparator): Stream
160
    {
161 4
        $this->sort($comparator)
162 4
            ->reverse();
163
164 4
        return $this;
165
    }
166
167 12
    public function reverse(): Stream
168
    {
169 12
        $array = $this->list->toArray();
170 12
        $reversedArray = array_reverse($array);
171 12
        $this->list = $this->emptyList();
172 12
        $this->list->addAll($reversedArray);
173 12
        return $this;
174
    }
175
176
    /**
177
     * @inheritDoc
178
     */
179 18
    public function collect(callable $collector)
180
    {
181 18
        return $collector($this->getCollection()->copy());
182
    }
183
184
    /**
185
     * @inheritDoc
186
     */
187 4
    public function findAny()
188
    {
189 4
        $size =  $this->list->size();
190 4
        if ($size === 0) {
191 1
            return null;
192
        }
193
        /** @noinspection PhpUnhandledExceptionInspection */
194 3
        $rIndex = random_int(0, $size - 1);
195 3
        $pointer = 0;
196 3
        $item = null;
197 3
        foreach ($this->list as $item) {
198 3
            if ($rIndex === $pointer++) {
199 3
                break;
200
            }
201
        }
202 3
        return $item;
203
    }
204
205
    /**
206
     * @inheritDoc
207
     */
208 22
    public function findFirst(callable $filter = null)
209
    {
210 22
        if (!$filter) {
211
            /** @noinspection LoopWhichDoesNotLoopInspection */
212 19
            foreach ($this->list as $item) {
213 18
                return $item;
214
            }
215 1
            return null;
216
        }
217
        /** @noinspection LoopWhichDoesNotLoopInspection */
218 3
        foreach ($this->list as $item) {
219 2
            if ($filter($item)) {
220 2
                return $item;
221
            }
222
        }
223 2
        return null;
224
    }
225
226
    /**
227
     * @inheritDoc
228
     */
229 4
    public function min(callable $comparator)
230
    {
231 4
        $collection = $this->getCollection();
232 4
        if ($collection->size() === 0) {
233 1
            return null;
234
        }
235
236 3
        $array = $collection->toArray();
237
238 3
        $el = array_shift($array);
239
240 3
        foreach ($array as $item) {
241 2
            if ($comparator($item, $el) < 0) {
242 2
                $el = $item;
243
            }
244
        }
245
246 3
        return $el;
247
    }
248
249
    /**
250
     * @inheritDoc
251
     */
252 4
    public function max(callable $comparator)
253
    {
254 4
        $collection = $this->getCollection();
255 4
        if ($collection->size() === 0) {
256 1
            return null;
257
        }
258
259 3
        $array = $collection->toArray();
260 3
        $el = null;
261
262 3
        foreach ($array as $item) {
263 3
            if ($comparator($item, $el) > 0) {
264 3
                $el = $item;
265
            }
266
        }
267
268 3
        return $el;
269
    }
270
271
    /**
272
     * @inheritDoc
273
     */
274 4
    public function reduce(callable $accumulator, $initialValue = null)
275
    {
276 4
        $accumulate = $initialValue;
277 4
        foreach ($this->list as $item) {
278 2
            $accumulate = $accumulator($item, $accumulate);
279
        }
280 4
        return $accumulate;
281
    }
282
283 112
    public function getCollection(): Collection
284
    {
285 112
        return $this->list->copy();
286
    }
287
288 65
    private function emptyList(): Collection
289
    {
290 65
        return ArrayList::of();
291
    }
292
293 19
    public function findLast()
294
    {
295 19
        $array = $this->list->toArray();
296 19
        return array_pop($array);
297
    }
298
299 3
    public function walk(callable $consumer, ?int $limit = null): Stream
300
    {
301 3
        $iterationsCount = $limit ?? $this->list->size();
302 3
        foreach ($this->list as $i => $item) {
303 3
            $consumerRes = $consumer($item, $i);
304 3
            if ($consumerRes === false) {
305 1
                break;
306
            }
307 3
            if ($i + 1 >= $iterationsCount) {
308 3
                break;
309
            }
310
        }
311
312 3
        return $this;
313
    }
314
315 1
    public function limit(int $size): Stream
316
    {
317 1
        $newCollection = $this->emptyList();
318
        $this->walk(static function ($el) use ($newCollection) {
319 1
            $newCollection->add($el);
320 1
        }, $size);
321
322 1
        $this->list = $newCollection;
323 1
        return $this;
324
    }
325
326 16
    public function when(bool $condition): Stream
327
    {
328 16
        if (!$condition) {
329 15
            return new DummyStreamDecorator($this);
330
        }
331
332 1
        return $this;
333
    }
334
335 1
    public function always(): Stream
336
    {
337 1
        return $this;
338
    }
339
340
    /**
341
     * @inheritDoc
342
     */
343 2
    public function toArray(): array
344
    {
345
        return $this
346 2
            ->getCollection()
347 2
            ->toArray()
348
        ;
349
    }
350
351
    /**
352
     * @inheritDoc
353
     */
354 1
    public function getSet(): Set
355
    {
356 1
        return new HashSet($this->toArray());
357
    }
358
}
359