Passed
Push — 1.x ( 1de473...d64718 )
by Ulises Jeremias
02:40
created

Sequenceable::push()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php namespace Mbh\Collection\Traits;
2
3
use Mbh\Collection\Interfaces\Collection as CollectionInterface;
4
use Mbh\Collection\Interfaces\Sequenceable as SequenceableInterface;
5
use Mbh\Collection\FixedArray;
6
use Mbh\Collection\CallbackHeap;
7
use Mbh\Iterator\SliceIterator;
8
use Mbh\Iterator\ConcatIterator;
9
use SplFixedArray;
10
use SplHeap;
11
use SplStack;
12
use LimitIterator;
13
use Iterator;
14
use ArrayAccess;
15
use Countable;
16
use CallbackFilterIterator;
17
use JsonSerializable;
18
use RuntimeException;
19
use Traversable;
20
use ReflectionClass;
21
use UnderflowException;
22
use OverflowException;
23
24
/**
25
 * MBHFramework
26
 *
27
 * @link      https://github.com/MBHFramework/mbh-framework
28
 * @copyright Copyright (c) 2017 Ulises Jeremias Cornejo Fandos
29
 * @license   https://github.com/MBHFramework/mbh-framework/blob/master/LICENSE (MIT License)
30
 */
31
32
trait Sequenceable
33
{
34
    use Collection;
35
    use Sort {
36
        Sort::heapSort as heapSortWithCallback;
37
        Sort::heapSorted as heapSortedWithCallback;
38
    }
39
40
    /**
41
     * @inheritDoc
42
     */
43
    public static function fromItems(Traversable $array): SequenceableInterface
44
    {
45
        // We can only do it this way if we can count it
46
        if ($array instanceof Countable) {
47
            $sfa = new SplFixedArray(count($array));
48
49
            foreach ($array as $i => $elem) {
50
                $sfa[$i] = $elem;
51
            }
52
53
            return new static($sfa);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static($sfa) returns the type Mbh\Collection\Traits\Sequenceable which is incompatible with the type-hinted return Mbh\Collection\Interfaces\Sequenceable.
Loading history...
Unused Code introduced by
The call to Mbh\Collection\Traits\Sequenceable::__construct() has too many arguments starting with $sfa. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

53
            return /** @scrutinizer ignore-call */ new static($sfa);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
54
        }
55
56
        // If we can't count it, it's simplest to iterate into an array first
57
        return static::fromArray(iterator_to_array($array));
58
    }
59
60
    /**
61
     * @inheritDoc
62
     */
63
    public static function fromArray(array $array): SequenceableInterface
64
    {
65
        return new static(SplFixedArray::fromArray($array));
0 ignored issues
show
Unused Code introduced by
The call to Mbh\Collection\Traits\Sequenceable::__construct() has too many arguments starting with SplFixedArray::fromArray($array). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

65
        return /** @scrutinizer ignore-call */ new static(SplFixedArray::fromArray($array));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug Best Practice introduced by
The expression return new static(SplFix...ray::fromArray($array)) returns the type Mbh\Collection\Traits\Sequenceable which is incompatible with the type-hinted return Mbh\Collection\Interfaces\Sequenceable.
Loading history...
66
    }
67
68
    /**
69
     * @inheritDoc
70
     */
71
    public function copy(): CollectionInterface
72
    {
73
        return static::fromArray($this->toArray());
74
    }
75
76
    /**
77
     * @inheritDoc
78
     */
79
    public function contains(...$values): bool
80
    {
81
        foreach ($values as $value) {
82
            if (!$this->find($value)) {
83
                return false;
84
            }
85
        }
86
87
        return true;
88
    }
89
90
    /**
91
    * @inheritDoc
92
    */
93
    public function first()
94
    {
95
        if ($this->isEmpty()) {
96
            throw new UnderflowException();
97
        }
98
99
        return $this[0];
100
    }
101
102
    /**
103
     * @inheritDoc
104
     */
105
    public function get(int $index)
106
    {
107
        if (! $this->validIndex($index)) {
0 ignored issues
show
Bug introduced by
It seems like validIndex() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

107
        if (! $this->/** @scrutinizer ignore-call */ validIndex($index)) {
Loading history...
108
            throw new OutOfRangeException();
0 ignored issues
show
Bug introduced by
The type Mbh\Collection\Traits\OutOfRangeException was not found. Did you mean OutOfRangeException? If so, make sure to prefix the type with \.
Loading history...
109
        }
110
111
        return $this[$index];
112
    }
113
114
    /**
115
     * @inheritDoc
116
     */
117
    public function insert(int $index, ...$values)
0 ignored issues
show
Unused Code introduced by
The parameter $values is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

117
    public function insert(int $index, /** @scrutinizer ignore-unused */ ...$values)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
118
    {
119
        if (! $this->validIndex($index) && $index !== count($this)) {
0 ignored issues
show
Bug introduced by
$this of type Mbh\Collection\Traits\Sequenceable is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

119
        if (! $this->validIndex($index) && $index !== count(/** @scrutinizer ignore-type */ $this)) {
Loading history...
120
            throw new OutOfRangeException();
121
        }
122
123
        // next implementation
124
    }
125
126
    /**
127
     * @inheritDoc
128
     */
129
    public function last()
130
    {
131
        if ($this->isEmpty()) {
132
            throw new UnderflowException();
133
        }
134
135
        return $this[count($this) - 1];
0 ignored issues
show
Bug introduced by
$this of type Mbh\Collection\Traits\Sequenceable is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

135
        return $this[count(/** @scrutinizer ignore-type */ $this) - 1];
Loading history...
136
    }
137
138
    /**
139
     * @inheritDoc
140
     */
141
    public function pop()
142
    {
143
        if ($this->isEmpty()) {
144
            throw new UnderflowException();
145
        }
146
147
        // next impplementation
148
    }
149
150
    /**
151
     * Pushes all values of either an array or traversable object.
152
     */
153
    private function pushAll($values)
154
    {
155
        foreach ($values as $value) {
156
            $this[] = $value;
157
        }
158
159
        $this->checkCapacity();
0 ignored issues
show
Bug introduced by
It seems like checkCapacity() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

159
        $this->/** @scrutinizer ignore-call */ 
160
               checkCapacity();
Loading history...
160
    }
161
162
    /**
163
     * @inheritDoc
164
     */
165
    public function push(...$values)
166
    {
167
        $this->pushAll($values);
168
    }
169
170
    /**
171
     * @inheritDoc
172
     */
173
    public function map(callable $callback): SequenceableInterface
174
    {
175
        $count = count($this);
0 ignored issues
show
Bug introduced by
$this of type Mbh\Collection\Traits\Sequenceable is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

175
        $count = count(/** @scrutinizer ignore-type */ $this);
Loading history...
176
        $sfa = new SplFixedArray($count);
177
178
        for ($i = 0; $i < $count; $i++) {
179
            $sfa[$i] = $callback($this[$i], $i, $this);
180
        }
181
182
        return new static($sfa);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static($sfa) returns the type Mbh\Collection\Traits\Sequenceable which is incompatible with the type-hinted return Mbh\Collection\Interfaces\Sequenceable.
Loading history...
Unused Code introduced by
The call to Mbh\Collection\Traits\Sequenceable::__construct() has too many arguments starting with $sfa. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

182
        return /** @scrutinizer ignore-call */ new static($sfa);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
183
    }
184
185
    /**
186
     * @inheritDoc
187
     */
188
    public function walk(callable $callback): SequenceableInterface
189
    {
190
        foreach ($this as $i => $elem) {
191
            $callback($elem, $i, $this);
192
        }
193
194
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Mbh\Collection\Traits\Sequenceable which is incompatible with the type-hinted return Mbh\Collection\Interfaces\Sequenceable.
Loading history...
195
    }
196
197
    /**
198
     * @inheritDoc
199
     */
200
    public function filter(callable $callback): SequenceableInterface
201
    {
202
        $count = count($this);
0 ignored issues
show
Bug introduced by
$this of type Mbh\Collection\Traits\Sequenceable is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

202
        $count = count(/** @scrutinizer ignore-type */ $this);
Loading history...
203
        $sfa = new SplFixedArray($count);
204
        $newCount = 0;
205
206
        foreach ($this as $elem) {
207
            if ($callback($elem)) {
208
                $sfa[$newCount++] = $elem;
209
            }
210
        }
211
212
        $sfa->setSize($newCount);
213
        return new static($sfa);
0 ignored issues
show
Unused Code introduced by
The call to Mbh\Collection\Traits\Sequenceable::__construct() has too many arguments starting with $sfa. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

213
        return /** @scrutinizer ignore-call */ new static($sfa);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug Best Practice introduced by
The expression return new static($sfa) returns the type Mbh\Collection\Traits\Sequenceable which is incompatible with the type-hinted return Mbh\Collection\Interfaces\Sequenceable.
Loading history...
214
    }
215
216
    /**
217
     * @inheritDoc
218
     */
219
    public function reduce(callable $callback, $accumulator = null)
220
    {
221
        foreach ($this as $i => $elem) {
222
            $accumulator = $callback($accumulator, $elem, $i, $this);
223
        }
224
225
        return $accumulator;
226
    }
227
228
    /**
229
     * @inheritDoc
230
     */
231
    public function join(string $token = ',', string $secondToken = null): string
232
    {
233
        $str = "";
234
        if ($secondToken) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $secondToken of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
235
            foreach ($this as $i => $elem) {
236
                $str .= $token . (string) $elem . $secondToken;
237
            }
238
        } else {
239
            $this->rewind();
0 ignored issues
show
Bug introduced by
It seems like rewind() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

239
            $this->/** @scrutinizer ignore-call */ 
240
                   rewind();
Loading history...
240
            while ($this->valid()) {
0 ignored issues
show
Bug introduced by
It seems like valid() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

240
            while ($this->/** @scrutinizer ignore-call */ valid()) {
Loading history...
241
                $str .= (string) $this->current();
0 ignored issues
show
Bug introduced by
It seems like current() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

241
                $str .= (string) $this->/** @scrutinizer ignore-call */ current();
Loading history...
242
                $this->next();
0 ignored issues
show
Bug introduced by
It seems like next() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

242
                $this->/** @scrutinizer ignore-call */ 
243
                       next();
Loading history...
243
                if ($this->valid()) {
244
                    $str .= $token;
245
                }
246
            }
247
        }
248
249
        return $str;
250
    }
251
252
    /**
253
     * @inheritDoc
254
     */
255
    public function slice(int $begin = 0, int $end = null): SequenceableInterface
256
    {
257
        $it = new SliceIterator($this, $begin, $end);
0 ignored issues
show
Bug introduced by
$this of type Mbh\Collection\Traits\Sequenceable is incompatible with the type Iterator expected by parameter $iterator of Mbh\Iterator\SliceIterator::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

257
        $it = new SliceIterator(/** @scrutinizer ignore-type */ $this, $begin, $end);
Loading history...
258
        return new static($it);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static($it) returns the type Mbh\Collection\Traits\Sequenceable which is incompatible with the type-hinted return Mbh\Collection\Interfaces\Sequenceable.
Loading history...
Unused Code introduced by
The call to Mbh\Collection\Traits\Sequenceable::__construct() has too many arguments starting with $it. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

258
        return /** @scrutinizer ignore-call */ new static($it);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
259
    }
260
261
    /**
262
     * @inheritDoc
263
     */
264
    public function concat(): SequenceableInterface
265
    {
266
        $args = func_get_args();
267
        array_unshift($args, $this);
268
269
        // Concat this iterator, and variadic args
270
        $class = new ReflectionClass('Mbh\Iterator\ConcatIterator');
271
        $concatIt = $class->newInstanceArgs($args);
272
273
        // Create as new immutable's iterator
274
        return new static($concatIt);
0 ignored issues
show
Bug Best Practice introduced by
The expression return new static($concatIt) returns the type Mbh\Collection\Traits\Sequenceable which is incompatible with the type-hinted return Mbh\Collection\Interfaces\Sequenceable.
Loading history...
Unused Code introduced by
The call to Mbh\Collection\Traits\Sequenceable::__construct() has too many arguments starting with $concatIt. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

274
        return /** @scrutinizer ignore-call */ new static($concatIt);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
275
    }
276
277
    /**
278
     * @inheritDoc
279
     */
280
    public function find(callable $callback)
281
    {
282
        foreach ($this as $i => $elem) {
283
            if ($callback($elem, $i, $this)) {
284
                return $elem;
285
            }
286
        }
287
    }
288
289
    /**
290
     * @inheritDoc
291
     */
292
    public function sort(callable $callback = null): SequenceableInterface
293
    {
294
        if ($callback) {
295
            return $this->mergeSort($callback);
296
        }
297
298
        return $this->arraySort();
299
    }
300
301
    /**
302
     * @inheritDoc
303
     */
304
    public function sorted(callable $callback = null): SequenceableInterface
305
    {
306
        $copy = FixedArray::fromItems($this);
0 ignored issues
show
Bug introduced by
$this of type Mbh\Collection\Traits\Sequenceable is incompatible with the type Traversable expected by parameter $array of Mbh\Collection\FixedArray::fromItems(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

306
        $copy = FixedArray::fromItems(/** @scrutinizer ignore-type */ $this);
Loading history...
307
308
        if ($callback) {
309
            $copy->mergeSort($callback);
310
        }
311
312
        $copy->arraySort();
313
314
        return static::fromItems($copy);
315
    }
316
317
    /**
318
     * @inheritDoc
319
     */
320
    public function heapSorted(SplHeap $heap): SequenceableInterface
321
    {
322
        return $this->copy()->heapSort($heap);
323
    }
324
325
    /**
326
     * @inheritDoc
327
     */
328
    public function heapSort(SplHeap $heap): SequenceableInterface
329
    {
330
        foreach ($this as $item) {
331
            $heap->insert($item);
332
        }
333
334
        $this->setTraversable(static::fromItems($heap));
335
336
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Mbh\Collection\Traits\Sequenceable which is incompatible with the type-hinted return Mbh\Collection\Interfaces\Sequenceable.
Loading history...
337
    }
338
339
    abstract protected function setTraversable(Traversable $traversable);
340
}
341