1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Pinq\Iterators\Generators; |
4
|
|
|
|
5
|
|
|
use Pinq\Iterators\Common; |
6
|
|
|
use Pinq\Iterators\Standard\IIterator; |
7
|
|
|
|
8
|
|
|
/** |
9
|
|
|
* Iterator scheme using rewindable generator implementations. |
10
|
|
|
* Compatible with >= PHP 5.5.0. |
11
|
|
|
* |
12
|
|
|
* @author Elliot Levin <[email protected]> |
13
|
|
|
*/ |
14
|
|
|
class GeneratorScheme extends Common\IteratorScheme |
15
|
|
|
{ |
16
|
|
|
public static function compatibleWith($phpVersion) |
17
|
|
|
{ |
18
|
|
|
// HHVM does not support foreach by reference on iterators. |
19
|
|
|
// This is used extensively by the generator classes, |
20
|
|
|
// hence fallback to the standard iterator scheme. |
21
|
|
|
return version_compare($phpVersion, '5.5.0', '>=') |
22
|
|
|
&& strpos($phpVersion, 'hhvm') === false |
23
|
|
|
&& strpos($phpVersion, 'hiphop') === false; |
24
|
|
|
} |
25
|
|
|
|
26
|
|
|
public function createOrderedMap(\Traversable $iterator = null) |
27
|
|
|
{ |
28
|
|
|
return new OrderedMap($iterator === null ? null : $this->adapter($iterator)); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
public function createSet(\Traversable $iterator = null) |
32
|
|
|
{ |
33
|
|
|
return new Set($iterator === null ? null : $this->adapter($iterator)); |
34
|
|
|
} |
35
|
|
|
|
36
|
|
|
public function walk(\Traversable $iterator, callable $function) |
37
|
|
|
{ |
38
|
|
|
$adapter = $this->adapter($iterator); |
39
|
|
|
foreach ($adapter as $key => &$value) { |
40
|
|
|
if ($function($value, $key) === false) { |
41
|
|
|
break; |
42
|
|
|
} |
43
|
|
|
} |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
public function toArray(\Traversable $iterator) |
47
|
|
|
{ |
48
|
|
|
$iterator = $this->arrayCompatibleIterator($iterator); |
49
|
|
|
$array = []; |
50
|
|
|
|
51
|
|
|
foreach ($iterator as $key => &$value) { |
52
|
|
|
$array[$key] =& $value; |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
return $array; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
View Code Duplication |
public function arrayCompatibleIterator(\Traversable $iterator) |
|
|
|
|
59
|
|
|
{ |
60
|
|
|
$iterator = $this->adapter($iterator); |
61
|
|
|
if ($iterator->isArrayCompatible()) { |
62
|
|
|
return $iterator; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
return new ArrayCompatibleIterator($this->adapter($iterator)); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @param \Traversable $iterator |
70
|
|
|
* |
71
|
|
|
* @return IGenerator |
72
|
|
|
*/ |
73
|
|
View Code Duplication |
public static function adapter(\Traversable $iterator) |
74
|
|
|
{ |
75
|
|
|
if ($iterator instanceof IGenerator) { |
76
|
|
|
return $iterator; |
77
|
|
|
} elseif ($iterator instanceof IIterator) { |
78
|
|
|
return new IIteratorAdapter($iterator); |
79
|
|
|
} elseif ($iterator instanceof \ArrayIterator) { |
80
|
|
|
return new ArrayIteratorAdapter($iterator); |
81
|
|
|
} elseif ($iterator instanceof \IteratorAggregate) { |
82
|
|
|
return static::adapter($iterator->getIterator()); |
83
|
|
|
} else { |
84
|
|
|
return new IteratorAdapter($iterator); |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
protected function adapterIterator(\Traversable $iterator) |
89
|
|
|
{ |
90
|
|
|
return static::adapter($iterator); |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
public function arrayIterator(array $array) |
94
|
|
|
{ |
95
|
|
|
return new ArrayIterator($array); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
public function emptyIterator() |
99
|
|
|
{ |
100
|
|
|
return new EmptyIterator(); |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
public function filterIterator(\Traversable $iterator, callable $predicate) |
104
|
|
|
{ |
105
|
|
|
return new FilterIterator($this->adapter($iterator), $predicate); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
public function projectionIterator( |
109
|
|
|
\Traversable $iterator, |
110
|
|
|
callable $keyProjectionFunction = null, |
111
|
|
|
callable $valueProjectionFunction = null |
112
|
|
|
) { |
113
|
|
|
return new ProjectionIterator( |
114
|
|
|
$this->adapter($iterator), |
115
|
|
|
$keyProjectionFunction, |
116
|
|
|
$valueProjectionFunction); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
public function reindexerIterator(\Traversable $iterator) |
120
|
|
|
{ |
121
|
|
|
return new ReindexedIterator($this->adapter($iterator)); |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
public function joinIterator(\Traversable $outerIterator, \Traversable $innerIterator) |
125
|
|
|
{ |
126
|
|
|
return new UnfilteredJoinIterator( |
127
|
|
|
$this->adapter($outerIterator), |
128
|
|
|
$this->adapter($innerIterator)); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
public function groupJoinIterator( |
132
|
|
|
\Traversable $outerIterator, |
133
|
|
|
\Traversable $innerIterator, |
134
|
|
|
callable $traversableFactory |
135
|
|
|
) { |
136
|
|
|
return new UnfilteredGroupJoinIterator( |
137
|
|
|
$this->adapter($outerIterator), |
138
|
|
|
$this->adapter($innerIterator), |
139
|
|
|
$traversableFactory); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
public function rangeIterator(\Traversable $iterator, $start, $amount) |
143
|
|
|
{ |
144
|
|
|
return new RangeIterator($this->adapter($iterator), $start, $amount); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
public function groupedIterator( |
148
|
|
|
\Traversable $iterator, |
149
|
|
|
callable $groupKeyFunction, |
150
|
|
|
callable $traversableFactory |
151
|
|
|
) { |
152
|
|
|
return new GroupedIterator( |
153
|
|
|
$this->adapter($iterator), |
154
|
|
|
$groupKeyFunction, |
155
|
|
|
$traversableFactory); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
public function orderedIterator(\Traversable $iterator, callable $function, $isAscending) |
159
|
|
|
{ |
160
|
|
|
return new OrderedIterator( |
161
|
|
|
$this->adapter($iterator), |
162
|
|
|
$function, |
163
|
|
|
$isAscending); |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
protected function setOperationIterator(\Traversable $iterator, Common\SetOperations\ISetFilter $setFilter) |
167
|
|
|
{ |
168
|
|
|
return new SetOperationIterator($this->adapter($iterator), $setFilter); |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
protected function flattenedIteratorsIterator(\Traversable $iteratorsIterator) |
172
|
|
|
{ |
173
|
|
|
return new FlatteningIterator($this->adapter($iteratorsIterator)); |
174
|
|
|
} |
175
|
|
|
} |
176
|
|
|
|
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.