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.

Traversable::indexBy()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 12
rs 9.4285
cc 1
eloc 7
nc 1
nop 1
1
<?php
2
3
namespace Pinq;
4
5
use Pinq\Iterators\IIteratorScheme;
6
7
/**
8
 * The standard traversable class, fully implements the traversable API
9
 * using iterators to achieve lazy evaluation
10
 *
11
 * @author Elliot Levin <[email protected]>
12
 */
13
class Traversable implements ITraversable, Interfaces\IOrderedTraversable
14
{
15
    /**
16
     * The iterator scheme used in the traversable instance.
17
     *
18
     * @var IIteratorScheme
19
     */
20
    protected $scheme;
21
22
    /**
23
     * The source traversable.
24
     *
25
     * @var Traversable|null
26
     */
27
    protected $source;
28
29
    /**
30
     * The element iterator for the traversable.
31
     *
32
     * @var \Traversable
33
     */
34
    protected $elements;
35
36
    public function __construct($elements = [], IIteratorScheme $scheme = null, Traversable $source = null)
37
    {
38
        $this->scheme   = $scheme ?: Iterators\SchemeProvider::getDefault();
39
        $this->source   = $source;
40
        $this->elements = $this->scheme->toIterator($elements);
41
    }
42
43
    /**
44
     * Constructs a new traversable object from the supplied elements.
45
     *
46
     * @param array|\Traversable   $elements
47
     * @param IIteratorScheme|null $scheme
48
     * @param Traversable|null     $source
49
     *
50
     * @return ITraversable
51
     */
52
    public static function from($elements, IIteratorScheme $scheme = null, Traversable $source = null)
53
    {
54
        return new static($elements, $scheme, $source);
55
    }
56
57
    /**
58
     * Returns a callable for the traversable constructor.
59
     *
60
     * @param IIteratorScheme|null $scheme
61
     * @param Traversable|null     $source
62
     *
63
     * @return callable
64
     */
65
    public static function factory(IIteratorScheme $scheme = null, Traversable $source = null)
66
    {
67
        //static:: doesn't work in closures?
68
        $static = get_called_class();
69
70
        return function ($elements) use ($static, $scheme, $source) {
71
            return $static::from($elements, $scheme, $source);
72
        };
73
    }
74
75
    /**
76
     * Returns a callable factory to construct an equivalent
77
     * instance with the supplied elements.
78
     *
79
     * @return callable
80
     */
81
    final protected function scopedSelfFactory()
82
    {
83
        return function ($elements) {
84
            return $this->constructScopedSelf($elements);
85
        };
86
    }
87
88
    /**
89
     * Returns a new instance of the traversable with the scoped elements
90
     * and same scheme and source.
91
     *
92
     * @param array|\Traversable $elements
93
     *
94
     * @return static
95
     */
96
    protected function constructScopedSelf($elements)
97
    {
98
        return static::from($elements, $this->scheme, $this->source ?: $this);
99
    }
100
101
    public function isSource()
102
    {
103
        return $this->source === null;
104
    }
105
106
    public function getSource()
107
    {
108
        return $this->source ?: $this;
109
    }
110
111
    public function asArray()
112
    {
113
        return $this->scheme->toArray($this->elements);
114
    }
115
116
    public function getIterator()
117
    {
118
        return $this->scheme->arrayCompatibleIterator($this->getTrueIterator());
119
    }
120
121
    public function getTrueIterator()
122
    {
123
        return $this->elements;
124
    }
125
126
    public function getIteratorScheme()
127
    {
128
        return $this->scheme;
129
    }
130
131
    public function asTraversable()
132
    {
133
        return $this;
134
    }
135
136
    public function asCollection()
137
    {
138
        return new Collection($this->elements, $this->scheme);
139
    }
140
141
    /**
142
     * @return Iterators\IOrderedMap
143
     */
144
    protected function asOrderedMap()
145
    {
146
        return $this->elements instanceof Iterators\IOrderedMap ?
147
                $this->elements : $this->scheme->createOrderedMap($this->elements);
148
    }
149
150
    public function iterate(callable $function)
151
    {
152
        $this->scheme->walk($this->elements, $function);
153
    }
154
155
    // <editor-fold defaultstate="collapsed" desc="Querying">
156
157
    public function first()
158
    {
159
        foreach ($this->elements as $value) {
160
            return $value;
161
        }
162
163
        return null;
164
    }
165
166
    public function last()
167
    {
168
        $value = null;
169
170
        foreach ($this->elements as $value) {
171
172
        }
173
174
        return $value;
175
    }
176
177
    public function where(callable $predicate)
178
    {
179
        return $this->constructScopedSelf(
180
                $this->scheme->filterIterator(
181
                        $this->elements,
182
                        $predicate
183
                )
184
        );
185
    }
186
187
    public function orderByAscending(callable $function)
188
    {
189
        return $this->constructScopedSelf(
190
                $this->scheme->orderedIterator(
191
                        $this->elements,
192
                        $function,
193
                        true
194
                )
195
        );
196
    }
197
198
    public function orderByDescending(callable $function)
199
    {
200
        return $this->constructScopedSelf(
201
                $this->scheme->orderedIterator(
202
                        $this->elements,
203
                        $function,
204
                        false
205
                )
206
        );
207
    }
208
209
    public function orderBy(callable $function, $direction)
210
    {
211
        return $direction === Direction::DESCENDING ?
212
                $this->orderByDescending($function) : $this->orderByAscending($function);
213
    }
214
215
    /**
216
     * Verifies that the traversable is ordered.
217
     *
218
     * @param string $method The called method name
219
     *
220
     * @return Iterators\IOrderedIterator
221
     * @throws PinqException
222
     */
223
    private function validateIsOrdered($method)
224
    {
225
        $innerIterator = $this->elements;
226
        if (!($innerIterator instanceof Iterators\IOrderedIterator)) {
227
            throw new PinqException(
228
                    'Invalid call to %s: %s::%s must be called first.',
229
                    $method,
230
                    __CLASS__,
231
                    'orderBy');
232
        }
233
234
        return $innerIterator;
235
    }
236
237
    public function thenBy(callable $function, $direction)
238
    {
239
        return $this->constructScopedSelf(
240
                $this->validateIsOrdered(__METHOD__)->thenOrderBy(
241
                        $function,
242
                        $direction !== Direction::DESCENDING
243
                )
244
        );
245
    }
246
247
    public function thenByAscending(callable $function)
248
    {
249
        return $this->constructScopedSelf(
250
                $this->validateIsOrdered(__METHOD__)
251
                        ->thenOrderBy($function, true)
252
        );
253
    }
254
255
    public function thenByDescending(callable $function)
256
    {
257
        return $this->constructScopedSelf(
258
                $this->validateIsOrdered(__METHOD__)
259
                        ->thenOrderBy($function, false)
260
        );
261
    }
262
263
    public function skip($amount)
264
    {
265
        return $this->constructScopedSelf(
266
                $this->scheme->rangeIterator(
267
                        $this->elements,
268
                        $amount,
269
                        null
270
                )
271
        );
272
    }
273
274
    public function take($amount)
275
    {
276
        return $this->constructScopedSelf(
277
                $this->scheme->rangeIterator(
278
                        $this->elements,
279
                        0,
280
                        $amount
281
                )
282
        );
283
    }
284
285
    public function slice($start, $amount)
286
    {
287
        return $this->constructScopedSelf(
288
                $this->scheme->rangeIterator(
289
                        $this->elements,
290
                        $start,
291
                        $amount
292
                )
293
        );
294
    }
295
296
    public function indexBy(callable $function)
297
    {
298
        return $this->constructScopedSelf(
299
                $this->scheme->uniqueKeyIterator(
300
                        $this->scheme->projectionIterator(
301
                                $this->elements,
302
                                $function,
303
                                null
304
                        )
305
                )
306
        );
307
    }
308
309 View Code Duplication
    public function keys()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
310
    {
311
        return $this->constructScopedSelf(
312
                $this->scheme->reindexerIterator(
313
                        $this->scheme->projectionIterator(
314
                                $this->elements,
315
                                null,
316
                                function ($value, $key) {
317
                                    return $key;
318
                                }
319
                        )
320
                )
321
        );
322
    }
323
324
    public function reindex()
325
    {
326
        return $this->constructScopedSelf(
327
                $this->scheme->reindexerIterator($this->elements)
328
        );
329
    }
330
331
    public function groupBy(callable $function)
332
    {
333
        return $this->constructScopedSelf(
334
                $this->scheme->groupedIterator(
335
                        $this->elements,
336
                        $function,
337
                        $this->scopedSelfFactory()
338
                )
339
        );
340
    }
341
342 View Code Duplication
    public function join($values)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
343
    {
344
        return new Connectors\JoiningTraversable(
345
                $this->scheme,
346
                $this->scheme->joinIterator(
347
                        $this->elements,
348
                        $this->scheme->toIterator($values)
349
                ),
350
                $this->scopedSelfFactory());
351
    }
352
353 View Code Duplication
    public function groupJoin($values)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
354
    {
355
        return new Connectors\JoiningTraversable(
356
                $this->scheme,
357
                $this->scheme->groupJoinIterator(
358
                        $this->elements,
359
                        $this->scheme->toIterator($values),
360
                        $this->scopedSelfFactory()
361
                ),
362
                $this->scopedSelfFactory());
363
    }
364
365
    public function unique()
366
    {
367
        return $this->constructScopedSelf($this->scheme->uniqueIterator($this->elements));
368
    }
369
370
    public function select(callable $function)
371
    {
372
        return $this->constructScopedSelf(
373
                $this->scheme->projectionIterator(
374
                        $this->elements,
375
                        null,
376
                        $function
377
                )
378
        );
379
    }
380
381 View Code Duplication
    public function selectMany(callable $function)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
382
    {
383
        $projectionIterator =
384
                $this->scheme->projectionIterator(
385
                        $this->elements,
386
                        null,
387
                        $function
388
                );
389
390
        return $this->constructScopedSelf($this->scheme->flattenedIterator($projectionIterator));
391
    }
392
393
    // </editor-fold>
394
395
    // <editor-fold defaultstate="collapsed" desc="Set Operations">
396
397
    public function union($values)
398
    {
399
        return $this->constructScopedSelf(
400
                $this->scheme->unionIterator(
401
                        $this->elements,
402
                        $this->scheme->toIterator($values)
403
                )
404
        );
405
    }
406
407
    public function intersect($values)
408
    {
409
        return $this->constructScopedSelf(
410
                $this->scheme->intersectionIterator(
411
                        $this->elements,
412
                        $this->scheme->toIterator($values)
413
                )
414
        );
415
    }
416
417
    public function difference($values)
418
    {
419
        return $this->constructScopedSelf(
420
                $this->scheme->differenceIterator(
421
                        $this->elements,
422
                        $this->scheme->toIterator($values)
423
                )
424
        );
425
    }
426
427
    // </editor-fold>
428
429
    // <editor-fold defaultstate="collapsed" desc="Multiset Operations">
430
431
    public function append($values)
432
    {
433
        return $this->constructScopedSelf(
434
                $this->scheme->appendIterator(
435
                        $this->elements,
436
                        $this->scheme->toIterator($values)
437
                )
438
        );
439
    }
440
441
    public function whereIn($values)
442
    {
443
        return $this->constructScopedSelf(
444
                $this->scheme->whereInIterator(
445
                        $this->elements,
446
                        $this->scheme->toIterator($values)
447
                )
448
        );
449
    }
450
451
    public function except($values)
452
    {
453
        return $this->constructScopedSelf(
454
                $this->scheme->exceptIterator(
455
                        $this->elements,
456
                        $this->scheme->toIterator($values)
457
                )
458
        );
459
    }
460
461
    // </editor-fold>
462
463
    // <editor-fold defaultstate="collapsed" desc="Array Access">
464
465
    public function offsetExists($index)
466
    {
467
        foreach ($this->keys() as $key) {
468
            if ($key === $index) {
469
                return true;
470
            }
471
        }
472
473
        return false;
474
    }
475
476
    public function offsetGet($index)
477
    {
478
        foreach ($this->select(function ($value, $key) { return [$key, $value]; }) as $element) {
479
            if ($element[0] === $index) {
480
                return $element[1];
481
            }
482
        }
483
484
        return false;
485
    }
486
487
    public function offsetSet($index, $value)
488
    {
489
        throw PinqException::notSupported(__METHOD__);
490
    }
491
492
    public function offsetUnset($index)
493
    {
494
        throw PinqException::notSupported(__METHOD__);
495
    }
496
497
    // </editor-fold>
498
499
    // <editor-fold defaultstate="collapsed" desc="Aggregates">
500
501
    public function count()
502
    {
503
        if($this->elements instanceof \Countable) {
504
            return $this->elements->count();
505
        }
506
507
        $count = 0;
508
509
        foreach($this->elements as $value) {
510
            $count++;
511
        }
512
513
        return $count;
514
    }
515
516
    public function isEmpty()
517
    {
518
        foreach ($this->elements as $value) {
519
            return false;
520
        }
521
522
        return true;
523
    }
524
525
    public function contains($value)
526
    {
527
        foreach ($this->elements as $containedValue) {
528
            if ($containedValue === $value) {
529
                return true;
530
            }
531
        }
532
533
        return false;
534
    }
535
536
    public function aggregate(callable $function)
537
    {
538
        $hasValue       = false;
539
        $aggregateValue = null;
540
541
        foreach ($this->elements as $value) {
542
            if (!$hasValue) {
543
                $aggregateValue = $value;
544
                $hasValue       = true;
545
                continue;
546
            }
547
548
            $aggregateValue = $function($aggregateValue, $value);
549
        }
550
551
        return $aggregateValue;
552
    }
553
554
    private function mapIterator(callable $function = null)
555
    {
556
        if ($function === null) {
557
            return $this->elements;
558
        } else {
559
            return $this->scheme->projectionIterator(
560
                    $this->elements,
561
                    null,
562
                    $function
563
            );
564
        }
565
    }
566
567 View Code Duplication
    public function maximum(callable $function = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
568
    {
569
        $max = null;
570
571
        foreach ($this->mapIterator($function) as $value) {
572
            if ($value > $max) {
573
                $max = $value;
574
            }
575
        }
576
577
        return $max;
578
    }
579
580
    public function minimum(callable $function = null)
581
    {
582
        $min = null;
583
        $first = true;
584
585
        foreach ($this->mapIterator($function) as $value) {
586
            if ($value < $min || $first) {
587
                $min   = $value;
588
                $first = false;
589
            }
590
        }
591
592
        return $min;
593
    }
594
595 View Code Duplication
    public function sum(callable $function = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
596
    {
597
        $sum = null;
598
599
        foreach ($this->mapIterator($function) as $value) {
600
            $sum += $value;
601
        }
602
603
        return $sum;
604
    }
605
606
    public function average(callable $function = null)
607
    {
608
        $sum = null;
609
        $count = 0;
610
611
        foreach ($this->mapIterator($function) as $value) {
612
            $sum += $value;
613
            $count++;
614
        }
615
616
        return $count === 0 ? null : $sum / $count;
617
    }
618
619
    public function all(callable $function = null)
620
    {
621
        foreach ($this->mapIterator($function) as $value) {
622
            if (!$value) {
623
                return false;
624
            }
625
        }
626
627
        return true;
628
    }
629
630
    public function any(callable $function = null)
631
    {
632
        foreach ($this->mapIterator($function) as $value) {
633
            if ($value) {
634
                return true;
635
            }
636
        }
637
638
        return false;
639
    }
640
641
    public function implode($delimiter, callable $function = null)
642
    {
643
        $string = '';
644
645
        foreach ($this->mapIterator($function) as $value) {
646
            $string .= $delimiter . $value;
647
        }
648
649
        return $string === '' ? '' : substr($string, strlen($delimiter));
650
    }
651
652
    // </editor-fold>
653
}
654