Passed
Branch php-cs-fixer (b9836a)
by Fabio
15:02
created

TPriorityMap::setDefaultPriority()   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
2
/**
3
 * TPriorityMap, TPriorityMapIterator classes
4
 *
5
 * @author Brad Anderson <[email protected]>
6
 * @link https://github.com/pradosoft/prado
7
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 * @package Prado\Collections
10
 */
11
12
namespace Prado\Collections;
13
14
use Prado\TPropertyValue;
15
use Prado\Exceptions\TInvalidOperationException;
16
use Prado\Exceptions\TInvalidDataTypeException;
17
18
/**
19
 * TPriorityMap class
20
 *
21
 * TPriorityMap implements a collection that takes key-value pairs with
22
 * a priority to allow key-value pairs to be ordered.  This ordering is
23
 * important when flattening the map. When flattening the map, if some
24
 * key-value pairs are required to be before or after others, use this
25
 * class to keep order to your map.
26
 *
27
 * You can access, add or remove an item with a key by using
28
 * {@link itemAt}, {@link add}, and {@link remove}.  These functions
29
 * can optionally take a priority parameter to allow access to specific
30
 * priorities.  TPriorityMap is functionally backward compatible
31
 * with {@link TMap}.
32
 *
33
 * To get the number of the items in the map, use {@link getCount}.
34
 * TPriorityMap can also be used like a regular array as follows,
35
 * <code>
36
 * $map[$key]=$value; // add a key-value pair
37
 * unset($map[$key]); // remove the value with the specified key
38
 * if(isset($map[$key])) // if the map contains the key
39
 * foreach($map as $key=>$value) // traverse the items in the map
40
 * $n=count($map);  // returns the number of items in the map
41
 * </code>
42
 * Using standard array access method like these will always use
43
 * the default priority.
44
 *
45
 * An item that doesn't specify a priority will receive the default
46
 * priority.  The default priority is set during the instantiation
47
 * of a new TPriorityMap. If no custom default priority is specified,
48
 * the standard default priority of 10 is used.
49
 *
50
 * Priorities with significant digits below precision will be rounded.
51
 *
52
 * A priority may also be a numeric with decimals.  This is set
53
 * during the instantiation of a new TPriorityMap.
54
 * The default is 8 decimal places for a priority.  If a negative number
55
 * is used, rounding occurs into the integer space rather than in
56
 * the decimal space.  See {@link round}.
57
 *
58
 * @author Brad Anderson <[email protected]>
59
 * @package Prado\Collections
60
 * @since 3.2a
61
 */
62
63
class TPriorityMap extends TMap
64
{
65
	/**
66
	 * @var array internal data storage
67
	 */
68
	private $_d = [];
69
	/**
70
	 * @var boolean whether this list is read-only
71
	 */
72
	private $_r = false;
73
	/**
74
	 * @var boolean indicates if the _d is currently ordered.
75
	 */
76
	private $_o = false;
77
	/**
78
	 * @var array cached flattened internal data storage
79
	 */
80
	private $_fd;
81
	/**
82
	 * @var integer number of items contain within the map
83
	 */
84
	private $_c = 0;
85
	/**
86
	 * @var numeric the default priority of items without specified priorities
0 ignored issues
show
Bug introduced by
The type Prado\Collections\numeric was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
87
	 */
88
	private $_dp = 10;
89
	/**
90
	 * @var integer the precision of the numeric priorities within this priority list.
91
	 */
92
	private $_p = 8;
93
94
	/**
95
	 * Constructor.
96
	 * Initializes the array with an array or an iterable object.
0 ignored issues
show
Bug introduced by
The type Prado\Collections\the was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
97
	 * @param map|array|Iterator|TPriorityMap the intial data. Default is null, meaning no initialization.
98
	 * @param boolean whether the list is read-only
0 ignored issues
show
Bug introduced by
The type Prado\Collections\whether was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
99
	 * @param numeric the default priority of items without specified priorities.
100
	 * @param integer the precision of the numeric priorities
101
	 * @throws TInvalidDataTypeException If data is not null and neither an array nor an iterator.
102
	 */
103
	public function __construct($data = null, $readOnly = false, $defaultPriority = 10, $precision = 8)
104
	{
105
		if($data !== null)
106
			$this->copyFrom($data);
107
		$this->setReadOnly($readOnly);
108
		$this->setPrecision($precision);
109
		$this->setDefaultPriority($defaultPriority);
110
	}
111
112
	/**
113
	 * @return boolean whether this map is read-only or not. Defaults to false.
114
	 */
115
	public function getReadOnly()
116
	{
117
		return $this->_r;
118
	}
119
120
	/**
121
	 * @param boolean whether this list is read-only or not
122
	 */
123
	protected function setReadOnly($value)
124
	{
125
		$this->_r = TPropertyValue::ensureBoolean($value);
126
	}
127
128
	/**
129
	 * @return numeric gets the default priority of inserted items without a specified priority
130
	 */
131
	public function getDefaultPriority()
132
	{
133
		return $this->_dp;
134
	}
135
136
	/**
137
	 * This must be called internally or when instantiated.
138
	 * @param numeric sets the default priority of inserted items without a specified priority
0 ignored issues
show
Bug introduced by
The type Prado\Collections\sets was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
139
	 */
140
	protected function setDefaultPriority($value)
141
	{
142
		$this->_dp = (string)round(TPropertyValue::ensureFloat($value), $this->_p);
0 ignored issues
show
Documentation Bug introduced by
It seems like (string)round(Prado\TPro...oat($value), $this->_p) of type string is incompatible with the declared type Prado\Collections\numeric of property $_dp.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
143
	}
144
145
	/**
146
	 * @return integer The precision of numeric priorities, defaults to 8
147
	 */
148
	public function getPrecision()
149
	{
150
		return $this->_p;
151
	}
152
153
	/**
154
	 * This must be called internally or when instantiated.
155
	 * @param integer The precision of numeric priorities.
0 ignored issues
show
Bug introduced by
The type Prado\Collections\The was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
156
	 */
157
	protected function setPrecision($value)
158
	{
159
		$this->_p = TPropertyValue::ensureInteger($value);
160
	}
161
162
	/**
163
	 * Returns an iterator for traversing the items in the map.
164
	 * This method is required by the interface \IteratorAggregate.
165
	 * @return Iterator an iterator for traversing the items in the map.
0 ignored issues
show
Bug introduced by
The type Prado\Collections\Iterator was not found. Did you mean Iterator? If so, make sure to prefix the type with \.
Loading history...
166
	 */
167
	public function getIterator()
168
	{
169
		return new \ArrayIterator($this->flattenPriorities());
0 ignored issues
show
Bug Best Practice introduced by
The expression return new ArrayIterator...s->flattenPriorities()) returns the type ArrayIterator which is incompatible with the documented return type Prado\Collections\Iterator.
Loading history...
170
	}
171
172
173
	/**
174
	 * Orders the priority list internally.
175
	 */
176
	protected function sortPriorities() {
177
		if(!$this->_o) {
178
			ksort($this->_d, SORT_NUMERIC);
179
			$this->_o = true;
180
		}
181
	}
182
183
	/**
184
	 * This flattens the priority map into a flat array [0,...,n-1]
185
	 * @return array array of items in the list in priority and index order
186
	 */
187
	protected function flattenPriorities() {
188
		if(is_array($this->_fd))
0 ignored issues
show
introduced by
The condition is_array($this->_fd) can never be false.
Loading history...
189
			return $this->_fd;
190
191
		$this->sortPriorities();
192
		$this->_fd = [];
193
		foreach($this->_d as $priority => $itemsatpriority)
194
			$this->_fd = array_merge($this->_fd, $itemsatpriority);
195
		return $this->_fd;
196
	}
197
198
	/**
199
	 * Returns the number of items in the map.
200
	 * This method is required by \Countable interface.
201
	 * @return integer number of items in the map.
202
	 */
203
	public function count()
204
	{
205
		return $this->getCount();
206
	}
207
208
	/**
209
	 * @return integer the number of items in the map
210
	 */
211
	public function getCount()
212
	{
213
		return $this->_c;
214
	}
215
216
	/**
217
	 * Gets the number of items at a priority within the map.
218
	 * @param numeric optional priority at which to count items.  if no parameter,
0 ignored issues
show
Bug introduced by
The type Prado\Collections\optional was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
219
	 * it will be set to the default {@link getDefaultPriority}
220
	 * @return integer the number of items in the map at the specified priority
221
	 */
222
	public function getPriorityCount($priority = null)
223
	{
224
		if($priority === null)
225
			$priority = $this->getDefaultPriority();
226
		$priority = (string)round(TPropertyValue::ensureFloat($priority), $this->_p);
227
228
		if(!isset($this->_d[$priority]) || !is_array($this->_d[$priority]))
229
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type integer.
Loading history...
230
		return count($this->_d[$priority]);
231
	}
232
233
	/**
234
	 * This returns a list of the priorities within this map, ordered lowest to highest.
235
	 * @return array the array of priority numerics in decreasing priority order
236
	 */
237
	public function getPriorities()
238
	{
239
		$this->sortPriorities();
240
		return array_keys($this->_d);
241
	}
242
243
	/**
244
	 * Returns the keys within the map ordered through the priority of each key-value pair
245
	 * @return array the key list
246
	 */
247
	public function getKeys()
248
	{
249
		return array_keys($this->flattenPriorities());
250
	}
251
252
	/**
253
	 * Returns the item with the specified key.  If a priority is specified, only items
254
	 * within that specific priority will be selected
255
	 * @param mixed the key
256
	 * @param mixed the priority.  null is the default priority, false is any priority,
257
	 * and numeric is a specific priority.  default: false, any priority.
258
	 * @return mixed the element at the offset, null if no element is found at the offset
259
	 */
260
	public function itemAt($key, $priority = false)
261
	{
262
		if($priority === false){
263
			$map = $this->flattenPriorities();
264
			return isset($map[$key])?$map[$key]:null;
265
		} else {
266
			if($priority === null)
267
				$priority = $this->getDefaultPriority();
268
			$priority = (string)round(TPropertyValue::ensureFloat($priority), $this->_p);
269
			return (isset($this->_d[$priority]) && isset($this->_d[$priority][$key]))?$this->_d[$priority][$key]:null;
270
		}
271
	}
272
273
	/**
274
	 * This changes an item's priority.  Specify the item and the new priority.
275
	 * This method is exactly the same as {@link offsetGet}.
276
	 * @param mixed the key
277
	 * @param numeric|null the priority.  default: null, filled in with the default priority numeric.
278
	 * @return numeric old priority of the item
279
	 */
280
	public function setPriorityAt($key, $priority = null)
281
	{
282
		if($priority === null)
283
			$priority = $this->getDefaultPriority();
284
		$priority = (string)round(TPropertyValue::ensureFloat($priority), $this->_p);
285
286
		$oldpriority = $this->priorityAt($key);
287
		if($oldpriority !== false && $oldpriority != $priority) {
0 ignored issues
show
introduced by
The condition $oldpriority !== false &...ldpriority != $priority can never be false.
Loading history...
288
			$value = $this->remove($key, $oldpriority);
289
			$this->add($key, $value, $priority);
290
		}
291
		return $oldpriority;
292
	}
293
294
	/**
295
	 * Gets all the items at a specific priority.
0 ignored issues
show
Bug introduced by
The type Prado\Collections\priority was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
296
	 * @param numeric priority of the items to get.  Defaults to null, filled in with the default priority, if left blank.
297
	 * @return array all items at priority in index order, null if there are no items at that priority
298
	 */
299
	public function itemsAtPriority($priority = null)
300
	{
301
		if($priority === null)
302
			$priority = $this->getDefaultPriority();
303
		$priority = (string)round(TPropertyValue::ensureFloat($priority), $this->_p);
304
305
		return isset($this->_d[$priority])?$this->_d[$priority]:null;
306
	}
307
308
	/**
309
	 * Returns the priority of a particular item within the map.  This searches the map for the item.
0 ignored issues
show
Bug introduced by
The type Prado\Collections\item was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
310
	 * @param mixed item to look for within the map
311
	 * @return numeric priority of the item in the map
312
	 */
313
	public function priorityOf($item)
314
	{
315
		$this->sortPriorities();
316
		foreach($this->_d as $priority => $items)
317
			if(($index = array_search($item, $items, true)) !== false)
0 ignored issues
show
Unused Code introduced by
The assignment to $index is dead and can be removed.
Loading history...
318
				return $priority;
319
		return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type Prado\Collections\numeric.
Loading history...
320
	}
321
322
	/**
323
	 * Retutrns the priority of an item at a particular flattened index.
0 ignored issues
show
Bug introduced by
The type Prado\Collections\index was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
324
	 * @param integer index of the item within the map
325
	 * @return numeric priority of the item in the map
326
	 */
327
	public function priorityAt($key)
328
	{
329
		$this->sortPriorities();
330
		foreach($this->_d as $priority => $items)
331
			if(array_key_exists($key, $items))
332
				return $priority;
333
		return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type Prado\Collections\numeric.
Loading history...
334
	}
335
336
	/**
337
	 * Adds an item into the map.  A third parameter may be used to set the priority
338
	 * of the item within the map.  Priority is primarily used during when flattening
339
	 * the map into an array where order may be and important factor of the key-value
0 ignored issues
show
Bug introduced by
The type Prado\Collections\value was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
340
	 * pairs within the array.
341
	 * Note, if the specified key already exists, the old value will be overwritten.
342
	 * No duplicate keys are allowed regardless of priority.
343
	 * @param mixed key
344
	 * @param mixed value
345
	 * @param numeric|null priority, default: null, filled in with default priority
346
	 * @return numeric priority at which the pair was added
347
	 * @throws TInvalidOperationException if the map is read-only
348
	 */
349
	public function add($key, $value, $priority = null)
350
	{
351
		if($priority === null)
352
			$priority = $this->getDefaultPriority();
353
		$priority = (string)round(TPropertyValue::ensureFloat($priority), $this->_p);
354
355
		if(!$this->_r)
356
		{
357
			foreach($this->_d as $innerpriority => $items)
358
				if(array_key_exists($key, $items))
359
				{
360
					unset($this->_d[$innerpriority][$key]);
361
					$this->_c--;
362
					if(count($this->_d[$innerpriority]) === 0)
363
						unset($this->_d[$innerpriority]);
364
				}
365
			if(!isset($this->_d[$priority])) {
366
				$this->_d[$priority] = [$key => $value];
367
				$this->_o = false;
368
			}
369
			else
370
				$this->_d[$priority][$key] = $value;
371
			$this->_c++;
372
			$this->_fd = null;
373
		}
374
		else
375
			throw new TInvalidOperationException('map_readonly', get_class($this));
376
		return $priority;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $priority returns the type string which is incompatible with the documented return type Prado\Collections\numeric.
Loading history...
377
	}
378
379
	/**
380
	 * Removes an item from the map by its key. If no priority, or false, is specified
381
	 * then priority is irrelevant. If null is used as a parameter for priority, then
382
	 * the priority will be the default priority.  If a priority is specified, or
383
	 * the default priority is specified, only key-value pairs in that priority
384
	 * will be affected.
385
	 * @param mixed the key of the item to be removed
386
	 * @param numeric|false|null priority.  False is any priority, null is the
387
	 * default priority, and numeric is a specific priority
388
	 * @return mixed the removed value, null if no such key exists.
389
	 * @throws TInvalidOperationException if the map is read-only
390
	 */
0 ignored issues
show
Documentation Bug introduced by
The doc comment priority. at position 0 could not be parsed: Unknown type name 'priority.' at position 0 in priority..
Loading history...
391
	public function remove($key, $priority = false)
392
	{
393
		if(!$this->_r)
394
		{
395
			if($priority === null)
396
				$priority = $this->getDefaultPriority();
397
398
			if($priority === false)
399
			{
400
				$this->sortPriorities();
401
				foreach($this->_d as $priority => $items)
402
					if(array_key_exists($key, $items))
403
					{
404
						$value = $this->_d[$priority][$key];
405
						unset($this->_d[$priority][$key]);
406
						$this->_c--;
407
						if(count($this->_d[$priority]) === 0)
408
						{
409
							unset($this->_d[$priority]);
410
							$this->_o = false;
411
						}
412
						$this->_fd = null;
413
						return $value;
414
					}
415
				return null;
416
			}
417
			else
418
			{
419
				$priority = (string)round(TPropertyValue::ensureFloat($priority), $this->_p);
420
				if(isset($this->_d[$priority]) && (isset($this->_d[$priority][$key]) || array_key_exists($key, $this->_d[$priority])))
421
				{
422
					$value = $this->_d[$priority][$key];
423
					unset($this->_d[$priority][$key]);
424
					$this->_c--;
425
					if(count($this->_d[$priority]) === 0) {
426
						unset($this->_d[$priority]);
427
						$this->_o = false;
428
					}
429
					$this->_fd = null;
430
					return $value;
431
				}
432
				else
433
					return null;
434
			}
435
		}
436
		else
437
			throw new TInvalidOperationException('map_readonly', get_class($this));
438
	}
439
440
	/**
441
	 * Removes all items in the map.  {@link remove} is called on all items.
442
	 */
443
	public function clear()
444
	{
445
		foreach($this->_d as $priority => $items)
446
			foreach(array_keys($items) as $key)
447
				$this->remove($key);
448
	}
449
450
	/**
451
	 * @param mixed the key
452
	 * @return boolean whether the map contains an item with the specified key
453
	 */
454
	public function contains($key)
455
	{
456
		$map = $this->flattenPriorities();
457
		return isset($map[$key]) || array_key_exists($key, $map);
458
	}
459
460
	/**
461
	 * When the map is flattened into an array, the priorities are taken into
462
	 * account and elements of the map are ordered in the array according to
463
	 * their priority.
464
	 * @return array the list of items in array
465
	 */
466
	public function toArray()
467
	{
468
		return $this->flattenPriorities();
469
	}
470
471
	/**
472
	 * Combines the map elements which have a priority below the parameter value
473
	 * @param numeric the cut-off priority.  All items of priority less than this are returned.
474
	 * @param boolean whether or not the input cut-off priority is inclusive.  Default: false, not inclusive.
475
	 * @return array the array of priorities keys with values of arrays of items that are below a specified priority.
476
	 *  The priorities are sorted so important priorities, lower numerics, are first.
477
	 */
478
	public function toArrayBelowPriority($priority, $inclusive = false)
479
	{
480
		$this->sortPriorities();
481
		$items = [];
482
		foreach($this->_d as $itemspriority => $itemsatpriority)
483
		{
484
			if((!$inclusive && $itemspriority >= $priority) || $itemspriority > $priority)
485
				break;
486
			$items = array_merge($items, $itemsatpriority);
487
		}
488
		return $items;
489
	}
490
491
	/**
492
	 * Combines the map elements which have a priority above the parameter value
493
	 * @param numeric the cut-off priority.  All items of priority greater than this are returned.
494
	 * @param boolean whether or not the input cut-off priority is inclusive.  Default: true, inclusive.
495
	 * @return array the array of priorities keys with values of arrays of items that are above a specified priority.
496
	 *  The priorities are sorted so important priorities, lower numerics, are first.
497
	 */
498
	public function toArrayAbovePriority($priority, $inclusive = true)
499
	{
500
		$this->sortPriorities();
501
		$items = [];
502
		foreach($this->_d as $itemspriority => $itemsatpriority)
503
		{
504
			if((!$inclusive && $itemspriority <= $priority) || $itemspriority < $priority)
505
				continue;
506
			$items = array_merge($items, $itemsatpriority);
507
		}
508
		return $items;
509
	}
510
511
	/**
512
	 * Copies iterable data into the map.
513
	 * Note, existing data in the map will be cleared first.
514
	 * @param mixed the data to be copied from, must be an array, object implementing
515
	 * Traversable, or a TPriorityMap
516
	 * @throws TInvalidDataTypeException If data is neither an array nor an iterator.
517
	 */
518
	public function copyFrom($data)
519
	{
520
		if($data instanceof TPriorityMap)
521
		{
522
			if($this->getCount() > 0)
523
				$this->clear();
524
			foreach($data->getPriorities() as $priority) {
525
				foreach($data->itemsAtPriority($priority) as $key => $value) {
526
					$this->add($key, $value, $priority);
527
				}
528
			}
529
		}
530
		elseif(is_array($data) || $data instanceof \Traversable)
531
		{
532
			if($this->getCount() > 0)
533
				$this->clear();
534
			foreach($data as $key => $value)
535
				$this->add($key, $value);
536
		}
537
		elseif($data !== null)
538
			throw new TInvalidDataTypeException('map_data_not_iterable');
539
	}
540
541
	/**
542
	 * Merges iterable data into the map.
543
	 * Existing data in the map will be kept and overwritten if the keys are the same.
544
	 * @param mixed the data to be merged with, must be an array, object implementing
545
	 * Traversable, or a TPriorityMap
546
	 * @throws TInvalidDataTypeException If data is neither an array nor an iterator.
547
	 */
548
	public function mergeWith($data)
549
	{
550
		if($data instanceof TPriorityMap)
551
		{
552
			foreach($data->getPriorities() as $priority)
553
			{
554
				foreach($data->itemsAtPriority($priority) as $key => $value)
555
					$this->add($key, $value, $priority);
556
			}
557
		}
558
		elseif(is_array($data) || $data instanceof \Traversable)
559
		{
560
			foreach($data as $key => $value)
561
				$this->add($key, $value);
562
		}
563
		elseif($data !== null)
564
			throw new TInvalidDataTypeException('map_data_not_iterable');
565
	}
566
567
	/**
568
	 * Returns whether there is an element at the specified offset.
569
	 * This method is required by the interface \ArrayAccess.
570
	 * @param mixed the offset to check on
571
	 * @return boolean
572
	 */
573
	public function offsetExists($offset)
574
	{
575
		return $this->contains($offset);
576
	}
577
578
	/**
579
	 * Returns the element at the specified offset.
580
	 * This method is required by the interface \ArrayAccess.
581
	 * @param integer the offset to retrieve element.
582
	 * @return mixed the element at the offset, null if no element is found at the offset
583
	 */
584
	public function offsetGet($offset)
585
	{
586
		return $this->itemAt($offset);
587
	}
588
589
	/**
590
	 * Sets the element at the specified offset.
591
	 * This method is required by the interface \ArrayAccess.
592
	 * @param integer the offset to set element
593
	 * @param mixed the element value
594
	 */
595
	public function offsetSet($offset, $item)
596
	{
597
		$this->add($offset, $item);
598
	}
599
600
	/**
601
	 * Unsets the element at the specified offset.
602
	 * This method is required by the interface \ArrayAccess.
603
	 * @param mixed the offset to unset element
604
	 */
605
	public function offsetUnset($offset)
606
	{
607
		$this->remove($offset);
608
	}
609
}