Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
17 | class Extension extends AbstractExtension implements GlobalsInterface |
||
18 | { |
||
19 | /** |
||
20 | * {@inheritDoc} |
||
21 | */ |
||
22 | 1 | public function getGlobals() |
|
23 | { |
||
24 | return [ |
||
25 | 'it' => (object)[ |
||
26 | 1 | 'filters' => new Itertools\util\Filters(), |
|
27 | 1 | 'mappings' => new Itertools\util\Mappings(), |
|
28 | 1 | 'reductions' => new Itertools\util\Reductions(), |
|
29 | ], |
||
30 | ]; |
||
31 | } |
||
32 | |||
33 | /** |
||
34 | * {@inheritDoc} |
||
35 | */ |
||
36 | 1 | public function getFilters() |
|
37 | { |
||
38 | return [ |
||
39 | 1 | new TwigFilter('it', [$this, 'it']), |
|
40 | |||
41 | // deprecated filters (because 'it' was introduced) |
||
42 | 1 | new TwigFilter('all', '\Zicht\Itertools\all', ['deprecated' => true, 'alternative' => '|it.all']), |
|
43 | 1 | new TwigFilter('any', '\Zicht\Itertools\any', ['deprecated' => true, 'alternative' => '|it.any']), |
|
44 | 1 | new TwigFilter('chain', '\Zicht\Itertools\chain', ['deprecated' => true, 'alternative' => '|it.chain']), |
|
45 | 1 | new TwigFilter('collapse', '\Zicht\Itertools\collapse', ['deprecated' => true, 'alternative' => '|it.collapse']), |
|
46 | 1 | new TwigFilter('filter', [$this, 'filter'], ['deprecated' => true, 'alternative' => '|it.filter']), |
|
47 | 1 | new TwigFilter('first', '\Zicht\Itertools\first', ['deprecated' => true, 'alternative' => '|it.first']), |
|
48 | 1 | new TwigFilter('group_by', [$this, 'groupBy'], ['deprecated' => true, 'alternative' => '|it.groupBy']), |
|
49 | 1 | new TwigFilter('last', '\Zicht\Itertools\last', ['deprecated' => true, 'alternative' => '|it.last']), |
|
50 | 1 | new TwigFilter('map', [$this, 'map'], ['deprecated' => true, 'alternative' => '|it.map']), |
|
51 | 1 | new TwigFilter('map_by', [$this, 'mapBy'], ['deprecated' => true, 'alternative' => '|it.mapBy']), |
|
52 | 1 | new TwigFilter('reduce', '\Zicht\Itertools\reduce', ['deprecated' => true, 'alternative' => '|it.reduce']), |
|
53 | 1 | new TwigFilter('reversed', '\Zicht\Itertools\reversed', ['deprecated' => true, 'alternative' => '|it.reversed']), |
|
54 | 1 | new TwigFilter('sorted', [$this, 'sorted'], ['deprecated' => true, 'alternative' => '|it.sorted']), |
|
55 | 1 | new TwigFilter('unique', [$this, 'unique'], ['deprecated' => true, 'alternative' => '|it.unique']), |
|
56 | 1 | new TwigFilter('zip', '\Zicht\Itertools\zip', ['deprecated' => true, 'alternative' => '|it.zip']), |
|
57 | |||
58 | // deprecated filters |
||
59 | 1 | new TwigFilter('filterby', [$this, 'deprecatedFilterBy'], ['deprecated' => true, 'alternative' => '|it.filter']), |
|
60 | 1 | new TwigFilter('groupBy', [$this, 'deprecatedGroupBy'], ['deprecated' => true, 'alternative' => '|it.groupBy']), |
|
61 | 1 | new TwigFilter('groupby', [$this, 'deprecatedGroupBy'], ['deprecated' => true, 'alternative' => '|it.groupBy']), |
|
62 | 1 | new TwigFilter('mapBy', [$this, 'deprecatedMapBy'], ['deprecated' => true, 'alternative' => '|it.mapBy']), |
|
63 | 1 | new TwigFilter('mapby', [$this, 'deprecatedMapBy'], ['deprecated' => true, 'alternative' => '|it.mapBy']), |
|
64 | 1 | new TwigFilter('sum', [$this, 'deprecatedSum'], ['deprecated' => true, 'alternative' => '|it.reduce']), |
|
65 | 1 | new TwigFilter('uniqueby', [$this, 'deprecatedUniqueBy'], ['deprecated' => true, 'alternative' => '|it.unique']), |
|
66 | ]; |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * {@inheritDoc} |
||
71 | */ |
||
72 | 1 | public function getFunctions() |
|
73 | { |
||
74 | return [ |
||
75 | 1 | new TwigFunction('it', [$this, 'it']), |
|
76 | |||
77 | // deprecated functions (because 'it' was introduced) |
||
78 | 1 | new TwigFunction('chain', '\Zicht\Itertools\chain', ['deprecated' => true, 'alternative' => '|it.chain']), |
|
79 | 1 | new TwigFunction('first', '\Zicht\Itertools\first', ['deprecated' => true, 'alternative' => '|it.first']), |
|
80 | 1 | new TwigFunction('last', '\Zicht\Itertools\last', ['deprecated' => true, 'alternative' => '|it.last']), |
|
81 | |||
82 | // deprecated functions (because 'it' was introduced) |
||
83 | 1 | new TwigFunction('reducing', [$this, 'reducing'], ['deprecated' => true, 'alternative' => 'it.reductions']), |
|
84 | 1 | new TwigFunction('mapping', [$this, 'mapping'], ['deprecated' => true, 'alternative' => 'it.mappings']), |
|
85 | 1 | new TwigFunction('filtering', [$this, 'filtering'], ['deprecated' => true, 'alternative' => 'it.filters']), |
|
86 | |||
87 | // deprecated functions |
||
88 | 1 | new TwigFunction('reduction', [$this, 'deprecatedGetReduction'], ['deprecated' => true, 'alternative' => 'reducing']), |
|
89 | ]; |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Takes an iterable and returns an object that allow mapping, sorting, etc. |
||
94 | * |
||
95 | * @param $iterable |
||
96 | * @return Itertools\lib\Interfaces\FiniteIterableInterface|Itertools\lib\IterableIterator |
||
97 | */ |
||
98 | 1 | public function it($iterable) |
|
99 | { |
||
100 | 1 | return Itertools\iterable($iterable); |
|
101 | } |
||
102 | |||
103 | /** |
||
104 | * Takes an iterable and returns another iterable that is unique. |
||
105 | * |
||
106 | * @param array|string|\Iterator $iterable |
||
107 | * @param mixed $strategy |
||
108 | * @return Itertools\lib\UniqueIterator |
||
109 | * @deprecated |
||
110 | */ |
||
111 | public function unique($iterable, $strategy = null) |
||
112 | { |
||
113 | return Itertools\unique($strategy, $iterable); |
||
|
|||
114 | } |
||
115 | |||
116 | /** |
||
117 | * Reduce an iterable to a single value |
||
118 | * |
||
119 | * Simple examples: |
||
120 | * {{ [1,2,3]|reduce }} --> 6 |
||
121 | * {{ [1,2,3]|reduce('max') }} --> 3 |
||
122 | * |
||
123 | * Sro example to get the prices for all items in the basket: |
||
124 | * {{ transaction_snapshot.Basket.Items|map('TotalPrice.Amount')|reduce }} |
||
125 | * |
||
126 | * @param array|string|\Iterator $iterable |
||
127 | * @param string|\Closure $closure |
||
128 | * @param mixed $initializer |
||
129 | * @return mixed |
||
130 | * @deprecated |
||
131 | */ |
||
132 | public function reduce($iterable, $closure = 'add', $initializer = null) |
||
133 | { |
||
134 | return Itertools\reduce($iterable, $closure, $initializer); |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Make an iterator that returns consecutive groups from the |
||
139 | * $iterable. Generally, the $iterable needs to already be sorted on |
||
140 | * the same key function. |
||
141 | * |
||
142 | * @param array|string|\Iterator $iterable |
||
143 | * @param string|\Closure $strategy |
||
144 | * @param boolean $sort |
||
145 | * @return Itertools\lib\GroupbyIterator |
||
146 | * @deprecated |
||
147 | */ |
||
148 | public function groupBy($iterable, $strategy, $sort = true) |
||
149 | { |
||
150 | return Itertools\group_by($strategy, $iterable, $sort); |
||
151 | } |
||
152 | |||
153 | /** |
||
154 | * Make an iterator that returns values from $iterable where the |
||
155 | * $strategy determines that the values are not empty. |
||
156 | * |
||
157 | * @param array|string|\Iterator $iterable |
||
158 | * @param null $strategy |
||
159 | * @return Itertools\lib\FilterIterator |
||
160 | * @deprecated |
||
161 | */ |
||
162 | public function filter($iterable, $strategy = null) |
||
163 | { |
||
164 | return Itertools\filter($strategy, $iterable); |
||
165 | } |
||
166 | |||
167 | /** |
||
168 | * Make an iterator that returns the values from $iterable sorted by |
||
169 | * $strategy. |
||
170 | * |
||
171 | * @param array|string|\Iterator $iterable |
||
172 | * @param string|\Closure $strategy |
||
173 | * @param bool $reverse |
||
174 | * @return Itertools\lib\SortedIterator |
||
175 | * @deprecated |
||
176 | */ |
||
177 | public function sorted($iterable, $strategy = null, $reverse = false) |
||
178 | { |
||
179 | return Itertools\sorted($strategy, $iterable, $reverse); |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * Make an iterator that applies $func to every entry in the $iterables. |
||
184 | * |
||
185 | * @param array|string|\Iterator $iterable |
||
186 | * @param string|\Closure $strategy |
||
187 | * @return Itertools\lib\MapIterator |
||
188 | * @deprecated |
||
189 | */ |
||
190 | public function map($iterable, $strategy) |
||
191 | { |
||
192 | return Itertools\map($strategy, $iterable); |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * Make an iterator returning values from $iterable and keys from |
||
197 | * $strategy. |
||
198 | * |
||
199 | * @param array|string|\Iterator $iterable |
||
200 | * @param string|\Closure $strategy |
||
201 | * @return Itertools\lib\MapByIterator |
||
202 | * @deprecated |
||
203 | */ |
||
204 | public function mapBy($iterable, $strategy) |
||
205 | { |
||
206 | return Itertools\map_by($strategy, $iterable); |
||
207 | } |
||
208 | |||
209 | |||
210 | /** |
||
211 | * Returns a reduction closure |
||
212 | * |
||
213 | * Any parameters provided, beyond $name, are passed directly to the underlying |
||
214 | * reduction. This can be used to, for example, provide a $glue when using join. |
||
215 | * |
||
216 | * @param string $name |
||
217 | * @return \Closure |
||
218 | * @throws \InvalidArgumentException |
||
219 | */ |
||
220 | 4 | View Code Duplication | public function reducing($name) |
221 | { |
||
222 | // note, once we stop supporting php 5.5, we can rewrite the code below |
||
223 | // to the reducing($name, ...$args) structure. |
||
224 | // http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list |
||
225 | 4 | $method = sprintf('\Zicht\Itertools\util\Reductions::%s', $name); |
|
226 | 4 | if (!is_callable($method)) { |
|
227 | 2 | throw new \InvalidArgumentException(sprintf('$name "%s" is not a valid reduction.', $name)); |
|
228 | } |
||
229 | 2 | return call_user_func_array($method, array_slice(func_get_args(), 1)); |
|
230 | } |
||
231 | |||
232 | /** |
||
233 | * Returns a mapping closure |
||
234 | * |
||
235 | * Any parameters provided, beyond $name, are passed directly to the underlying |
||
236 | * mapping. This can be used to, for example, provide a $glue when using join. |
||
237 | * |
||
238 | * @param string $name |
||
239 | * @return \Closure |
||
240 | * @throws \InvalidArgumentException |
||
241 | */ |
||
242 | 2 | View Code Duplication | public function mapping($name) |
243 | { |
||
244 | // note, once we stop supporting php 5.5, we can rewrite the code below |
||
245 | // to the reducing($name, ...$args) structure. |
||
246 | // http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list |
||
247 | 2 | $method = sprintf('\Zicht\Itertools\util\Mappings::%s', $name); |
|
248 | 2 | if (!is_callable($method)) { |
|
249 | 1 | throw new \InvalidArgumentException(sprintf('$name "%s" is not a valid mapping.', $name)); |
|
250 | } |
||
251 | 1 | return call_user_func_array($method, array_slice(func_get_args(), 1)); |
|
252 | } |
||
253 | |||
254 | /** |
||
255 | * Returns a filter closure |
||
256 | * |
||
257 | * Any parameters provided, beyond $name, are passed directly to the underlying |
||
258 | * filter. This can be used to, for example, provide a $glue when using join. |
||
259 | * |
||
260 | * @param string $name |
||
261 | * @return \Closure |
||
262 | * @throws \InvalidArgumentException |
||
263 | */ |
||
264 | 2 | View Code Duplication | public function filtering($name) |
265 | { |
||
266 | // note, once we stop supporting php 5.5, we can rewrite the code below |
||
267 | // to the reducing($name, ...$args) structure. |
||
268 | // http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list |
||
269 | 2 | $method = sprintf('\Zicht\Itertools\util\Filters::%s', $name); |
|
270 | 2 | if (!is_callable($method)) { |
|
271 | 1 | throw new \InvalidArgumentException(sprintf('$name "%s" is not a valid filter.', $name)); |
|
272 | } |
||
273 | 1 | return call_user_func_array($method, array_slice(func_get_args(), 1)); |
|
274 | } |
||
275 | |||
276 | /** |
||
277 | * Make an iterator that returns values from $iterable where the |
||
278 | * $strategy determines that the values are not empty. |
||
279 | * |
||
280 | * @param array|string|\Iterator $iterable |
||
281 | * @param string|\Closure $strategy |
||
282 | * @return Itertools\lib\FilterIterator |
||
283 | * @deprecated Use filter instead! |
||
284 | */ |
||
285 | public function deprecatedFilterBy($iterable, $strategy) |
||
286 | { |
||
287 | return Itertools\filter($strategy, $iterable); |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Make an iterator that returns consecutive groups from the |
||
292 | * $iterable. Generally, the $iterable needs to already be sorted on |
||
293 | * the same key function. |
||
294 | * |
||
295 | * @param array|string|\Iterator $iterable |
||
296 | * @param string|\Closure $strategy |
||
297 | * @return Itertools\lib\GroupbyIterator |
||
298 | * @deprecated Use group_by instead! |
||
299 | */ |
||
300 | public function deprecatedGroupBy($iterable, $strategy) |
||
301 | { |
||
302 | return Itertools\group_by($strategy, $iterable); |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * Make an iterator returning values from $iterable and keys from |
||
307 | * $strategy. |
||
308 | * |
||
309 | * @param array|string|\Iterator $iterable |
||
310 | * @param string|\Closure $strategy |
||
311 | * @return Itertools\lib\MapByIterator |
||
312 | * @deprecated Use map_by instead! |
||
313 | */ |
||
314 | public function deprecatedMapBy($iterable, $strategy) |
||
318 | |||
319 | /** |
||
320 | * Create a reduction |
||
321 | * |
||
322 | * @param array|string|\Iterator $iterable |
||
323 | * @param int $default |
||
324 | * @return int |
||
325 | * @deprecated Use reduce instead! |
||
326 | */ |
||
327 | public function deprecatedSum($iterable, $default = 0) |
||
328 | { |
||
329 | $result = $default; |
||
330 | foreach (Itertools\accumulate($iterable) as $result) { |
||
331 | }; |
||
332 | return $result; |
||
333 | } |
||
334 | |||
335 | /** |
||
336 | * Takes an iterable and returns another iterable that is unique. |
||
337 | * |
||
338 | * @param array|string|\Iterator $iterable |
||
339 | * @param mixed $strategy |
||
340 | * @return Itertools\lib\UniqueIterator |
||
341 | * @deprecated Use unique instead! |
||
342 | */ |
||
343 | public function deprecatedUniqueBy($iterable, $strategy = null) |
||
347 | |||
348 | /** |
||
349 | * Returns a reduction closure |
||
350 | * |
||
351 | * @param string $name |
||
352 | * @return \Closure |
||
353 | * @throws \InvalidArgumentException |
||
354 | * @deprecated Use reducing instead! |
||
355 | */ |
||
356 | public function deprecatedGetReduction($name) |
||
360 | |||
361 | /** |
||
362 | * {@inheritDoc} |
||
363 | */ |
||
364 | 1 | public function getName() |
|
368 | } |
||
369 |
This function has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.