friendship ended with social-app. php is my new best friend
1<?php
2
3/**
4 * This file is part of the Nette Framework (https://nette.org)
5 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6 */
7
8declare(strict_types=1);
9
10namespace Nette\Utils;
11
12use Nette;
13use function array_slice, array_splice, count, is_int;
14
15
16/**
17 * Provides the base class for a generic list (items can be accessed by index).
18 * @template T
19 * @implements \IteratorAggregate<int, T>
20 * @implements \ArrayAccess<int, T>
21 */
22class ArrayList implements \ArrayAccess, \Countable, \IteratorAggregate
23{
24 use Nette\SmartObject;
25
26 private array $list = [];
27
28
29 /**
30 * Transforms array to ArrayList.
31 * @param list<T> $array
32 */
33 public static function from(array $array): static
34 {
35 if (!Arrays::isList($array)) {
36 throw new Nette\InvalidArgumentException('Array is not valid list.');
37 }
38
39 $obj = new static;
40 $obj->list = $array;
41 return $obj;
42 }
43
44
45 /**
46 * Returns an iterator over all items.
47 * @return \Iterator<int, T>
48 */
49 public function &getIterator(): \Iterator
50 {
51 foreach ($this->list as &$item) {
52 yield $item;
53 }
54 }
55
56
57 /**
58 * Returns items count.
59 */
60 public function count(): int
61 {
62 return count($this->list);
63 }
64
65
66 /**
67 * Replaces or appends an item.
68 * @param int|null $index
69 * @param T $value
70 * @throws Nette\OutOfRangeException
71 */
72 public function offsetSet($index, $value): void
73 {
74 if ($index === null) {
75 $this->list[] = $value;
76
77 } elseif (!is_int($index) || $index < 0 || $index >= count($this->list)) {
78 throw new Nette\OutOfRangeException('Offset invalid or out of range');
79
80 } else {
81 $this->list[$index] = $value;
82 }
83 }
84
85
86 /**
87 * Returns an item.
88 * @param int $index
89 * @return T
90 * @throws Nette\OutOfRangeException
91 */
92 public function offsetGet($index): mixed
93 {
94 if (!is_int($index) || $index < 0 || $index >= count($this->list)) {
95 throw new Nette\OutOfRangeException('Offset invalid or out of range');
96 }
97
98 return $this->list[$index];
99 }
100
101
102 /**
103 * Determines whether an item exists.
104 * @param int $index
105 */
106 public function offsetExists($index): bool
107 {
108 return is_int($index) && $index >= 0 && $index < count($this->list);
109 }
110
111
112 /**
113 * Removes the element at the specified position in this list.
114 * @param int $index
115 * @throws Nette\OutOfRangeException
116 */
117 public function offsetUnset($index): void
118 {
119 if (!is_int($index) || $index < 0 || $index >= count($this->list)) {
120 throw new Nette\OutOfRangeException('Offset invalid or out of range');
121 }
122
123 array_splice($this->list, $index, 1);
124 }
125
126
127 /**
128 * Prepends an item.
129 * @param T $value
130 */
131 public function prepend(mixed $value): void
132 {
133 $first = array_slice($this->list, 0, 1);
134 $this->offsetSet(0, $value);
135 array_splice($this->list, 1, 0, $first);
136 }
137}