1<?php 2 3/* 4 * This file is part of the league/commonmark package. 5 * 6 * (c) Colin O'Dell <colinodell@gmail.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace League\CommonMark\Util; 13 14/** 15 * Array collection 16 * 17 * Provides a wrapper around a standard PHP array. 18 * 19 * @internal 20 * 21 * @phpstan-template TKey 22 * @phpstan-template TValue 23 * @phpstan-implements \IteratorAggregate<TKey, TValue> 24 * @phpstan-implements \ArrayAccess<TKey, TValue> 25 */ 26class ArrayCollection implements \IteratorAggregate, \Countable, \ArrayAccess 27{ 28 /** 29 * @var array<int|string, mixed> 30 * @phpstan-var array<TKey, TValue> 31 */ 32 private $elements; 33 34 /** 35 * Constructor 36 * 37 * @param array<int|string, mixed> $elements 38 * 39 * @phpstan-param array<TKey, TValue> $elements 40 */ 41 public function __construct(array $elements = []) 42 { 43 $this->elements = $elements; 44 45 if (self::class !== static::class) { 46 @\trigger_error('Extending the ArrayCollection class is deprecated in league/commonmark 1.6 and will not be allowed in 2.0', \E_USER_DEPRECATED); 47 } 48 } 49 50 /** 51 * @return mixed|false 52 * 53 * @phpstan-return TValue|false 54 */ 55 public function first() 56 { 57 return \reset($this->elements); 58 } 59 60 /** 61 * @return mixed|false 62 * 63 * @phpstan-return TValue|false 64 */ 65 public function last() 66 { 67 return \end($this->elements); 68 } 69 70 /** 71 * Retrieve an external iterator 72 * 73 * @return \ArrayIterator<int|string, mixed> 74 */ 75 #[\ReturnTypeWillChange] 76 public function getIterator() 77 { 78 return new \ArrayIterator($this->elements); 79 } 80 81 /** 82 * @param mixed $element 83 * 84 * @return bool 85 * 86 * @phpstan-param TValue $element 87 * 88 * @deprecated 89 */ 90 public function add($element): bool 91 { 92 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4, use "%s" instead.', self::class, 'add()', '$collection[] = $value'), E_USER_DEPRECATED); 93 94 $this->elements[] = $element; 95 96 return true; 97 } 98 99 /** 100 * @param int|string $key 101 * @param mixed $value 102 * 103 * @return void 104 * 105 * @phpstan-param TKey $key 106 * @phpstan-param TValue $value 107 * 108 * @deprecated 109 */ 110 public function set($key, $value) 111 { 112 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4, use "%s" instead.', self::class, 'set()', '$collection[$key] = $value'), E_USER_DEPRECATED); 113 114 $this->offsetSet($key, $value); 115 } 116 117 /** 118 * @param int|string $key 119 * 120 * @return mixed 121 * 122 * @phpstan-param TKey $key 123 * 124 * @phpstan-return TValue|null 125 * 126 * @deprecated 127 */ 128 public function get($key) 129 { 130 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4, use "%s" instead.', self::class, 'get()', '$collection[$key]'), E_USER_DEPRECATED); 131 132 return $this->offsetGet($key); 133 } 134 135 /** 136 * @param int|string $key 137 * 138 * @return mixed 139 * 140 * @phpstan-param TKey $key 141 * 142 * @phpstan-return TValue|null 143 * 144 * @deprecated 145 */ 146 public function remove($key) 147 { 148 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4, use "%s" instead.', self::class, 'remove()', 'unset($collection[$key])'), E_USER_DEPRECATED); 149 150 if (!\array_key_exists($key, $this->elements)) { 151 return; 152 } 153 154 $removed = $this->elements[$key]; 155 unset($this->elements[$key]); 156 157 return $removed; 158 } 159 160 /** 161 * @return bool 162 * 163 * @deprecated 164 */ 165 public function isEmpty(): bool 166 { 167 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4, use "%s" instead.', self::class, 'isEmpty()', 'count($collection) === 0'), E_USER_DEPRECATED); 168 169 return empty($this->elements); 170 } 171 172 /** 173 * @param mixed $element 174 * 175 * @return bool 176 * 177 * @phpstan-param TValue $element 178 * 179 * @deprecated 180 */ 181 public function contains($element): bool 182 { 183 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4, use "%s" instead.', self::class, 'contains()', 'in_array($value, $collection->toArray(), true)'), E_USER_DEPRECATED); 184 185 return \in_array($element, $this->elements, true); 186 } 187 188 /** 189 * @param mixed $element 190 * 191 * @return mixed|false 192 * 193 * @phpstan-param TValue $element 194 * 195 * @deprecated 196 */ 197 public function indexOf($element) 198 { 199 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4, use "%s" instead.', self::class, 'indexOf()', 'array_search($value, $collection->toArray(), true)'), E_USER_DEPRECATED); 200 201 return \array_search($element, $this->elements, true); 202 } 203 204 /** 205 * @param int|string $key 206 * 207 * @return bool 208 * 209 * @phpstan-param TKey $key 210 * 211 * @deprecated 212 */ 213 public function containsKey($key): bool 214 { 215 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4, use "%s" instead.', self::class, 'containsKey()', 'isset($collection[$key])'), E_USER_DEPRECATED); 216 217 return \array_key_exists($key, $this->elements); 218 } 219 220 /** 221 * Count elements of an object 222 * 223 * @return int The count as an integer. 224 */ 225 public function count(): int 226 { 227 return \count($this->elements); 228 } 229 230 /** 231 * Whether an offset exists 232 * 233 * @param int|string $offset An offset to check for. 234 * 235 * @return bool true on success or false on failure. 236 * 237 * @phpstan-param TKey $offset 238 */ 239 public function offsetExists($offset): bool 240 { 241 return \array_key_exists($offset, $this->elements); 242 } 243 244 /** 245 * Offset to retrieve 246 * 247 * @param int|string $offset 248 * 249 * @return mixed|null 250 * 251 * @phpstan-param TKey $offset 252 * 253 * @phpstan-return TValue|null 254 */ 255 #[\ReturnTypeWillChange] 256 public function offsetGet($offset) 257 { 258 return $this->elements[$offset] ?? null; 259 } 260 261 /** 262 * Offset to set 263 * 264 * @param int|string|null $offset The offset to assign the value to. 265 * @param mixed $value The value to set. 266 * 267 * @return void 268 * 269 * @phpstan-param TKey|null $offset 270 * @phpstan-param TValue $value 271 */ 272 #[\ReturnTypeWillChange] 273 public function offsetSet($offset, $value) 274 { 275 if ($offset === null) { 276 $this->elements[] = $value; 277 } else { 278 $this->elements[$offset] = $value; 279 } 280 } 281 282 /** 283 * Offset to unset 284 * 285 * @param int|string $offset The offset to unset. 286 * 287 * @return void 288 * 289 * @phpstan-param TKey $offset 290 */ 291 #[\ReturnTypeWillChange] 292 public function offsetUnset($offset) 293 { 294 if (!\array_key_exists($offset, $this->elements)) { 295 return; 296 } 297 298 unset($this->elements[$offset]); 299 } 300 301 /** 302 * Returns a subset of the array 303 * 304 * @param int $offset 305 * @param int|null $length 306 * 307 * @return array<int|string, mixed> 308 * 309 * @phpstan-return array<TKey, TValue> 310 */ 311 public function slice(int $offset, ?int $length = null): array 312 { 313 return \array_slice($this->elements, $offset, $length, true); 314 } 315 316 /** 317 * @return array<int|string, mixed> 318 * 319 * @phpstan-return array<TKey, TValue> 320 */ 321 public function toArray(): array 322 { 323 return $this->elements; 324 } 325 326 /** 327 * @param array<int|string, mixed> $elements 328 * 329 * @return $this 330 * 331 * @phpstan-param array<TKey, TValue> $elements 332 * 333 * @deprecated 334 */ 335 public function replaceWith(array $elements) 336 { 337 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4.', self::class, 'replaceWith()'), E_USER_DEPRECATED); 338 339 $this->elements = $elements; 340 341 return $this; 342 } 343 344 /** 345 * @deprecated 346 * 347 * @return void 348 */ 349 public function removeGaps() 350 { 351 @trigger_error(sprintf('The "%s:%s" method is deprecated since league/commonmark 1.4.', self::class, 'removeGaps()'), E_USER_DEPRECATED); 352 353 $this->elements = \array_filter($this->elements); 354 } 355} 356