Просмотр файла vendor/visavi/motor-orm/src/Collection.php

Размер файла: 8.04Kb
  1. <?php
  2.  
  3. declare(strict_types=1);
  4.  
  5. namespace MotorORM;
  6.  
  7. use ArrayAccess;
  8. use ArrayIterator;
  9. use Countable;
  10. use IteratorAggregate;
  11. use Traversable;
  12.  
  13. /**
  14. * Collection
  15. *
  16. * @license Code and contributions have MIT License
  17. * @link https://visavi.net
  18. * @author Alexander Grigorev <admin@visavi.net>
  19. * @version 1.0
  20. */
  21. class Collection implements Countable, IteratorAggregate, ArrayAccess
  22. {
  23. /**
  24. * Initializes a new collection.
  25. */
  26. public function __construct(
  27. protected array $elements = [],
  28. ) {
  29. $this->elements = array_values($elements);
  30. }
  31.  
  32. /**
  33. * Creates a new instance from the specified elements.
  34. *
  35. * This method is provided for derived classes to specify how a new
  36. * instance should be created when constructor semantics have changed.
  37. *
  38. * @param array $elements Elements.
  39. *
  40. * @return static
  41. */
  42. protected function createFrom(array $elements): static
  43. {
  44. return new static($elements);
  45. }
  46.  
  47. /**
  48. * Gets a native PHP array representation of the collection.
  49. *
  50. * @return array
  51. */
  52. public function toArray(): array
  53. {
  54. return $this->elements;
  55. }
  56.  
  57. /**
  58. * Sets the internal iterator to the first element in the collection and returns this element.
  59. *
  60. * @return false|mixed
  61. */
  62. public function first(): mixed
  63. {
  64. return reset($this->elements);
  65. }
  66.  
  67. /**
  68. * Sets the internal iterator to the last element in the collection and returns this element.
  69. *
  70. * @return false|mixed
  71. */
  72. public function last(): mixed
  73. {
  74. return end($this->elements);
  75. }
  76.  
  77. /**
  78. * Gets the key/index of the element at the current iterator position.
  79. *
  80. * @return int|string|null
  81. */
  82. public function key(): int|string|null
  83. {
  84. return key($this->elements);
  85. }
  86.  
  87. /**
  88. * Moves the internal iterator position to the next element and returns this element.
  89. *
  90. * @return false|mixed
  91. */
  92. public function next(): mixed
  93. {
  94. return next($this->elements);
  95. }
  96.  
  97. /**
  98. * Gets the element of the collection at the current iterator position.
  99. *
  100. * @return false|mixed
  101. */
  102. public function current(): mixed
  103. {
  104. return current($this->elements);
  105. }
  106.  
  107. /**
  108. * Removes the element at the specified index from the collection.
  109. *
  110. * @param string|int $key
  111. *
  112. * @return mixed|null
  113. */
  114. public function remove(string|int $key): mixed
  115. {
  116. if (! isset($this->elements[$key]) && ! array_key_exists($key, $this->elements)) {
  117. return null;
  118. }
  119.  
  120. $removed = $this->elements[$key];
  121. unset($this->elements[$key]);
  122.  
  123. return $removed;
  124. }
  125.  
  126. /**
  127. * Removes the specified element from the collection, if it is found.
  128. *
  129. * @param mixed $element
  130. *
  131. * @return bool
  132. */
  133. public function removeElement(mixed $element): bool
  134. {
  135. $key = array_search($element, $this->elements, true);
  136.  
  137. if ($key === false) {
  138. return false;
  139. }
  140.  
  141. unset($this->elements[$key]);
  142.  
  143. return true;
  144. }
  145.  
  146. /**
  147. * Required by interface ArrayAccess.
  148. *
  149. * @param $offset
  150. *
  151. * @return bool
  152. */
  153. public function offsetExists($offset): bool
  154. {
  155. return $this->containsKey($offset);
  156. }
  157.  
  158. /**
  159. * Required by interface ArrayAccess.
  160. *
  161. * @param $offset
  162. *
  163. * @return mixed
  164. */
  165. public function offsetGet($offset): mixed
  166. {
  167. return $this->get($offset);
  168. }
  169.  
  170. /**
  171. * Required by interface ArrayAccess.
  172. *
  173. * @param $offset
  174. * @param $value
  175. *
  176. * @return void
  177. */
  178. public function offsetSet($offset, $value): void
  179. {
  180. if (! isset($offset)) {
  181. $this->add($value);
  182.  
  183. return;
  184. }
  185.  
  186. $this->set($offset, $value);
  187. }
  188.  
  189. /**
  190. * Required by interface ArrayAccess.
  191. *
  192. * @param $offset
  193. *
  194. * @return void
  195. */
  196. public function offsetUnset($offset): void
  197. {
  198. $this->remove($offset);
  199. }
  200.  
  201. /**
  202. * Checks whether the collection contains an element with the specified key/index.
  203. *
  204. * @param string|int $key
  205. *
  206. * @return bool
  207. */
  208. public function containsKey(string|int $key): bool
  209. {
  210. return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
  211. }
  212.  
  213. /**
  214. * Checks whether an element is contained in the collection.
  215. * This is an O(n) operation, where n is the size of the collection.
  216. *
  217. * @param mixed $element
  218. *
  219. * @return bool
  220. */
  221. public function contains(mixed $element): bool
  222. {
  223. return in_array($element, $this->elements, true);
  224. }
  225.  
  226. /**
  227. * @param $element
  228. *
  229. * @return false|int|string
  230. */
  231. public function indexOf($element): bool|int|string
  232. {
  233. return array_search($element, $this->elements, true);
  234. }
  235.  
  236. /**
  237. * Gets the element at the specified key/index.
  238. *
  239. * @param string|int $key
  240. *
  241. * @return mixed|null
  242. */
  243. public function get(string|int $key): mixed
  244. {
  245. return $this->elements[$key] ?? null;
  246. }
  247.  
  248. /**
  249. * Gets all keys/indices of the collection.
  250. *
  251. * @return array
  252. */
  253. public function getKeys(): array
  254. {
  255. return array_keys($this->elements);
  256. }
  257.  
  258. /**
  259. * Gets all values of the collection.
  260. *
  261. * @return array
  262. */
  263. public function getValues(): array
  264. {
  265. return array_values($this->elements);
  266. }
  267.  
  268. /**
  269. * @return int
  270. */
  271. public function count(): int
  272. {
  273. return count($this->elements);
  274. }
  275.  
  276. /**
  277. * Sets an element in the collection at the specified key/index.
  278. *
  279. * @param string|int $key
  280. * @param mixed $value
  281. *
  282. * @return void
  283. */
  284. public function set(string|int $key, mixed $value): void
  285. {
  286. $this->elements[$key] = $value;
  287. }
  288.  
  289. /**
  290. * Adds an element at the end of the collection.
  291. *
  292. * @param mixed $element
  293. *
  294. * @return bool
  295. */
  296. public function add(mixed $element): bool
  297. {
  298. $this->elements[] = $element;
  299.  
  300. return true;
  301. }
  302.  
  303. /**
  304. * Checks whether the collection is empty (contains no elements).
  305. *
  306. * @return bool
  307. */
  308. public function isEmpty(): bool
  309. {
  310. return empty($this->elements);
  311. }
  312.  
  313. /**
  314. * Checks whether the collection is not empty.
  315. *
  316. * @return bool
  317. */
  318. public function isNotEmpty(): bool
  319. {
  320. return ! empty($this->elements);
  321. }
  322.  
  323. /**
  324. * @return Traversable<int|string, mixed>
  325. */
  326. public function getIterator(): Traversable
  327. {
  328. return new ArrayIterator($this->elements);
  329. }
  330.  
  331. /**
  332. * Returns a string representation of this object.
  333. *
  334. * @return string
  335. */
  336. public function __toString()
  337. {
  338. return self::class . '@' . spl_object_hash($this);
  339. }
  340.  
  341. /**
  342. * Clears the collection, removing all elements.
  343. *
  344. * @return void
  345. */
  346. public function clear(): void
  347. {
  348. $this->elements = [];
  349. }
  350.  
  351. /**
  352. * Extracts a slice of $length elements starting at position $offset from the Collection.
  353. *
  354. * If $length is null it returns all elements from $offset to the end of the Collection.
  355. * Keys have to be preserved by this method. Calling this method will only return the
  356. * selected slice and NOT change the elements contained in the collection slice is called on.
  357. *
  358. * @param int $offset
  359. * @param int|null $length
  360. *
  361. * @return array
  362. */
  363. public function slice($offset, $length = null)
  364. {
  365. return array_slice($this->elements, $offset, $length, true);
  366. }
  367.  
  368. /**
  369. * Pluck
  370. *
  371. * @param string $value
  372. * @param string|null $key
  373. *
  374. * @return array
  375. */
  376. public function pluck(string $value, ?string $key = null)
  377. {
  378. if ($key === null) {
  379. return array_column($this->elements, $value);
  380. }
  381.  
  382. return array_column($this->elements, $value, $key);
  383. }
  384. }