1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* TPriorityMap, TPriorityMapIterator classes |
4
|
|
|
* |
5
|
|
|
* @author Brad Anderson <[email protected]> |
6
|
|
|
* @link https://github.com/pradosoft/prado |
7
|
|
|
* @license https://github.com/pradosoft/prado/blob/master/LICENSE |
8
|
|
|
* @package Prado\Collections |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace Prado\Collections; |
12
|
|
|
|
13
|
|
|
use Prado\TPropertyValue; |
14
|
|
|
use Prado\Exceptions\TInvalidOperationException; |
15
|
|
|
use Prado\Exceptions\TInvalidDataTypeException; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* TPriorityMap class |
19
|
|
|
* |
20
|
|
|
* TPriorityMap implements a collection that takes key-value pairs with |
21
|
|
|
* a priority to allow key-value pairs to be ordered. This ordering is |
22
|
|
|
* important when flattening the map. When flattening the map, if some |
23
|
|
|
* key-value pairs are required to be before or after others, use this |
24
|
|
|
* class to keep order to your map. |
25
|
|
|
* |
26
|
|
|
* You can access, add or remove an item with a key by using |
27
|
|
|
* {@link itemAt}, {@link add}, and {@link remove}. These functions |
28
|
|
|
* can optionally take a priority parameter to allow access to specific |
29
|
|
|
* priorities. TPriorityMap is functionally backward compatible |
30
|
|
|
* with {@link TMap}. |
31
|
|
|
* |
32
|
|
|
* To get the number of the items in the map, use {@link getCount}. |
33
|
|
|
* TPriorityMap can also be used like a regular array as follows, |
34
|
|
|
* <code> |
35
|
|
|
* $map[$key]=$value; // add a key-value pair |
36
|
|
|
* unset($map[$key]); // remove the value with the specified key |
37
|
|
|
* if(isset($map[$key])) // if the map contains the key |
38
|
|
|
* foreach($map as $key=>$value) // traverse the items in the map |
39
|
|
|
* $n=count($map); // returns the number of items in the map |
40
|
|
|
* </code> |
41
|
|
|
* Using standard array access method like these will always use |
42
|
|
|
* the default priority. |
43
|
|
|
* |
44
|
|
|
* An item that doesn't specify a priority will receive the default |
45
|
|
|
* priority. The default priority is set during the instantiation |
46
|
|
|
* of a new TPriorityMap. If no custom default priority is specified, |
47
|
|
|
* the standard default priority of 10 is used. |
48
|
|
|
* |
49
|
|
|
* Priorities with significant digits below precision will be rounded. |
50
|
|
|
* |
51
|
|
|
* A priority may also be a numeric with decimals. This is set |
52
|
|
|
* during the instantiation of a new TPriorityMap. |
53
|
|
|
* The default is 8 decimal places for a priority. If a negative number |
54
|
|
|
* is used, rounding occurs into the integer space rather than in |
55
|
|
|
* the decimal space. See {@link round}. |
56
|
|
|
* |
57
|
|
|
* @author Brad Anderson <[email protected]> |
58
|
|
|
* @package Prado\Collections |
59
|
|
|
* @since 3.2a |
60
|
|
|
*/ |
61
|
|
|
|
62
|
|
|
class TPriorityMap extends TMap |
63
|
|
|
{ |
64
|
|
|
/** |
65
|
|
|
* @var bool indicates if the _d is currently ordered. |
66
|
|
|
*/ |
67
|
|
|
private $_o = false; |
68
|
|
|
/** |
69
|
|
|
* @var array cached flattened internal data storage |
70
|
|
|
*/ |
71
|
|
|
private $_fd; |
72
|
|
|
/** |
73
|
|
|
* @var int number of items contain within the map |
74
|
|
|
*/ |
75
|
|
|
private $_c = 0; |
76
|
|
|
/** |
77
|
|
|
* @var numeric the default priority of items without specified priorities |
78
|
|
|
*/ |
79
|
|
|
private $_dp = 10; |
80
|
|
|
/** |
81
|
|
|
* @var int the precision of the numeric priorities within this priority list. |
82
|
|
|
*/ |
83
|
|
|
private $_p = 8; |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Constructor. |
87
|
|
|
* Initializes the array with an array or an iterable object. |
88
|
|
|
* @param null|array|Iterator|map|TPriorityMap $data the intial data. Default is null, meaning no initialization. |
89
|
|
|
* @param bool $readOnly whether the list is read-only |
90
|
|
|
* @param numeric $defaultPriority the default priority of items without specified priorities. |
91
|
|
|
* @param int $precision the precision of the numeric priorities |
92
|
|
|
* @throws TInvalidDataTypeException If data is not null and neither an array nor an iterator. |
93
|
|
|
*/ |
94
|
53 |
View Code Duplication |
public function __construct($data = null, $readOnly = false, $defaultPriority = 10, $precision = 8) |
|
|
|
|
95
|
|
|
{ |
96
|
53 |
|
if ($data !== null) { |
97
|
4 |
|
$this->copyFrom($data); |
98
|
|
|
} |
99
|
53 |
|
$this->setReadOnly($readOnly); |
100
|
53 |
|
$this->setPrecision($precision); |
101
|
53 |
|
$this->setDefaultPriority($defaultPriority); |
102
|
53 |
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* @return numeric gets the default priority of inserted items without a specified priority |
106
|
|
|
*/ |
107
|
53 |
|
public function getDefaultPriority() |
108
|
|
|
{ |
109
|
53 |
|
return $this->_dp; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* This must be called internally or when instantiated. |
114
|
|
|
* @param numeric $value sets the default priority of inserted items without a specified priority |
115
|
|
|
*/ |
116
|
53 |
|
protected function setDefaultPriority($value) |
117
|
|
|
{ |
118
|
53 |
|
$this->_dp = (string) round(TPropertyValue::ensureFloat($value), $this->_p); |
|
|
|
|
119
|
53 |
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* @return int The precision of numeric priorities, defaults to 8 |
123
|
|
|
*/ |
124
|
2 |
|
public function getPrecision() |
125
|
|
|
{ |
126
|
2 |
|
return $this->_p; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* This must be called internally or when instantiated. |
131
|
|
|
* @param int $value The precision of numeric priorities. |
132
|
|
|
*/ |
133
|
53 |
|
protected function setPrecision($value) |
134
|
|
|
{ |
135
|
53 |
|
$this->_p = TPropertyValue::ensureInteger($value); |
136
|
53 |
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Returns an iterator for traversing the items in the map. |
140
|
|
|
* This method is required by the interface \IteratorAggregate. |
141
|
|
|
* @return Iterator an iterator for traversing the items in the map. |
142
|
|
|
*/ |
143
|
2 |
|
public function getIterator() |
144
|
|
|
{ |
145
|
2 |
|
return new \ArrayIterator($this->flattenPriorities()); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Orders the priority list internally. |
151
|
|
|
*/ |
152
|
48 |
|
protected function sortPriorities() |
153
|
|
|
{ |
154
|
48 |
|
if (!$this->_o) { |
155
|
48 |
|
ksort($this->_d, SORT_NUMERIC); |
156
|
48 |
|
$this->_o = true; |
157
|
|
|
} |
158
|
48 |
|
} |
159
|
|
|
|
160
|
|
|
/** |
161
|
|
|
* This flattens the priority map into a flat array [0,...,n-1] |
162
|
|
|
* @return array array of items in the list in priority and index order |
163
|
|
|
*/ |
164
|
42 |
View Code Duplication |
protected function flattenPriorities() |
|
|
|
|
165
|
|
|
{ |
166
|
42 |
|
if (is_array($this->_fd)) { |
167
|
34 |
|
return $this->_fd; |
168
|
|
|
} |
169
|
|
|
|
170
|
42 |
|
$this->sortPriorities(); |
171
|
42 |
|
$this->_fd = []; |
172
|
42 |
|
foreach ($this->_d as $priority => $itemsatpriority) { |
173
|
41 |
|
$this->_fd = array_merge($this->_fd, $itemsatpriority); |
174
|
|
|
} |
175
|
42 |
|
return $this->_fd; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* @return int the number of items in the map |
180
|
|
|
*/ |
181
|
20 |
|
public function getCount() |
182
|
|
|
{ |
183
|
20 |
|
return $this->_c; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* Gets the number of items at a priority within the map. |
188
|
|
|
* @param null|numeric $priority optional priority at which to count items. if no parameter, |
189
|
|
|
* it will be set to the default {@link getDefaultPriority} |
190
|
|
|
* @return int the number of items in the map at the specified priority |
191
|
|
|
*/ |
192
|
|
View Code Duplication |
public function getPriorityCount($priority = null) |
|
|
|
|
193
|
|
|
{ |
194
|
|
|
if ($priority === null) { |
195
|
|
|
$priority = $this->getDefaultPriority(); |
196
|
|
|
} |
197
|
|
|
$priority = (string) round(TPropertyValue::ensureFloat($priority), $this->_p); |
198
|
|
|
|
199
|
|
|
if (!isset($this->_d[$priority]) || !is_array($this->_d[$priority])) { |
200
|
|
|
return false; |
201
|
|
|
} |
202
|
|
|
return count($this->_d[$priority]); |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
/** |
206
|
|
|
* This returns a list of the priorities within this map, ordered lowest to highest. |
207
|
|
|
* @return array the array of priority numerics in decreasing priority order |
208
|
|
|
*/ |
209
|
3 |
|
public function getPriorities() |
210
|
|
|
{ |
211
|
3 |
|
$this->sortPriorities(); |
212
|
3 |
|
return array_keys($this->_d); |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* Returns the keys within the map ordered through the priority of each key-value pair |
217
|
|
|
* @return array the key list |
218
|
|
|
*/ |
219
|
1 |
|
public function getKeys() |
220
|
|
|
{ |
221
|
1 |
|
return array_keys($this->flattenPriorities()); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Returns the item with the specified key. If a priority is specified, only items |
226
|
|
|
* within that specific priority will be selected |
227
|
|
|
* @param mixed $key the key |
228
|
|
|
* @param mixed $priority the priority. null is the default priority, false is any priority, |
229
|
|
|
* and numeric is a specific priority. default: false, any priority. |
230
|
|
|
* @return mixed the element at the offset, null if no element is found at the offset |
231
|
|
|
*/ |
232
|
29 |
|
public function itemAt($key, $priority = false) |
233
|
|
|
{ |
234
|
29 |
|
if ($priority === false) { |
235
|
29 |
|
$map = $this->flattenPriorities(); |
236
|
29 |
|
return $map[$key] ?? null; |
237
|
|
|
} else { |
238
|
1 |
|
if ($priority === null) { |
239
|
|
|
$priority = $this->getDefaultPriority(); |
240
|
|
|
} |
241
|
1 |
|
$priority = (string) round(TPropertyValue::ensureFloat($priority), $this->_p); |
242
|
1 |
|
return (isset($this->_d[$priority]) && isset($this->_d[$priority][$key])) ? $this->_d[$priority][$key] : null; |
243
|
|
|
} |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* This changes an item's priority. Specify the item and the new priority. |
248
|
|
|
* This method is exactly the same as {@link offsetGet}. |
249
|
|
|
* @param mixed $key the key |
250
|
|
|
* @param null|numeric $priority the priority. default: null, filled in with the default priority numeric. |
251
|
|
|
* @return numeric old priority of the item |
252
|
|
|
*/ |
253
|
1 |
|
public function setPriorityAt($key, $priority = null) |
254
|
|
|
{ |
255
|
1 |
|
if ($priority === null) { |
256
|
1 |
|
$priority = $this->getDefaultPriority(); |
257
|
|
|
} |
258
|
1 |
|
$priority = (string) round(TPropertyValue::ensureFloat($priority), $this->_p); |
259
|
|
|
|
260
|
1 |
|
$oldpriority = $this->priorityAt($key); |
261
|
1 |
|
if ($oldpriority !== false && $oldpriority != $priority) { |
262
|
1 |
|
$value = $this->remove($key, $oldpriority); |
263
|
1 |
|
$this->add($key, $value, $priority); |
264
|
|
|
} |
265
|
1 |
|
return $oldpriority; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* Gets all the items at a specific priority. |
270
|
|
|
* @param null|numeric $priority priority of the items to get. Defaults to null, filled in with the default priority, if left blank. |
271
|
|
|
* @return array all items at priority in index order, null if there are no items at that priority |
272
|
|
|
*/ |
273
|
3 |
View Code Duplication |
public function itemsAtPriority($priority = null) |
|
|
|
|
274
|
|
|
{ |
275
|
3 |
|
if ($priority === null) { |
276
|
|
|
$priority = $this->getDefaultPriority(); |
277
|
|
|
} |
278
|
3 |
|
$priority = (string) round(TPropertyValue::ensureFloat($priority), $this->_p); |
279
|
|
|
|
280
|
3 |
|
return isset($this->_d[$priority]) ? $this->_d[$priority] : null; |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
/** |
284
|
|
|
* Returns the priority of a particular item within the map. This searches the map for the item. |
285
|
|
|
* @param mixed $item item to look for within the map |
286
|
|
|
* @return numeric priority of the item in the map |
287
|
|
|
*/ |
288
|
2 |
|
public function priorityOf($item) |
289
|
|
|
{ |
290
|
2 |
|
$this->sortPriorities(); |
291
|
2 |
|
foreach ($this->_d as $priority => $items) { |
292
|
2 |
|
if (($index = array_search($item, $items, true)) !== false) { |
293
|
2 |
|
return $priority; |
294
|
|
|
} |
295
|
|
|
} |
296
|
1 |
|
return false; |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
/** |
300
|
|
|
* Retutrns the priority of an item at a particular flattened index. |
301
|
|
|
* @param int $key index of the item within the map |
302
|
|
|
* @return numeric priority of the item in the map |
303
|
|
|
*/ |
304
|
3 |
|
public function priorityAt($key) |
305
|
|
|
{ |
306
|
3 |
|
$this->sortPriorities(); |
307
|
3 |
|
foreach ($this->_d as $priority => $items) { |
308
|
3 |
|
if (array_key_exists($key, $items)) { |
309
|
3 |
|
return $priority; |
310
|
|
|
} |
311
|
|
|
} |
312
|
1 |
|
return false; |
313
|
|
|
} |
314
|
|
|
|
315
|
|
|
/** |
316
|
|
|
* Adds an item into the map. A third parameter may be used to set the priority |
317
|
|
|
* of the item within the map. Priority is primarily used during when flattening |
318
|
|
|
* the map into an array where order may be and important factor of the key-value |
319
|
|
|
* pairs within the array. |
320
|
|
|
* Note, if the specified key already exists, the old value will be overwritten. |
321
|
|
|
* No duplicate keys are allowed regardless of priority. |
322
|
|
|
* @param mixed $key |
323
|
|
|
* @param mixed $value |
324
|
|
|
* @param null|numeric $priority default: null, filled in with default priority |
325
|
|
|
* @throws TInvalidOperationException if the map is read-only |
326
|
|
|
* @return numeric priority at which the pair was added |
327
|
|
|
*/ |
328
|
53 |
|
public function add($key, $value, $priority = null) |
329
|
|
|
{ |
330
|
53 |
|
if ($priority === null) { |
331
|
53 |
|
$priority = $this->getDefaultPriority(); |
332
|
|
|
} |
333
|
53 |
|
$priority = (string) round(TPropertyValue::ensureFloat($priority), $this->_p); |
334
|
|
|
|
335
|
53 |
|
if (!$this->_r) { |
336
|
53 |
|
foreach ($this->_d as $innerpriority => $items) { |
337
|
36 |
|
if (array_key_exists($key, $items)) { |
338
|
4 |
|
unset($this->_d[$innerpriority][$key]); |
339
|
4 |
|
$this->_c--; |
340
|
4 |
|
if (count($this->_d[$innerpriority]) === 0) { |
341
|
36 |
|
unset($this->_d[$innerpriority]); |
342
|
|
|
} |
343
|
|
|
} |
344
|
|
|
} |
345
|
53 |
|
if (!isset($this->_d[$priority])) { |
346
|
53 |
|
$this->_d[$priority] = [$key => $value]; |
347
|
53 |
|
$this->_o = false; |
348
|
|
|
} else { |
349
|
36 |
|
$this->_d[$priority][$key] = $value; |
350
|
|
|
} |
351
|
53 |
|
$this->_c++; |
352
|
53 |
|
$this->_fd = null; |
|
|
|
|
353
|
|
|
} else { |
354
|
1 |
|
throw new TInvalidOperationException('map_readonly', get_class($this)); |
355
|
|
|
} |
356
|
53 |
|
return $priority; |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* Removes an item from the map by its key. If no priority, or false, is specified |
361
|
|
|
* then priority is irrelevant. If null is used as a parameter for priority, then |
362
|
|
|
* the priority will be the default priority. If a priority is specified, or |
363
|
|
|
* the default priority is specified, only key-value pairs in that priority |
364
|
|
|
* will be affected. |
365
|
|
|
* @param mixed $key the key of the item to be removed |
366
|
|
|
* @param null|false|numeric $priority priority. False is any priority, null is the |
367
|
|
|
* default priority, and numeric is a specific priority |
368
|
|
|
* @throws TInvalidOperationException if the map is read-only |
369
|
|
|
* @return mixed the removed value, null if no such key exists. |
370
|
|
|
*/ |
371
|
26 |
|
public function remove($key, $priority = false) |
372
|
|
|
{ |
373
|
26 |
|
if (!$this->_r) { |
374
|
25 |
|
if ($priority === null) { |
375
|
7 |
|
$priority = $this->getDefaultPriority(); |
376
|
|
|
} |
377
|
|
|
|
378
|
25 |
|
if ($priority === false) { |
379
|
19 |
|
$this->sortPriorities(); |
380
|
19 |
|
foreach ($this->_d as $priority => $items) { |
381
|
19 |
|
if (array_key_exists($key, $items)) { |
382
|
19 |
|
$value = $this->_d[$priority][$key]; |
383
|
19 |
|
unset($this->_d[$priority][$key]); |
384
|
19 |
|
$this->_c--; |
385
|
19 |
View Code Duplication |
if (count($this->_d[$priority]) === 0) { |
|
|
|
|
386
|
14 |
|
unset($this->_d[$priority]); |
387
|
14 |
|
$this->_o = false; |
388
|
|
|
} |
389
|
19 |
|
$this->_fd = null; |
|
|
|
|
390
|
19 |
|
return $value; |
391
|
|
|
} |
392
|
|
|
} |
393
|
2 |
|
return null; |
394
|
|
|
} else { |
395
|
8 |
|
$priority = (string) round(TPropertyValue::ensureFloat($priority), $this->_p); |
396
|
8 |
|
if (isset($this->_d[$priority]) && (isset($this->_d[$priority][$key]) || array_key_exists($key, $this->_d[$priority]))) { |
397
|
7 |
|
$value = $this->_d[$priority][$key]; |
398
|
7 |
|
unset($this->_d[$priority][$key]); |
399
|
7 |
|
$this->_c--; |
400
|
7 |
View Code Duplication |
if (count($this->_d[$priority]) === 0) { |
|
|
|
|
401
|
6 |
|
unset($this->_d[$priority]); |
402
|
6 |
|
$this->_o = false; |
403
|
|
|
} |
404
|
7 |
|
$this->_fd = null; |
405
|
7 |
|
return $value; |
406
|
|
|
} else { |
407
|
1 |
|
return null; |
408
|
|
|
} |
409
|
|
|
} |
410
|
|
|
} else { |
411
|
1 |
|
throw new TInvalidOperationException('map_readonly', get_class($this)); |
412
|
|
|
} |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
/** |
416
|
|
|
* Removes all items in the map. {@link remove} is called on all items. |
417
|
|
|
*/ |
418
|
3 |
|
public function clear() |
419
|
|
|
{ |
420
|
3 |
|
foreach ($this->_d as $priority => $items) { |
421
|
3 |
|
foreach (array_keys($items) as $key) { |
422
|
3 |
|
$this->remove($key); |
423
|
|
|
} |
424
|
|
|
} |
425
|
3 |
|
} |
426
|
|
|
|
427
|
|
|
/** |
428
|
|
|
* @param mixed $key the key |
429
|
|
|
* @return bool whether the map contains an item with the specified key |
430
|
|
|
*/ |
431
|
31 |
|
public function contains($key) |
432
|
|
|
{ |
433
|
31 |
|
$map = $this->flattenPriorities(); |
434
|
31 |
|
return isset($map[$key]) || array_key_exists($key, $map); |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
/** |
438
|
|
|
* When the map is flattened into an array, the priorities are taken into |
439
|
|
|
* account and elements of the map are ordered in the array according to |
440
|
|
|
* their priority. |
441
|
|
|
* @return array the list of items in array |
442
|
|
|
*/ |
443
|
30 |
|
public function toArray() |
444
|
|
|
{ |
445
|
30 |
|
return $this->flattenPriorities(); |
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
/** |
449
|
|
|
* Combines the map elements which have a priority below the parameter value |
450
|
|
|
* @param numeric $priority the cut-off priority. All items of priority less than this are returned. |
451
|
|
|
* @param bool $inclusive whether or not the input cut-off priority is inclusive. Default: false, not inclusive. |
452
|
|
|
* @return array the array of priorities keys with values of arrays of items that are below a specified priority. |
453
|
|
|
* The priorities are sorted so important priorities, lower numerics, are first. |
454
|
|
|
*/ |
455
|
1 |
View Code Duplication |
public function toArrayBelowPriority($priority, $inclusive = false) |
|
|
|
|
456
|
|
|
{ |
457
|
1 |
|
$this->sortPriorities(); |
458
|
1 |
|
$items = []; |
459
|
1 |
|
foreach ($this->_d as $itemspriority => $itemsatpriority) { |
460
|
1 |
|
if ((!$inclusive && $itemspriority >= $priority) || $itemspriority > $priority) { |
461
|
1 |
|
break; |
462
|
|
|
} |
463
|
1 |
|
$items = array_merge($items, $itemsatpriority); |
464
|
|
|
} |
465
|
1 |
|
return $items; |
466
|
|
|
} |
467
|
|
|
|
468
|
|
|
/** |
469
|
|
|
* Combines the map elements which have a priority above the parameter value |
470
|
|
|
* @param numeric $priority the cut-off priority. All items of priority greater than this are returned. |
471
|
|
|
* @param bool $inclusive whether or not the input cut-off priority is inclusive. Default: true, inclusive. |
472
|
|
|
* @return array the array of priorities keys with values of arrays of items that are above a specified priority. |
473
|
|
|
* The priorities are sorted so important priorities, lower numerics, are first. |
474
|
|
|
*/ |
475
|
1 |
View Code Duplication |
public function toArrayAbovePriority($priority, $inclusive = true) |
|
|
|
|
476
|
|
|
{ |
477
|
1 |
|
$this->sortPriorities(); |
478
|
1 |
|
$items = []; |
479
|
1 |
|
foreach ($this->_d as $itemspriority => $itemsatpriority) { |
480
|
1 |
|
if ((!$inclusive && $itemspriority <= $priority) || $itemspriority < $priority) { |
481
|
1 |
|
continue; |
482
|
|
|
} |
483
|
1 |
|
$items = array_merge($items, $itemsatpriority); |
484
|
|
|
} |
485
|
1 |
|
return $items; |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
/** |
489
|
|
|
* Copies iterable data into the map. |
490
|
|
|
* Note, existing data in the map will be cleared first. |
491
|
|
|
* @param array|TPriorityMap|Traversable $data the data to be copied from, must be an array, object implementing |
492
|
|
|
* @throws TInvalidDataTypeException If data is neither an array nor an iterator. |
493
|
|
|
*/ |
494
|
6 |
View Code Duplication |
public function copyFrom($data) |
|
|
|
|
495
|
|
|
{ |
496
|
6 |
|
if ($data instanceof TPriorityMap) { |
497
|
2 |
|
if ($this->getCount() > 0) { |
498
|
1 |
|
$this->clear(); |
499
|
|
|
} |
500
|
2 |
|
foreach ($data->getPriorities() as $priority) { |
501
|
2 |
|
foreach ($data->itemsAtPriority($priority) as $key => $value) { |
502
|
2 |
|
$this->add($key, $value, $priority); |
503
|
|
|
} |
504
|
|
|
} |
505
|
5 |
|
} elseif (is_array($data) || $data instanceof \Traversable) { |
506
|
5 |
|
if ($this->getCount() > 0) { |
507
|
1 |
|
$this->clear(); |
508
|
|
|
} |
509
|
5 |
|
foreach ($data as $key => $value) { |
510
|
5 |
|
$this->add($key, $value); |
511
|
|
|
} |
512
|
1 |
|
} elseif ($data !== null) { |
513
|
1 |
|
throw new TInvalidDataTypeException('map_data_not_iterable'); |
514
|
|
|
} |
515
|
6 |
|
} |
516
|
|
|
|
517
|
|
|
/** |
518
|
|
|
* Merges iterable data into the map. |
519
|
|
|
* Existing data in the map will be kept and overwritten if the keys are the same. |
520
|
|
|
* @param array|TPriorityMap|Traversable $data the data to be merged with, must be an array, |
521
|
|
|
* object implementing Traversable, or a TPriorityMap |
522
|
|
|
* @throws TInvalidDataTypeException If data is neither an array nor an iterator. |
523
|
|
|
*/ |
524
|
2 |
View Code Duplication |
public function mergeWith($data) |
|
|
|
|
525
|
|
|
{ |
526
|
2 |
|
if ($data instanceof TPriorityMap) { |
527
|
1 |
|
foreach ($data->getPriorities() as $priority) { |
528
|
1 |
|
foreach ($data->itemsAtPriority($priority) as $key => $value) { |
529
|
1 |
|
$this->add($key, $value, $priority); |
530
|
|
|
} |
531
|
|
|
} |
532
|
1 |
|
} elseif (is_array($data) || $data instanceof \Traversable) { |
533
|
1 |
|
foreach ($data as $key => $value) { |
534
|
1 |
|
$this->add($key, $value); |
535
|
|
|
} |
536
|
1 |
|
} elseif ($data !== null) { |
537
|
1 |
|
throw new TInvalidDataTypeException('map_data_not_iterable'); |
538
|
|
|
} |
539
|
2 |
|
} |
540
|
|
|
} |
541
|
|
|
|
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.