vendor/doctrine/collections/lib/Doctrine/Common/Collections/ArrayCollection.php line 40

Open in your IDE?
  1. <?php
  2. namespace Doctrine\Common\Collections;
  3. use ArrayIterator;
  4. use Closure;
  5. use Doctrine\Common\Collections\Expr\ClosureExpressionVisitor;
  6. use const ARRAY_FILTER_USE_BOTH;
  7. use function array_filter;
  8. use function array_key_exists;
  9. use function array_keys;
  10. use function array_map;
  11. use function array_reverse;
  12. use function array_search;
  13. use function array_slice;
  14. use function array_values;
  15. use function count;
  16. use function current;
  17. use function end;
  18. use function in_array;
  19. use function key;
  20. use function next;
  21. use function reset;
  22. use function spl_object_hash;
  23. use function uasort;
  24. /**
  25.  * An ArrayCollection is a Collection implementation that wraps a regular PHP array.
  26.  *
  27.  * Warning: Using (un-)serialize() on a collection is not a supported use-case
  28.  * and may break when we change the internals in the future. If you need to
  29.  * serialize a collection use {@link toArray()} and reconstruct the collection
  30.  * manually.
  31.  *
  32.  * @psalm-template TKey of array-key
  33.  * @psalm-template T
  34.  * @template-implements Collection<TKey,T>
  35.  * @template-implements Selectable<TKey,T>
  36.  */
  37. class ArrayCollection implements CollectionSelectable
  38. {
  39.     /**
  40.      * An array containing the entries of this collection.
  41.      *
  42.      * @psalm-var array<TKey,T>
  43.      * @var array
  44.      */
  45.     private $elements;
  46.     /**
  47.      * Initializes a new ArrayCollection.
  48.      *
  49.      * @param array $elements
  50.      *
  51.      * @psalm-param array<TKey,T> $elements
  52.      */
  53.     public function __construct(array $elements = [])
  54.     {
  55.         $this->elements $elements;
  56.     }
  57.     /**
  58.      * {@inheritDoc}
  59.      */
  60.     public function toArray()
  61.     {
  62.         return $this->elements;
  63.     }
  64.     /**
  65.      * {@inheritDoc}
  66.      */
  67.     public function first()
  68.     {
  69.         return reset($this->elements);
  70.     }
  71.     /**
  72.      * Creates a new instance from the specified elements.
  73.      *
  74.      * This method is provided for derived classes to specify how a new
  75.      * instance should be created when constructor semantics have changed.
  76.      *
  77.      * @param array $elements Elements.
  78.      *
  79.      * @return static
  80.      *
  81.      * @psalm-param array<TKey,T> $elements
  82.      * @psalm-return static<TKey,T>
  83.      */
  84.     protected function createFrom(array $elements)
  85.     {
  86.         return new static($elements);
  87.     }
  88.     /**
  89.      * {@inheritDoc}
  90.      */
  91.     public function last()
  92.     {
  93.         return end($this->elements);
  94.     }
  95.     /**
  96.      * {@inheritDoc}
  97.      */
  98.     public function key()
  99.     {
  100.         return key($this->elements);
  101.     }
  102.     /**
  103.      * {@inheritDoc}
  104.      */
  105.     public function next()
  106.     {
  107.         return next($this->elements);
  108.     }
  109.     /**
  110.      * {@inheritDoc}
  111.      */
  112.     public function current()
  113.     {
  114.         return current($this->elements);
  115.     }
  116.     /**
  117.      * {@inheritDoc}
  118.      */
  119.     public function remove($key)
  120.     {
  121.         if (! isset($this->elements[$key]) && ! array_key_exists($key$this->elements)) {
  122.             return null;
  123.         }
  124.         $removed $this->elements[$key];
  125.         unset($this->elements[$key]);
  126.         return $removed;
  127.     }
  128.     /**
  129.      * {@inheritDoc}
  130.      */
  131.     public function removeElement($element)
  132.     {
  133.         $key array_search($element$this->elementstrue);
  134.         if ($key === false) {
  135.             return false;
  136.         }
  137.         unset($this->elements[$key]);
  138.         return true;
  139.     }
  140.     /**
  141.      * Required by interface ArrayAccess.
  142.      *
  143.      * {@inheritDoc}
  144.      */
  145.     public function offsetExists($offset)
  146.     {
  147.         return $this->containsKey($offset);
  148.     }
  149.     /**
  150.      * Required by interface ArrayAccess.
  151.      *
  152.      * {@inheritDoc}
  153.      */
  154.     public function offsetGet($offset)
  155.     {
  156.         return $this->get($offset);
  157.     }
  158.     /**
  159.      * Required by interface ArrayAccess.
  160.      *
  161.      * {@inheritDoc}
  162.      */
  163.     public function offsetSet($offset$value)
  164.     {
  165.         if (! isset($offset)) {
  166.             $this->add($value);
  167.             return;
  168.         }
  169.         $this->set($offset$value);
  170.     }
  171.     /**
  172.      * Required by interface ArrayAccess.
  173.      *
  174.      * {@inheritDoc}
  175.      */
  176.     public function offsetUnset($offset)
  177.     {
  178.         $this->remove($offset);
  179.     }
  180.     /**
  181.      * {@inheritDoc}
  182.      */
  183.     public function containsKey($key)
  184.     {
  185.         return isset($this->elements[$key]) || array_key_exists($key$this->elements);
  186.     }
  187.     /**
  188.      * {@inheritDoc}
  189.      */
  190.     public function contains($element)
  191.     {
  192.         return in_array($element$this->elementstrue);
  193.     }
  194.     /**
  195.      * {@inheritDoc}
  196.      */
  197.     public function exists(Closure $p)
  198.     {
  199.         foreach ($this->elements as $key => $element) {
  200.             if ($p($key$element)) {
  201.                 return true;
  202.             }
  203.         }
  204.         return false;
  205.     }
  206.     /**
  207.      * {@inheritDoc}
  208.      */
  209.     public function indexOf($element)
  210.     {
  211.         return array_search($element$this->elementstrue);
  212.     }
  213.     /**
  214.      * {@inheritDoc}
  215.      */
  216.     public function get($key)
  217.     {
  218.         return $this->elements[$key] ?? null;
  219.     }
  220.     /**
  221.      * {@inheritDoc}
  222.      */
  223.     public function getKeys()
  224.     {
  225.         return array_keys($this->elements);
  226.     }
  227.     /**
  228.      * {@inheritDoc}
  229.      */
  230.     public function getValues()
  231.     {
  232.         return array_values($this->elements);
  233.     }
  234.     /**
  235.      * {@inheritDoc}
  236.      */
  237.     public function count()
  238.     {
  239.         return count($this->elements);
  240.     }
  241.     /**
  242.      * {@inheritDoc}
  243.      */
  244.     public function set($key$value)
  245.     {
  246.         $this->elements[$key] = $value;
  247.     }
  248.     /**
  249.      * {@inheritDoc}
  250.      */
  251.     public function add($element)
  252.     {
  253.         $this->elements[] = $element;
  254.         return true;
  255.     }
  256.     /**
  257.      * {@inheritDoc}
  258.      */
  259.     public function isEmpty()
  260.     {
  261.         return empty($this->elements);
  262.     }
  263.     /**
  264.      * Required by interface IteratorAggregate.
  265.      *
  266.      * {@inheritDoc}
  267.      */
  268.     public function getIterator()
  269.     {
  270.         return new ArrayIterator($this->elements);
  271.     }
  272.     /**
  273.      * {@inheritDoc}
  274.      *
  275.      * @return static
  276.      *
  277.      * @psalm-template U
  278.      * @psalm-param Closure(T=):U $func
  279.      * @psalm-return static<TKey, U>
  280.      */
  281.     public function map(Closure $func)
  282.     {
  283.         return $this->createFrom(array_map($func$this->elements));
  284.     }
  285.     /**
  286.      * {@inheritDoc}
  287.      *
  288.      * @return static
  289.      *
  290.      * @psalm-return static<TKey,T>
  291.      */
  292.     public function filter(Closure $p)
  293.     {
  294.         return $this->createFrom(array_filter($this->elements$pARRAY_FILTER_USE_BOTH));
  295.     }
  296.     /**
  297.      * {@inheritDoc}
  298.      */
  299.     public function forAll(Closure $p)
  300.     {
  301.         foreach ($this->elements as $key => $element) {
  302.             if (! $p($key$element)) {
  303.                 return false;
  304.             }
  305.         }
  306.         return true;
  307.     }
  308.     /**
  309.      * {@inheritDoc}
  310.      */
  311.     public function partition(Closure $p)
  312.     {
  313.         $matches $noMatches = [];
  314.         foreach ($this->elements as $key => $element) {
  315.             if ($p($key$element)) {
  316.                 $matches[$key] = $element;
  317.             } else {
  318.                 $noMatches[$key] = $element;
  319.             }
  320.         }
  321.         return [$this->createFrom($matches), $this->createFrom($noMatches)];
  322.     }
  323.     /**
  324.      * Returns a string representation of this object.
  325.      *
  326.      * @return string
  327.      */
  328.     public function __toString()
  329.     {
  330.         return self::class . '@' spl_object_hash($this);
  331.     }
  332.     /**
  333.      * {@inheritDoc}
  334.      */
  335.     public function clear()
  336.     {
  337.         $this->elements = [];
  338.     }
  339.     /**
  340.      * {@inheritDoc}
  341.      */
  342.     public function slice($offset$length null)
  343.     {
  344.         return array_slice($this->elements$offset$lengthtrue);
  345.     }
  346.     /**
  347.      * {@inheritDoc}
  348.      */
  349.     public function matching(Criteria $criteria)
  350.     {
  351.         $expr     $criteria->getWhereExpression();
  352.         $filtered $this->elements;
  353.         if ($expr) {
  354.             $visitor  = new ClosureExpressionVisitor();
  355.             $filter   $visitor->dispatch($expr);
  356.             $filtered array_filter($filtered$filter);
  357.         }
  358.         $orderings $criteria->getOrderings();
  359.         if ($orderings) {
  360.             $next null;
  361.             foreach (array_reverse($orderings) as $field => $ordering) {
  362.                 $next ClosureExpressionVisitor::sortByField($field$ordering === Criteria::DESC ? -1$next);
  363.             }
  364.             uasort($filtered$next);
  365.         }
  366.         $offset $criteria->getFirstResult();
  367.         $length $criteria->getMaxResults();
  368.         if ($offset || $length) {
  369.             $filtered array_slice($filtered, (int) $offset$length);
  370.         }
  371.         return $this->createFrom($filtered);
  372.     }
  373. }