Passed
Push — 1.x ( e2fed3...0bef74 )
by Ulises Jeremias
02:56
created

Sequenceable   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 197
rs 10
c 0
b 0
f 0
wmc 24

11 Methods

Rating   Name   Duplication   Size   Complexity  
A reduce() 0 7 2
B join() 0 19 5
A slice() 0 4 1
A find() 0 5 3
A walk() 0 7 2
A concat() 0 11 1
A map() 0 10 2
A heapSort() 0 6 2
A filter() 0 14 3
A sort() 0 7 2
A copy() 0 3 1
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\CallbackHeap;
6
use Mbh\Iterator\SliceIterator;
7
use Mbh\Iterator\ConcatIterator;
8
use SplFixedArray;
9
use SplHeap;
10
use SplStack;
11
use LimitIterator;
12
use Iterator;
13
use ArrayAccess;
14
use Countable;
15
use CallbackFilterIterator;
16
use JsonSerializable;
17
use RuntimeException;
18
use Traversable;
19
use ReflectionClass;
20
21
/**
22
 * MBHFramework
23
 *
24
 * @link      https://github.com/MBHFramework/mbh-framework
25
 * @copyright Copyright (c) 2017 Ulises Jeremias Cornejo Fandos
26
 * @license   https://github.com/MBHFramework/mbh-framework/blob/master/LICENSE (MIT License)
27
 */
28
29
trait Sequenceable
30
{
31
    use Collection;
32
    use Sort {
33
        Sort::heapSort as heapSortWithCallback;
34
    }
35
36
    /**
37
     * Map elements to a new Sequenceable via a callback
38
     *
39
     * @param callable $callback Function to map new data
40
     * @return Sequenceable
41
     */
42
    public function map(callable $callback): SequenceableInterface
43
    {
44
        $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

44
        $count = count(/** @scrutinizer ignore-type */ $this);
Loading history...
45
        $sfa = new SplFixedArray($count);
46
47
        for ($i = 0; $i < $count; $i++) {
48
            $sfa[$i] = $callback($this[$i], $i, $this);
49
        }
50
51
        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

51
        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...
52
    }
53
54
    /**
55
     * forEach, or "walk" the data
56
     * Exists primarily to provide a consistent interface, though it's seldom
57
     * any better than a simple php foreach. Mainly useful for chaining.
58
     * Named walk for historic reasons - forEach is reserved in PHP
59
     *
60
     * @param callable $callback Function to call on each element
61
     * @return Sequenceable
62
     */
63
    public function walk(callable $callback): SequenceableInterface
64
    {
65
        foreach ($this as $i => $elem) {
66
            $callback($elem, $i, $this);
67
        }
68
69
        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...
70
    }
71
72
    /**
73
     * Filter out elements
74
     *
75
     * @param callable $callback Function to filter out on false
76
     * @return Sequenceable
77
     */
78
    public function filter(callable $callback): SequenceableInterface
79
    {
80
        $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

80
        $count = count(/** @scrutinizer ignore-type */ $this);
Loading history...
81
        $sfa = new SplFixedArray($count);
82
        $newCount = 0;
83
84
        foreach ($this as $elem) {
85
            if ($callback($elem)) {
86
                $sfa[$newCount++] = $elem;
87
            }
88
        }
89
90
        $sfa->setSize($newCount);
91
        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

91
        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...
92
    }
93
94
    /**
95
     * Reduce to a single value
96
     *
97
     * @param callable $callback Callback(
98
     *     mixed $previous, mixed $current[, mixed $index, mixed $immArray]
99
     * ):mixed Callback to run reducing function
100
     * @param mixed $accumulator Initial value for first argument
101
     */
102
    public function reduce(callable $callback, $accumulator = null)
103
    {
104
        foreach ($this as $i => $elem) {
105
            $accumulator = $callback($accumulator, $elem, $i, $this);
106
        }
107
108
        return $accumulator;
109
    }
110
111
    /**
112
     * Join a set of strings together.
113
     *
114
     * @param string $token Main token to put between elements
115
     * @param string $secondToken If set, $token on left $secondToken on right
116
     * @return string
117
     */
118
    public function join(string $token = ',', string $secondToken = null): string
119
    {
120
        $str = "";
121
        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...
122
            foreach ($this as $i => $elem) {
123
                $str .= $token . (string) $elem . $secondToken;
124
            }
125
        } else {
126
            $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

126
            $this->/** @scrutinizer ignore-call */ 
127
                   rewind();
Loading history...
127
            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

127
            while ($this->/** @scrutinizer ignore-call */ valid()) {
Loading history...
128
                $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

128
                $str .= (string) $this->/** @scrutinizer ignore-call */ current();
Loading history...
129
                $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

129
                $this->/** @scrutinizer ignore-call */ 
130
                       next();
Loading history...
130
                if ($this->valid()) {
131
                    $str .= $token;
132
                }
133
            }
134
        }
135
136
        return $str;
137
    }
138
139
    /**
140
     * Take a slice of the array
141
     *
142
     * @param int $begin Start index of slice
143
     * @param int $end End index of slice
144
     * @return Sequenceable
145
     */
146
    public function slice(int $begin = 0, int $end = null): SequenceableInterface
147
    {
148
        $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

148
        $it = new SliceIterator(/** @scrutinizer ignore-type */ $this, $begin, $end);
Loading history...
149
        return new static($it);
0 ignored issues
show
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

149
        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...
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...
150
    }
151
152
    /**
153
     * Concat to the end of this array
154
     *
155
     * @param Traversable,...
156
     * @return Sequenceable
157
     */
158
    public function concat(): SequenceableInterface
159
    {
160
        $args = func_get_args();
161
        array_unshift($args, $this);
162
163
        // Concat this iterator, and variadic args
164
        $class = new ReflectionClass('Mbh\Iterator\ConcatIterator');
165
        $concatIt = $class->newInstanceArgs($args);
166
167
        // Create as new immutable's iterator
168
        return new static($concatIt);
0 ignored issues
show
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

168
        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...
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...
169
    }
170
171
    /**
172
     * Find a single element
173
     *
174
     * @param callable $callback The test to run on each element
175
     * @return mixed The element we found
176
     */
177
    public function find(callable $callback)
178
    {
179
        foreach ($this as $i => $elem) {
180
            if ($callback($elem, $i, $this)) {
181
                return $elem;
182
            }
183
        }
184
    }
185
186
    /**
187
     * Return a new sorted Sequenceable
188
     *
189
     * @param callable $callback The sort callback
190
     * @return Sequenceable
191
     */
192
    public function sort(callable $callback = null)
193
    {
194
        if ($callback) {
195
            return $this->mergeSort($callback);
196
        }
197
198
        return $this->arraySort();
199
    }
200
201
    /**
202
     * Sort a new Sequenceable by filtering through a heap.
203
     * Tends to run much faster than array or merge sorts, since you're only
204
     * sorting the pointers, and the sort function is running in a highly
205
     * optimized space.
206
     *
207
     * @param SplHeap $heap The heap to run for sorting
208
     * @return Sequenceable
209
     */
210
    public function heapSort(SplHeap $heap): SequenceableInterface
211
    {
212
        foreach ($this as $item) {
213
            $heap->insert($item);
214
        }
215
        return static::fromItems($heap);
216
    }
217
218
    /**
219
     * Creates a shallow copy of the collection.
220
     *
221
     * @return CollectionInterface a shallow copy of the collection.
222
     */
223
    public function copy(): CollectionInterface
224
    {
225
        return static::fromArray($this->toArray());
226
    }
227
}
228