Iterator.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <?php
  2. namespace Grav\Common;
  3. use RocketTheme\Toolbox\ArrayTraits\ArrayAccessWithGetters;
  4. use RocketTheme\Toolbox\ArrayTraits\Iterator as ArrayIterator;
  5. use RocketTheme\Toolbox\ArrayTraits\Constructor;
  6. use RocketTheme\Toolbox\ArrayTraits\Countable;
  7. use RocketTheme\Toolbox\ArrayTraits\Export;
  8. use RocketTheme\Toolbox\ArrayTraits\Serializable;
  9. /**
  10. * Class Iterator
  11. * @package Grav\Common
  12. */
  13. class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
  14. {
  15. use Constructor, ArrayAccessWithGetters, ArrayIterator, Countable, Serializable, Export;
  16. /**
  17. * @var array
  18. */
  19. protected $items = [];
  20. /**
  21. * Convert function calls for the existing keys into their values.
  22. *
  23. * @param string $key
  24. * @param mixed $args
  25. * @return mixed
  26. */
  27. public function __call($key, $args)
  28. {
  29. return (isset($this->items[$key])) ? $this->items[$key] : null;
  30. }
  31. /**
  32. * Clone the iterator.
  33. */
  34. public function __clone()
  35. {
  36. foreach ($this as $key => $value) {
  37. if (is_object($value)) {
  38. $this->$key = clone $this->$key;
  39. }
  40. }
  41. }
  42. /**
  43. * Convents iterator to a comma separated list.
  44. *
  45. * @return string
  46. */
  47. public function __toString()
  48. {
  49. return implode(',', $this->items);
  50. }
  51. /**
  52. * Remove item from the list.
  53. *
  54. * @param $key
  55. */
  56. public function remove($key)
  57. {
  58. $this->offsetUnset($key);
  59. }
  60. /**
  61. * Return previous item.
  62. *
  63. * @return mixed
  64. */
  65. public function prev()
  66. {
  67. return prev($this->items);
  68. }
  69. /**
  70. * Return nth item.
  71. *
  72. * @param int $key
  73. * @return mixed|bool
  74. */
  75. public function nth($key)
  76. {
  77. $items = array_keys($this->items);
  78. return (isset($items[$key])) ? $this->offsetGet($items[$key]) : false;
  79. }
  80. /**
  81. * Get the first item
  82. *
  83. * @return mixed
  84. */
  85. public function first()
  86. {
  87. $items = array_keys($this->items);
  88. return $this->offsetGet(array_shift($items));
  89. }
  90. /**
  91. * Get the last item
  92. *
  93. * @return mixed
  94. */
  95. public function last()
  96. {
  97. $items = array_keys($this->items);
  98. return $this->offsetGet(array_pop($items));
  99. }
  100. /**
  101. * Reverse the Iterator
  102. *
  103. * @return $this
  104. */
  105. public function reverse()
  106. {
  107. $this->items = array_reverse($this->items);
  108. return $this;
  109. }
  110. /**
  111. * @param mixed $needle Searched value.
  112. * @return string|bool Key if found, otherwise false.
  113. */
  114. public function indexOf($needle)
  115. {
  116. foreach (array_values($this->items) as $key => $value) {
  117. if ($value === $needle) {
  118. return $key;
  119. }
  120. }
  121. return false;
  122. }
  123. /**
  124. * Shuffle items.
  125. *
  126. * @return $this
  127. */
  128. public function shuffle()
  129. {
  130. $keys = array_keys($this->items);
  131. shuffle($keys);
  132. $new = array();
  133. foreach ($keys as $key) {
  134. $new[$key] = $this->items[$key];
  135. }
  136. $this->items = $new;
  137. return $this;
  138. }
  139. /**
  140. * Slice the list.
  141. *
  142. * @param int $offset
  143. * @param int $length
  144. * @return $this
  145. */
  146. public function slice($offset, $length = null)
  147. {
  148. $this->items = array_slice($this->items, $offset, $length);
  149. return $this;
  150. }
  151. /**
  152. * Pick one or more random entries.
  153. *
  154. * @param int $num Specifies how many entries should be picked.
  155. * @return $this
  156. */
  157. public function random($num = 1)
  158. {
  159. $this->items = array_intersect_key($this->items, array_flip((array) array_rand($this->items, $num)));
  160. return $this;
  161. }
  162. /**
  163. * Append new elements to the list.
  164. *
  165. * @param array|Iterator $items Items to be appended. Existing keys will be overridden with the new values.
  166. * @return $this
  167. */
  168. public function append($items)
  169. {
  170. if ($items instanceof static) {
  171. $items = $items->toArray();
  172. }
  173. $this->items = array_merge($this->items, (array) $items);
  174. return $this;
  175. }
  176. /**
  177. * Filter elements from the list
  178. * @param callable|null $callback A function the receives ($value, $key) and must return a boolean to indicate filter status
  179. * @return $this
  180. */
  181. public function filter(callable $callback = null)
  182. {
  183. foreach ($this->items as $key => $value) {
  184. if (
  185. ($callback && !call_user_func($callback, $value, $key)) ||
  186. (!$callback && !(bool) $value)
  187. ) {
  188. unset($this->items[$key]);
  189. }
  190. }
  191. return $this;
  192. }
  193. }