ArrayList.php 2.6 KB

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