GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — develop ( c3b70c...588978 )
by Baptiste
05:12
created

Stream::toArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Immutable;
5
6
use Innmind\Immutable\Exception\{
7
    LogicException,
8
    GroupEmptySequenceException,
9
    InvalidArgumentException
10
};
11
12
/**
13
 * {@inheritdoc}
14
 */
15
final class Stream implements \Countable
16
{
17
    private string $type;
18
    private SpecificationInterface $spec;
19
    private Sequence $values;
20
21 145
    public function __construct(string $type)
22
    {
23 145
        $this->type = $type;
24 145
        $this->spec = Type::of($type);
25 145
        $this->values = new Sequence;
26 145
    }
27
28
    /**
29
     * @param T $values
30
     */
31 48
    public static function of(string $type, ...$values): self
32
    {
33 48
        $self = new self($type);
34 48
        $self->values = new Sequence(...$values);
35
        $self->values->foreach(static function($element) use ($self): void {
36 37
            $self->spec->validate($element);
37 48
        });
38
39 48
        return $self;
40
    }
41
42 27
    public function isOfType(string $type): bool
43
    {
44 27
        return $this->type === $type;
45
    }
46
47
    /**
48
     * Type of the elements
49
     */
50 32
    public function type(): string
51
    {
52 32
        return $this->type;
53
    }
54
55 23
    public function size(): int
56
    {
57 23
        return $this->values->size();
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 5
    public function count(): int
64
    {
65 5
        return $this->values->size();
66
    }
67
68 80
    public function toArray(): array
69
    {
70 80
        return $this->values->toArray();
71
    }
72
73
    /**
74
     * Return the element at the given index
75
     *
76
     * @throws OutOfBoundException
77
     *
78
     * @return T
79
     */
80 24
    public function get(int $index)
81
    {
82 24
        return $this->values->get($index);
83
    }
84
85
    /**
86
     * Return the diff between this stream and another
87
     *
88
     * @param self<T> $stream
89
     *
90
     * @return self<T>
91
     */
92 2
    public function diff(self $stream): self
93
    {
94 2
        $this->validate($stream);
95
96 2
        $newStream = clone $this;
97 2
        $newStream->values = $this->values->diff(
98 2
            new Sequence(...$stream->toArray())
99
        );
100
101 2
        return $newStream;
102
    }
103
104
    /**
105
     * Remove all duplicates from the stream
106
     *
107
     * @return self<T>
108
     */
109 33
    public function distinct(): self
110
    {
111 33
        $stream = clone $this;
112 33
        $stream->values = $this->values->distinct();
113
114 33
        return $stream;
115
    }
116
117
    /**
118
     * Remove the n first elements
119
     *
120
     * @return self<T>
121
     */
122 4
    public function drop(int $size): self
123
    {
124 4
        $stream = clone $this;
125 4
        $stream->values = $this->values->drop($size);
126
127 4
        return $stream;
128
    }
129
130
    /**
131
     * Remove the n last elements
132
     *
133
     * @return self<T>
134
     */
135 1
    public function dropEnd(int $size): self
136
    {
137 1
        $stream = clone $this;
138 1
        $stream->values = $this->values->dropEnd($size);
139
140 1
        return $stream;
141
    }
142
143
    /**
144
     * Check if the two streams are equal
145
     *
146
     * @param self<T> $stream
147
     */
148 7
    public function equals(self $stream): bool
149
    {
150 7
        $this->validate($stream);
151
152 6
        return $this->values->equals(
153 6
            new Sequence(...$stream->toArray())
154
        );
155
    }
156
157
    /**
158
     * Return all elements that satisfy the given predicate
159
     *
160
     * @param callable(T): bool $predicate
161
     *
162
     * @return self<T>
163
     */
164 2
    public function filter(callable $predicate): self
165
    {
166 2
        $stream = clone $this;
167 2
        $stream->values = $this->values->filter($predicate);
168
169 2
        return $stream;
170
    }
171
172
    /**
173
     * Apply the given function to all elements of the stream
174
     *
175
     * @param callable(T): void $function
176
     *
177
     * @return self<T>
178
     */
179 2
    public function foreach(callable $function): void
180
    {
181 2
        $this->values->foreach($function);
182 2
    }
183
184
    /**
185
     * Return a new map of pairs grouped by keys determined with the given
186
     * discriminator function
187
     *
188
     * @param callable(T) $discriminator
189
     *
190
     * @throws GroupEmptySequenceException
191
     *
192
     * @return Map<mixed, self<T>>
193
     */
194 3
    public function groupBy(callable $discriminator): Map
195
    {
196 3
        if ($this->size() === 0) {
197 1
            throw new GroupEmptySequenceException;
198
        }
199
200 2
        $map = null;
201
202 2
        foreach ($this->values->toArray() as $value) {
203 2
            $key = $discriminator($value);
204
205 2
            if ($map === null) {
206 2
                $map = new Map(
207 2
                    Type::determine($key),
208 2
                    self::class
209
                );
210
            }
211
212 2
            if ($map->contains($key)) {
213 2
                $map = $map->put(
214 2
                    $key,
215 2
                    $map->get($key)->add($value)
216
                );
217
            } else {
218 2
                $map = $map->put(
219 2
                    $key,
220 2
                    (new self($this->type))->add($value)
221
                );
222
            }
223
        }
224
225 2
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $map could return the type null which is incompatible with the type-hinted return Innmind\Immutable\Map. Consider adding an additional type-check to rule them out.
Loading history...
226
    }
227
228
    /**
229
     * Return the first element
230
     *
231
     * @return T
232
     */
233 2
    public function first()
234
    {
235 2
        return $this->values->first();
236
    }
237
238
    /**
239
     * Return the last element
240
     *
241
     * @return T
242
     */
243 2
    public function last()
244
    {
245 2
        return $this->values->last();
246
    }
247
248
    /**
249
     * Check if the stream contains the given element
250
     *
251
     * @param T $element
252
     */
253 53
    public function contains($element): bool
254
    {
255 53
        return $this->values->contains($element);
256
    }
257
258
    /**
259
     * Return the index for the given element
260
     *
261
     * @param T $element
262
     *
263
     * @throws ElementNotFoundException
264
     */
265 17
    public function indexOf($element): int
266
    {
267 17
        return $this->values->indexOf($element);
268
    }
269
270
    /**
271
     * Return the list of indices
272
     *
273
     * @return self<int>
274
     */
275 2
    public function indices(): self
276
    {
277 2
        return $this->values->indices();
278
    }
279
280
    /**
281
     * Return a new stream by applying the given function to all elements
282
     *
283
     * @param callable(T): T $function
284
     *
285
     * @return self<T>
286
     */
287 3
    public function map(callable $function): self
288
    {
289 3
        $self = clone $this;
290 3
        $self->values = $this->values->map($function);
291
        $self->values->foreach(function($element): void {
292 3
            $this->spec->validate($element);
293 3
        });
294
295 2
        return $self;
296
    }
297
298
    /**
299
     * Pad the stream to a defined size with the given element
300
     *
301
     * @param T $element
302
     *
303
     * @return self<T>
304
     */
305 2
    public function pad(int $size, $element): self
306
    {
307 2
        $this->spec->validate($element);
308
309 1
        $stream = clone $this;
310 1
        $stream->values = $this->values->pad($size, $element);
311
312 1
        return $stream;
313
    }
314
315
    /**
316
     * Return a stream of 2 streams partitioned according to the given predicate
317
     *
318
     * @param callable(T): bool $predicate
319
     *
320
     * @return Map<bool, self<T>>
321
     */
322 2
    public function partition(callable $predicate): Map
323
    {
324 2
        $truthy = [];
325 2
        $falsy = [];
326
327 2
        foreach ($this->values->toArray() as $value) {
328 2
            if ($predicate($value) === true) {
329 2
                $truthy[] = $value;
330
            } else {
331 2
                $falsy[] = $value;
332
            }
333
        }
334
335 2
        $true = $this->clear();
336 2
        $true->values = new Sequence(...$truthy);
337 2
        $false = $this->clear();
338 2
        $false->values = new Sequence(...$falsy);
339
340 2
        return Map::of('bool', self::class)
341 2
            (true, $true)
342 2
            (false, $false);
343
    }
344
345
    /**
346
     * Slice the stream
347
     *
348
     * @return self<T>
349
     */
350 3
    public function slice(int $from, int $until): self
351
    {
352 3
        $stream = clone $this;
353 3
        $stream->values = $this->values->slice($from, $until);
354
355 3
        return $stream;
356
    }
357
358
    /**
359
     * Split the stream in a stream of 2 streams splitted at the given position
360
     *
361
     * @throws OutOfBoundException
362
     *
363
     * @return self<self<T>>
364
     */
365 1
    public function splitAt(int $position): self
366
    {
367 1
        $stream = new self(self::class);
368 1
        $splitted = $this->values->splitAt($position);
369 1
        $first = new self($this->type);
370 1
        $second = new self($this->type);
371 1
        $first->values = $splitted->first();
372 1
        $second->values = $splitted->last();
373
374 1
        return $stream->add($first)->add($second);
375
    }
376
377
    /**
378
     * Return a stream with the n first elements
379
     *
380
     * @return self<T>
381
     */
382 4
    public function take(int $size): self
383
    {
384 4
        $stream = clone $this;
385 4
        $stream->values = $this->values->take($size);
386
387 4
        return $stream;
388
    }
389
390
    /**
391
     * Return a stream with the n last elements
392
     *
393
     * @return self<T>
394
     */
395 1
    public function takeEnd(int $size): self
396
    {
397 1
        $stream = clone $this;
398 1
        $stream->values = $this->values->takeEnd($size);
399
400 1
        return $stream;
401
    }
402
403
    /**
404
     * Append the given stream to the current one
405
     *
406
     * @param self<T> $stream
407
     *
408
     * @return self<T>
409
     */
410 7
    public function append(self $stream): self
411
    {
412 7
        $this->validate($stream);
413
414 6
        $self = clone $this;
415 6
        $self->values = $this->values->append(
416 6
            new Sequence(...$stream->toArray())
417
        );
418
419 6
        return $self;
420
    }
421
422
    /**
423
     * Return a stream with all elements from the current one that exist
424
     * in the given one
425
     *
426
     * @param self<T> $stream
427
     *
428
     * @return self<T>
429
     */
430 12
    public function intersect(self $stream): self
431
    {
432 12
        $this->validate($stream);
433
434 11
        $self = clone $this;
435 11
        $self->values = $this->values->intersect(
436 11
            new Sequence(...$stream->toArray())
437
        );
438
439 11
        return $self;
440
    }
441
442
    /**
443
     * Concatenate all elements with the given separator
444
     */
445 10
    public function join(string $separator): Str
446
    {
447 10
        return new Str((string) $this->values->join($separator));
448
    }
449
450
    /**
451
     * Add the given element at the end of the stream
452
     *
453
     * @param T $element
454
     *
455
     * @return self<T>
456
     */
457 101
    public function add($element): self
458
    {
459 101
        $this->spec->validate($element);
460
461 100
        $stream = clone $this;
462 100
        $stream->values = $this->values->add($element);
463
464 100
        return $stream;
465
    }
466
467
    /**
468
     * Sort the stream in a different order
469
     *
470
     * @param callable(T, T): int $function
471
     *
472
     * @return self<T>
473
     */
474 2
    public function sort(callable $function): self
475
    {
476 2
        $stream = clone $this;
477 2
        $stream->values = $this->values->sort($function);
478
479 2
        return $stream;
480
    }
481
482
    /**
483
     * Reduce the stream to a single value
484
     *
485
     * @param mixed $carry
486
     * @param callable(mixed, T) $reducer
487
     *
488
     * @return mixed
489
     */
490 6
    public function reduce($carry, callable $reducer)
491
    {
492 6
        return $this->values->reduce($carry, $reducer);
493
    }
494
495
    /**
496
     * Return a set of the same type but without any value
497
     *
498
     * @return self<T>
499
     */
500 12
    public function clear(): self
501
    {
502 12
        $self = clone $this;
503 12
        $self->values = new Sequence;
504
505 12
        return $self;
506
    }
507
508
    /**
509
     * Return the same stream but in reverse order
510
     *
511
     * @return self<T>
512
     */
513 2
    public function reverse(): self
514
    {
515 2
        $self = clone $this;
516 2
        $self->values = $this->values->reverse();
517
518 2
        return $self;
519
    }
520
521 3
    public function empty(): bool
522
    {
523 3
        return $this->values->empty();
524
    }
525
526
    /**
527
     * Make sure the stream is compatible with the current one
528
     *
529
     * @throws InvalidArgumentException
530
     */
531 26
    private function validate(self $stream): void
532
    {
533 26
        if (!$stream->isOfType($this->type)) {
534 3
            throw new InvalidArgumentException(
535 3
                'The 2 streams does not reference the same type'
536
            );
537
        }
538 23
    }
539
}
540