ObjectCollection.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. /**
  3. * @package Grav\Framework\Object
  4. *
  5. * @copyright Copyright (c) 2015 - 2023 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Framework\Object;
  9. use Doctrine\Common\Collections\Criteria;
  10. use Grav\Framework\Collection\ArrayCollection;
  11. use Grav\Framework\Object\Access\NestedPropertyCollectionTrait;
  12. use Grav\Framework\Object\Base\ObjectCollectionTrait;
  13. use Grav\Framework\Object\Collection\ObjectExpressionVisitor;
  14. use Grav\Framework\Object\Interfaces\NestedObjectCollectionInterface;
  15. use InvalidArgumentException;
  16. use function array_slice;
  17. /**
  18. * Class contains a collection of objects.
  19. *
  20. * @template TKey of array-key
  21. * @template T of \Grav\Framework\Object\Interfaces\ObjectInterface
  22. * @extends ArrayCollection<TKey,T>
  23. * @implements NestedObjectCollectionInterface<TKey,T>
  24. */
  25. class ObjectCollection extends ArrayCollection implements NestedObjectCollectionInterface
  26. {
  27. /** @phpstan-use ObjectCollectionTrait<TKey,T> */
  28. use ObjectCollectionTrait;
  29. use NestedPropertyCollectionTrait {
  30. NestedPropertyCollectionTrait::group insteadof ObjectCollectionTrait;
  31. }
  32. /**
  33. * @param array $elements
  34. * @param string|null $key
  35. * @throws InvalidArgumentException
  36. */
  37. public function __construct(array $elements = [], $key = null)
  38. {
  39. parent::__construct($this->setElements($elements));
  40. $this->setKey($key ?? '');
  41. }
  42. /**
  43. * @param array $ordering
  44. * @return static
  45. * @phpstan-return static<TKey,T>
  46. */
  47. public function orderBy(array $ordering)
  48. {
  49. $criteria = Criteria::create()->orderBy($ordering);
  50. return $this->matching($criteria);
  51. }
  52. /**
  53. * @param int $start
  54. * @param int|null $limit
  55. * @return static
  56. * @phpstan-return static<TKey,T>
  57. */
  58. public function limit($start, $limit = null)
  59. {
  60. /** @phpstan-var static<TKey,T> */
  61. return $this->createFrom($this->slice($start, $limit));
  62. }
  63. /**
  64. * @param Criteria $criteria
  65. * @return static
  66. * @phpstan-return static<TKey,T>
  67. */
  68. public function matching(Criteria $criteria)
  69. {
  70. $expr = $criteria->getWhereExpression();
  71. $filtered = $this->getElements();
  72. if ($expr) {
  73. $visitor = new ObjectExpressionVisitor();
  74. $filter = $visitor->dispatch($expr);
  75. $filtered = array_filter($filtered, $filter);
  76. }
  77. if ($orderings = $criteria->getOrderings()) {
  78. $next = null;
  79. foreach (array_reverse($orderings) as $field => $ordering) {
  80. $next = ObjectExpressionVisitor::sortByField($field, $ordering === Criteria::DESC ? -1 : 1, $next);
  81. }
  82. /** @phpstan-ignore-next-line */
  83. if ($next) {
  84. uasort($filtered, $next);
  85. }
  86. }
  87. $offset = $criteria->getFirstResult();
  88. $length = $criteria->getMaxResults();
  89. if ($offset || $length) {
  90. $filtered = array_slice($filtered, (int)$offset, $length);
  91. }
  92. /** @phpstan-var static<TKey,T> */
  93. return $this->createFrom($filtered);
  94. }
  95. /**
  96. * @return array
  97. * @phpstan-return array<TKey,T>
  98. */
  99. protected function getElements()
  100. {
  101. return $this->toArray();
  102. }
  103. /**
  104. * @param array $elements
  105. * @return array
  106. * @phpstan-return array<TKey,T>
  107. */
  108. protected function setElements(array $elements)
  109. {
  110. /** @phpstan-var array<TKey,T> $elements */
  111. return $elements;
  112. }
  113. }