Passed
Push — master ( 04e442...6900bc )
by Fabio
04:44
created

TPriorityList::copyFrom()   C

Complexity

Conditions 14
Paths 18

Size

Total Lines 31
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 14.0891

Importance

Changes 0
Metric Value
cc 14
eloc 21
c 0
b 0
f 0
nc 18
nop 1
dl 0
loc 31
rs 6.2666
ccs 12
cts 13
cp 0.9231
crap 14.0891

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * TPriorityList class
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
 */
9
10
namespace Prado\Collections;
11
12
use Prado\Exceptions\TInvalidDataTypeException;
13
use Prado\Exceptions\TInvalidDataValueException;
14
use Prado\Exceptions\TInvalidOperationException;
15
use Prado\TPropertyValue;
16
17
/**
18
 * TPriorityList class
19
 *
20
 * TPriorityList implements a priority ordered list collection class.  It allows you to specify
21
 * any numeric for priorities down to a specific precision.  The lower the numeric, the high the priority of the item in the
22
 * list.  Thus -10 has a higher priority than -5, 0, 10 (the default), 18, 10005, etc.  Per {@link round}, precision may be negative and
23
 * thus rounding can go by 10, 100, 1000, etc, instead of just .1, .01, .001, etc. The default precision allows for 8 decimal
24
 * places. There is also a default priority of 10, if no different default priority is specified or no item specific priority is indicated.
25
 * If you replace TList with this class it will  work exactly the same with items inserted set to the default priority, until you start
26
 * using different priorities than the default priority.
27
 *
28
 * As you access the PHP array features of this class, it flattens and caches the results.  If at all possible, this
29
 * will keep the cache fresh even when manipulated.  If this is not possible the cache is cleared.
30
 * When an array of items are needed and the cache is outdated, the cache is recreated from the items and their priorities
31
 *
32
 * You can access, append, insert, remove an item by using
33
 * {@link itemAt}, {@link add}, {@link insertAt}, and {@link remove}.
34
 * To get the number of the items in the list, use {@link getCount}.
35
 * TPriorityList can also be used like a regular array as follows,
36
 * <code>
37
 * $list[]=$item;  // append with the default priority.  It may not be the last item if other items in the list are prioritized after the default priority
38
 * $list[$index]=$item; // $index must be between 0 and $list->Count-1.  This sets the element regardless of priority.  Priority stays the same.
39
 * $list[$index]=$item; // $index is $list->Count.  This appends the item to the end of the list with the same priority as the last item in the list.
40
 * unset($list[$index]); // remove the item at $index
41
 * if(isset($list[$index])) // if the list has an item at $index
42
 * foreach($list as $index=>$item) // traverse each item in the list in proper priority order and add/insert order
43
 * $n=count($list); // returns the number of items in the list
44
 * </code>
45
 *
46
 * To extend TPriorityList for doing your own operations with each addition or removal,
47
 * override {@link insertAtIndexInPriority()} and {@link removeAtIndexInPriority()} and then call the parent.
48
 *
49
 * @author Brad Anderson <[email protected]>
50
 * @since 3.2a
51
 */
52
class TPriorityList extends TList
53
{
54
	use TPriorityCollectionTrait;
55
56
	/**
57
	 * Constructor.
58
	 * Initializes the list with an array or an iterable object.
59
	 * @param null|array|\Iterator $data the initial data. Default is null, meaning no initial data.
60
	 * @param bool $readOnly whether the list is read-only
61
	 * @param numeric $defaultPriority 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...
62
	 * @param int $precision the precision of the numeric priorities
63
	 * @throws TInvalidDataTypeException If data is not null and is neither an array nor an iterator.
64
	 */
65
	public function __construct($data = null, $readOnly = false, $defaultPriority = 10, $precision = 8)
66
	{
67
		$this->setPrecision($precision);
68
		$this->setDefaultPriority($defaultPriority);
0 ignored issues
show
Bug introduced by
It seems like $defaultPriority can also be of type integer; however, parameter $value of Prado\Collections\TPrior...t::setDefaultPriority() does only seem to accept Prado\Collections\numeric, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

68
		$this->setDefaultPriority(/** @scrutinizer ignore-type */ $defaultPriority);
Loading history...
69
		parent::__construct($data, $readOnly);
70
	}
71
72
	/**
73
	 * Returns the item at the index of a flattened priority list.
74
	 * {@link offsetGet} calls this method.
75
	 * @param int $index the index of the item to get
76
	 * @throws TInvalidDataValueException Issued when the index is invalid
77
	 * @return mixed the element at the offset
78
	 */
79
	public function itemAt($index)
80
	{
81
		if ($index >= 0 && $index < $this->getCount()) {
82
			$this->flattenPriorities();
83
			return $this->_fd[$index];
84
		} else {
85
			throw new TInvalidDataValueException('list_index_invalid', $index);
86
		}
87
	}
88
89
	/**
90 90
	 * Returns the item at an index within a priority
91
	 * @param int $index the index into the list of items at priority
92 90
	 * @param null|numeric $priority the priority which to index.  no parameter or null
93 90
	 *   will result in the default priority
94 25
	 * @throws TInvalidDataValueException if the index is out of the range at the
95
	 *   priority or no items at the priority.
96 90
	 * @return mixed the element at the offset, false if no element is found at the offset
97 90
	 */
98 90
	public function itemAtIndexInPriority($index, $priority = null)
99 90
	{
100
		$priority = $this->ensurePriority($priority);
101
		if (isset($this->_d[$priority]) && 0 <= $index && $index < count($this->_d[$priority])) {
102
			return $this->_d[$priority][$index];
103
		} else {
104
			throw new TInvalidDataValueException('prioritylist_index_invalid', $index, count($this->_d[$priority] ?? []), $priority);
105
		}
106 3
	}
107
108 3
	/**
109
	 * Appends an item into the list at the end of the specified priority.  The position of the added item may
110
	 * not be at the end of the list.
111
	 * @param mixed $item item to add into the list at priority
112
	 * @param null|numeric $priority priority blank or null for the default priority
113
	 * @throws TInvalidOperationException if the map is read-only
114
	 * @return int the index within the flattened array
115 133
	 */
116
	public function add($item, $priority = null)
117 133
	{
118
		if ($this->getReadOnly()) {
119
			throw new TInvalidOperationException('list_readonly', $this::class);
120
		}
121
122
		return $this->insertAtIndexInPriority($item, false, $priority, true);
123
	}
124
125 2
	/**
126
	 * Inserts an item at an index.  It reads the priority of the item at index within the flattened list
127 2
	 * and then inserts the item at that priority-index.
128 2
	 * @param int $index the specified position in the flattened list.
129
	 * @param mixed $item new item to add
130 2
	 * @throws TInvalidDataValueException If the index specified exceeds the bound
131
	 * @throws TInvalidOperationException if the list is read-only
132 2
	 */
133
	public function insertAt($index, $item)
134
	{
135 2
		if ($this->getReadOnly()) {
136
			throw new TInvalidOperationException('list_readonly', $this::class);
137
		}
138
139
		if (($priority = $this->priorityAt($index, true)) !== false) {
140
			$this->insertAtIndexInPriority($item, $priority[1], $priority[0]);
141 116
		} else {
142
			throw new TInvalidDataValueException('list_index_invalid', $index);
143 116
		}
144
	}
145
146
	/**
147
	 * Inserts an item at the specified index within a priority.  Override and call this method to
148
	 * insert your own functionality.
149
	 * @param mixed $item item to add within the list.
150 90
	 * @param false|int $index index within the priority to add the item, defaults to false which appends the item at the priority
151
	 * @param null|numeric $priority priority of the item.  defaults to null, which sets it to the default priority
152 90
	 * @param bool $preserveCache preserveCache specifies if this is a special quick function or not. This defaults to false.
153 90
	 * @throws TInvalidDataValueException If the index specified exceeds the bound
154
	 * @throws TInvalidOperationException if the list is read-only
155
	 */
156
	public function insertAtIndexInPriority($item, $index = false, $priority = null, $preserveCache = false)
157
	{
158 1
		if ($this->getReadOnly()) {
159
			throw new TInvalidOperationException('list_readonly', $this::class);
160 1
		}
161
162
		$itemPriority = null;
163
		if (($isPriorityItem = ($item instanceof IPriorityItem)) && ($priority === null || !is_numeric($priority))) {
164
			$itemPriority = $priority = $item->getPriority();
165
		}
166
		$priority = $this->ensurePriority($priority);
167 90
		if (($item instanceof IPriorityCapture) && (!$isPriorityItem || $itemPriority !== $priority)) {
168
			$item->setPriority($priority);
0 ignored issues
show
Bug introduced by
$priority of type string is incompatible with the type Prado\Collections\numeric expected by parameter $value of Prado\Collections\IPriorityCapture::setPriority(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

168
			$item->setPriority(/** @scrutinizer ignore-type */ $priority);
Loading history...
169 90
		}
170 90
171
		if (isset($this->_d[$priority])) {
172
			if ($index === false) {
173
				$c = count($this->_d[$priority]);
174
				$this->_d[$priority][] = $item;
175
			} elseif (0 <= $index && $index <= count($this->_d[$priority])) {
176
				$c = $index;
177 2
				array_splice($this->_d[$priority], $index, 0, [$item]);
178
			} else {
179 2
				throw new TInvalidDataValueException('prioritylist_index_invalid', $index, count($this->_d[$priority] ?? []), $priority);
180
			}
181
		} elseif ($index === 0 || $index === false) {
182
			$c = 0;
183
			$this->_o = false;
184
			$this->_d[$priority] = [$item];
185
		} else {
186 16
			throw new TInvalidDataValueException('prioritylist_index_invalid', $index, 0, $priority);
187
		}
188 16
189 16
		if ($preserveCache) {
190
			if ($this->_fd !== null) {
191
				$this->sortPriorities();
192
				foreach ($this->_d as $prioritykey => $items) {
193
					if ($prioritykey >= $priority) {
194
						break;
195
					} else {
196 121
						$c += count($items);
197
					}
198 121
				}
199 112
				array_splice($this->_fd, $c, 0, [$item]);
200 112
			}
201
		} else {
202 121
			if ($this->_fd !== null && count($this->_d) == 1) {
203
				array_splice($this->_fd, $c, 0, [$item]);
204
			} else {
205
				$this->_fd = null;
206
				$c = null;
207
			}
208 93
		}
209
210 93
		$this->_c++;
211 68
212
		return $c;
213
	}
214 59
215 59
216 59
	/**
217 56
	 * Removes an item from the priority list.
218
	 * The list will search for the item.  The first matching item found will be removed from the list.
219 59
	 * @param mixed $item item the item to be removed.
220
	 * @param null|bool|float $priority priority of item to remove. without this parameter it defaults to false.
221
	 * A value of false means any priority. null will be filled in with the default priority.
222
	 * @throws TInvalidDataValueException If the item does not exist
223
	 * @return int index within the flattened list at which the item is being removed
224
	 */
225
	public function remove($item, $priority = false)
226
	{
227
		if ($this->getReadOnly()) {
228
			throw new TInvalidOperationException('list_readonly', $this::class);
229
		}
230 8
231
		if (($p = $this->priorityOf($item, true)) !== false) {
232 8
			if ($priority !== false) {
233 8
				$priority = $this->ensurePriority($priority);
234 8
				if ($p[0] != $priority) {
235
					throw new TInvalidDataValueException('list_item_inexistent');
236 2
				}
237
			}
238
			$this->removeAtIndexInPriority($p[1], $p[0]);
239
			return $p[2];
240
		} else {
241
			throw new TInvalidDataValueException('list_item_inexistent');
242
		}
243
	}
244
245 16
	/**
246
	 * Removes an item at the specified index in the flattened list.
247 16
	 * @param int $index index of the item to be removed.
248 1
	 * @throws TInvalidDataValueException If the index specified exceeds the bound
249
	 * @throws TInvalidOperationException if the list is read-only
250 16
	 * @return mixed the removed item.
251
	 */
252 16
	public function removeAt($index)
253
	{
254
		if ($this->getReadOnly()) {
255
			throw new TInvalidOperationException('list_readonly', $this::class);
256
		}
257
258
		if (($priority = $this->priorityAt($index, true)) !== false) {
259
			return $this->removeAtIndexInPriority($priority[1], $priority[0]);
260
		}
261 1
		throw new TInvalidDataValueException('list_index_invalid', $index);
262
	}
263 1
264 1
	/**
265
	 * Removes the item at a specific index within a priority.  Override
266 1
	 * and call this method to insert your own functionality.
267
	 * @param int $index index of item to remove within the priority.
268 1
	 * @param null|numeric $priority priority of the item to remove, defaults to null, or left blank, it is then set to the default priority
269 1
	 * @throws TInvalidDataValueException If the item does not exist
270
	 * @return mixed the removed item.
271
	 */
272
	public function removeAtIndexInPriority($index, $priority = null)
273
	{
274
		if ($this->getReadOnly()) {
275
			throw new TInvalidOperationException('list_readonly', $this::class);
276
		}
277
278
		$priority = $this->ensurePriority($priority);
279
		if (!isset($this->_d[$priority]) || $index < 0 || $index >= ($c = count($this->_d[$priority]))) {
280
			throw new TInvalidDataValueException('list_item_inexistent');
281 116
		}
282
283 116
		if ($index === $c - 1) {
284 1
			$value = array_pop($this->_d[$priority]);
285
		} else {
286
			$value = array_splice($this->_d[$priority], $index, 1);
287 116
			$value = $value[0];
288
		}
289
		if (!count($this->_d[$priority])) {
290
			unset($this->_d[$priority]);
291
		}
292
293
		$this->_c--;
294
		$this->_fd = null;
295
		return $value;
296
	}
297
298 3
	/**
299
	 * Removes all items in the priority list by calling removeAtIndexInPriority from the last item to the first.
300 3
	 */
301 1
	public function clear(): void
302
	{
303
		if ($this->getReadOnly()) {
304 2
			throw new TInvalidOperationException('list_readonly', $this::class);
305 2
		}
306
307
		foreach (array_keys($this->_d) as $priority) {
308
			for ($index = count($this->_d[$priority]) - 1; $index >= 0; $index--) {
309 2
				$this->removeAtIndexInPriority($index, $priority);
310
			}
311
		}
312
	}
313
314
	/**
315
	 * @param mixed $item item
316
	 * @return int the index of the item in the flattened list (0 based), -1 if not found.
317
	 */
318
	public function indexOf($item)
319
	{
320
		$this->flattenPriorities();
321 116
		if (($index = array_search($item, $this->_fd, true)) === false) {
0 ignored issues
show
Bug introduced by
It seems like $this->_fd can also be of type null; however, parameter $haystack of array_search() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

321
		if (($index = array_search($item, /** @scrutinizer ignore-type */ $this->_fd, true)) === false) {
Loading history...
322
			return -1;
323 116
		} else {
324 1
			return $index;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $index also could return the type string which is incompatible with the documented return type integer.
Loading history...
325
		}
326
	}
327 116
328 116
	/**
329
	 * Returns the priority of a particular item
330 116
	 * @param mixed $item the item to look for within the list
331
	 * @param bool $withindex this specifies if the full positional data of the item within the list is returned.
332 116
	 * 		This defaults to false, if no parameter is provided, so only provides the priority number of the item by default.
333 116
	 * @return array|false|numeric the priority of the item in the list, false if not found.
334 116
	 *   if $withindex is true, an array is returned of [0 => $priority, 1 => $priorityIndex, 2 => flattenedIndex,
335 116
	 * 'priority' => $priority, 'index' => $priorityIndex, 'absindex' => flattenedIndex]
336 89
	 */
337 89
	public function priorityOf($item, $withindex = false)
338
	{
339 65
		$this->sortPriorities();
340
341
		$absindex = 0;
342
		foreach (array_keys($this->_d) as $priority) {
343 116
			if (($index = array_search($item, $this->_d[$priority], true)) !== false) {
344 89
				$absindex += $index;
345 89
				return $withindex ? [$priority, $index, $absindex,
346 89
						'priority' => $priority, 'index' => $index, 'absindex' => $absindex, ] : $priority;
347 106
			} else {
348 1
				$absindex += count($this->_d[$priority]);
349 1
			}
350
		}
351 106
352 106
		return false;
353 106
	}
354
355
	/**
356 116
	 * Returns the priority of an item at a particular flattened index.  The index after
357 116
	 * the last item does not exist but receives a priority from the last item so that
358
	 * priority information about any new items being appended is available.
359
	 * @param int $index index of the item within the list
360 20
	 * @param bool $withindex this specifies if the full positional data of the item within the list is returned.
361 20
	 * 		This defaults to false, if no parameter is provided, so only provides the priority number of the item by default.
362 2
	 * @return array|false|numeric the priority of the item in the list, false if not found.
363 2
	 *   if $withindex is true, an array is returned of [0 => $priority, 1 => $priorityIndex, 2 => flattenedIndex,
364 20
	 * 'priority' => $priority, 'index' => $priorityIndex, 'absindex' => flattenedIndex]
365 18
	 */
366 18
	public function priorityAt($index, $withindex = false)
367
	{
368 17
		if (0 <= $index && $index <= $this->_c) {
369 17
			$c = $absindex = $index;
370 17
			$priority = null;
371
			$this->sortPriorities();
372 20
			foreach (array_keys($this->_d) as $priority) {
373 1
				if ($index >= ($c = count($this->_d[$priority]))) {
374
					$index -= $c;
375 20
				} else {
376
					return $withindex ? [$priority, $index, $absindex,
377
							'priority' => $priority, 'index' => $index, 'absindex' => $absindex, ] : $priority;
378
				}
379 116
			}
380
			return $withindex ? [$priority, $c, $absindex,
381 116
					'priority' => $priority, 'index' => $c, 'absindex' => $absindex, ] : $priority;
382
		}
383
		return false;
384
	}
385
386
	/**
387
	 * This inserts an item before another item within the list.  It uses the same priority as the
388
	 * found index item and places the new item before it.
389
	 * @param mixed $indexitem the item to index
390
	 * @param mixed $item the item to add before indexitem
391
	 * @throws TInvalidDataValueException If the item does not exist
392
	 * @return int where the item has been inserted in the flattened list
393
	 */
394 41
	public function insertBefore($indexitem, $item)
395
	{
396 41
		if ($this->getReadOnly()) {
397 1
			throw new TInvalidOperationException('list_readonly', $this::class);
398
		}
399
400 40
		if (($priority = $this->priorityOf($indexitem, true)) === false) {
401 40
			throw new TInvalidDataValueException('list_item_inexistent');
402 1
		}
403 1
404
		$this->insertAtIndexInPriority($item, $priority[1], $priority[0]);
405 1
406
		return $priority[2];
407 1
	}
408 1
409
	/**
410
	 * This inserts an item after another item within the list.  It uses the same priority as the
411 40
	 * found index item and places the new item after it.
412 40
	 * @param mixed $indexitem the item to index
413
	 * @param mixed $item the item to add after indexitem
414 2
	 * @throws TInvalidDataValueException If the item does not exist
415
	 * @return int where the item has been inserted in the flattened list
416
	 */
417
	public function insertAfter($indexitem, $item)
418
	{
419
		if ($this->getReadOnly()) {
420
			throw new TInvalidOperationException('list_readonly', $this::class);
421
		}
422
423
		if (($priority = $this->priorityOf($indexitem, true)) === false) {
424
			throw new TInvalidDataValueException('list_item_inexistent');
425 5
		}
426
427 5
		$this->insertAtIndexInPriority($item, $priority[1] + 1, $priority[0]);
428 1
429
		return $priority[2] + 1;
430
	}
431 4
432 4
	/**
433
	 * Copies iterable data into the priority list.
434
	 * Note, existing data in the map will be cleared first.
435
	 * @param mixed $data the data to be copied from, must be an array or object implementing Traversable
436
	 * @throws TInvalidDataTypeException If data is neither an array nor an iterator.
437
	 */
438
	public function copyFrom($data): void
439
	{
440
		if ($data instanceof TPriorityList) {
441
			if ($this->getCount() > 0) {
442
				$this->clear();
443
			}
444
			$array = $data->toPriorityArray();
445 51
			foreach (array_keys($array) as $priority) {
446
				for ($i = 0, $c = count($array[$priority]); $i < $c; $i++) {
447 51
					$this->insertAtIndexInPriority($array[$priority][$i], false, $priority);
448 1
				}
449
			}
450
		} elseif ($data instanceof TPriorityMap) {
451 50
			if ($this->getCount() > 0) {
452
				$this->clear();
453
			}
454 50
			$array = $data->toPriorityArray();
455
			foreach (array_keys($array) as $priority) {
456 50
				foreach ($array[$priority] as $item) {
457 1
					$this->insertAtIndexInPriority($item, false, $priority);
458
				}
459
			}
460
		} elseif (is_array($data) || $data instanceof \Traversable) {
461 49
			if ($this->getCount() > 0) {
462 49
				$this->clear();
463
			}
464 49
			foreach ($data as $item) {
465 30
				$this->insertAtIndexInPriority($item);
466
			}
467
		} elseif ($data !== null) {
468 49
			throw new TInvalidDataTypeException('map_data_not_iterable');
469 49
		}
470 49
	}
471
472
	/**
473
	 * Merges iterable data into the priority list.
474
	 * New data will be appended to the end of the existing data.  If another TPriorityList is merged,
475
	 * the incoming parameter items will be appended at the priorities they are present.  These items will be added
476 7
	 * to the end of the existing items with equal priorities, if there are any.
477
	 * @param mixed $data the data to be merged with, must be an array or object implementing Traversable
478 7
	 * @throws TInvalidDataTypeException If data is neither an array nor an iterator.
479 1
	 */
480
	public function mergeWith($data): void
481
	{
482 6
		if ($data instanceof TPriorityList) {
483 6
			$array = $data->toPriorityArray();
484 6
			foreach (array_keys($array) as $priority) {
485
				for ($i = 0, $c = count($array[$priority]); $i < $c; $i++) {
486 6
					$this->insertAtIndexInPriority($array[$priority][$i], false, $priority);
487
				}
488 6
			}
489
		} elseif ($data instanceof TPriorityMap) {
490
			$array = $data->toPriorityArray();
491
			foreach (array_keys($array) as $priority) {
492
				foreach ($array[$priority] as $item) {
493
					$this->insertAtIndexInPriority($item, false, $priority);
494 2
				}
495
			}
496 2
		} elseif (is_array($data) || $data instanceof \Traversable) {
497
			foreach ($data as $item) {
498
				$this->insertAtIndexInPriority($item);
499
			}
500
		} elseif ($data !== null) {
501
			throw new TInvalidDataTypeException('map_data_not_iterable');
502
		}
503 13
	}
504
505 13
	/**
506 11
	 * Returns whether there is an element at the specified offset.
507
	 * This method is required by the interface \ArrayAccess.
508 11
	 * @param mixed $offset the offset to check on
509
	 * @return bool
510
	 */
511
	public function offsetExists($offset): bool
512
	{
513
		return ($offset >= 0 && $offset < $this->getCount());
514
	}
515
516
	/**
517
	 * Sets the element at the specified offset. This method is required by the interface \ArrayAccess.
518
	 * Setting elements in a priority list is not straight forword when appending and setting at the
519
	 * end boundary.  When appending without an offset (a null offset), the item will be added at
520
	 * the default priority.  The item may not be the last item in the list.  When appending with an
521 48
	 * offset equal to the count of the list, the item will get be appended with the last items priority.
522
	 *
523 48
	 * All together, when setting the location of an item, the item stays in that location, but appending
524
	 * an item into a priority list doesn't mean the item is at the end of the list.
525 48
	 * @param int $offset the offset to set element
526 48
	 * @param mixed $item the element value
527 48
	 */
528 46
	public function offsetSet($offset, $item): void
529 46
	{
530 46
		if ($offset === null) {
0 ignored issues
show
introduced by
The condition $offset === null is always false.
Loading history...
531
			$this->add($item);
532 11
			return;
533
		}
534
		if ($offset === $this->getCount()) {
535
			$priority = $this->priorityAt($offset, true);
536 4
		} else {
537
			$priority = $this->priorityAt($offset, true);
538
			$this->removeAtIndexInPriority($priority[1], $priority[0]);
539
		}
540
		$this->insertAtIndexInPriority($item, $priority[1], $priority[0]);
541
	}
542
543
	/**
544
	 * Unsets the element at the specified offset.
545
	 * This method is required by the interface \ArrayAccess.
546
	 * @param mixed $offset the offset to unset element
547
	 */
548 12
	public function offsetUnset($offset): void
549
	{
550 12
		$this->removeAt($offset);
551 4
	}
552
553
	/**
554 12
	 * Returns an array with the names of all variables of this object that should NOT be serialized
555 12
	 * because their value is the default one or useless to be cached for the next page loads.
556 12
	 * Reimplement in derived classes to add new variables, but remember to  also to call the parent
557 12
	 * implementation first.
558 7
	 * @param array $exprops by reference
559
	 * @since 4.2.3
560 12
	 */
561 12
	protected function _getZappableSleepProps(&$exprops)
562
	{
563
		parent::_getZappableSleepProps($exprops);
564
		$this->_priorityZappableSleepProps($exprops);
565
	}
566
}
567