vendor/shopware/core/Framework/Struct/Collection.php line 149

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Struct;
  3. use Shopware\Core\Framework\Log\Package;
  4. /**
  5.  * @template TElement
  6.  *
  7.  * @implements \IteratorAggregate<array-key, TElement>
  8.  */
  9. #[Package('core')]
  10. abstract class Collection extends Struct implements \IteratorAggregate\Countable
  11. {
  12.     /**
  13.      * @var array<array-key, TElement>
  14.      */
  15.     protected $elements = [];
  16.     /**
  17.      * @param array<TElement> $elements
  18.      */
  19.     public function __construct(iterable $elements = [])
  20.     {
  21.         foreach ($elements as $key => $element) {
  22.             $this->set($key$element);
  23.         }
  24.     }
  25.     /**
  26.      * @param TElement $element
  27.      */
  28.     public function add($element): void
  29.     {
  30.         $this->validateType($element);
  31.         $this->elements[] = $element;
  32.     }
  33.     /**
  34.      * @param array-key|null $key
  35.      * @param TElement $element
  36.      */
  37.     public function set($key$element): void
  38.     {
  39.         $this->validateType($element);
  40.         if ($key === null) {
  41.             $this->elements[] = $element;
  42.         } else {
  43.             $this->elements[$key] = $element;
  44.         }
  45.     }
  46.     /**
  47.      * @param array-key $key
  48.      *
  49.      * @return TElement|null
  50.      */
  51.     public function get($key)
  52.     {
  53.         if ($this->has($key)) {
  54.             return $this->elements[$key];
  55.         }
  56.         return null;
  57.     }
  58.     public function clear(): void
  59.     {
  60.         $this->elements = [];
  61.     }
  62.     public function count(): int
  63.     {
  64.         return \count($this->elements);
  65.     }
  66.     /**
  67.      * @return list<array-key>
  68.      */
  69.     public function getKeys(): array
  70.     {
  71.         return array_keys($this->elements);
  72.     }
  73.     /**
  74.      * @param array-key $key
  75.      */
  76.     public function has($key): bool
  77.     {
  78.         return \array_key_exists($key$this->elements);
  79.     }
  80.     /**
  81.      * @return list<mixed>
  82.      */
  83.     public function map(\Closure $closure): array
  84.     {
  85.         return array_map($closure$this->elements);
  86.     }
  87.     /**
  88.      * @param  mixed|null        $initial
  89.      *
  90.      * @return mixed|null
  91.      */
  92.     public function reduce(\Closure $closure$initial null)
  93.     {
  94.         return array_reduce($this->elements$closure$initial);
  95.     }
  96.     /**
  97.      * @return array<array-key, mixed>
  98.      */
  99.     public function fmap(\Closure $closure): array
  100.     {
  101.         return array_filter($this->map($closure));
  102.     }
  103.     public function sort(\Closure $closure): void
  104.     {
  105.         uasort($this->elements$closure);
  106.     }
  107.     /**
  108.      * @param class-string $class
  109.      *
  110.      * tag v6.6.0 Return type will be natively typed to `static`
  111.      *
  112.      * @return static
  113.      */
  114.     #[\ReturnTypeWillChange]
  115.     public function filterInstance(string $class)
  116.     {
  117.         return $this->filter(static function ($item) use ($class) {
  118.             return $item instanceof $class;
  119.         });
  120.     }
  121.     /**
  122.      * tag v6.6.0 Return type will be natively typed to `static`
  123.      *
  124.      * @return static
  125.      */
  126.     #[\ReturnTypeWillChange]
  127.     public function filter(\Closure $closure)
  128.     {
  129.         return $this->createNew(array_filter($this->elements$closure));
  130.     }
  131.     /**
  132.      * tag v6.6.0 Return type will be natively typed to `static`
  133.      *
  134.      * @return static
  135.      */
  136.     #[\ReturnTypeWillChange]
  137.     public function slice(int $offset, ?int $length null)
  138.     {
  139.         return $this->createNew(\array_slice($this->elements$offset$lengthtrue));
  140.     }
  141.     /**
  142.      * @return array<TElement>
  143.      */
  144.     public function getElements(): array
  145.     {
  146.         return $this->elements;
  147.     }
  148.     /**
  149.      * @return list<TElement>
  150.      */
  151.     public function jsonSerialize(): array
  152.     {
  153.         return array_values($this->elements);
  154.     }
  155.     /**
  156.      * return ($this->elements is non-empty-array ? TElement : null) does not work as return type for now.
  157.      * Possible with PHPStan 1.9.0 see https://github.com/phpstan/phpstan/issues/7110
  158.      */
  159.     public function first()
  160.     {
  161.         return array_values($this->elements)[0] ?? null;
  162.     }
  163.     /**
  164.      * @return TElement|null
  165.      */
  166.     public function getAt(int $position)
  167.     {
  168.         return array_values($this->elements)[$position] ?? null;
  169.     }
  170.     /**
  171.      * return ($this->elements is non-empty-array ? TElement : null) does not work as return type for now.
  172.      * Possible with PHPStan 1.9.0 see https://github.com/phpstan/phpstan/issues/7110
  173.      */
  174.     public function last()
  175.     {
  176.         return array_values($this->elements)[\count($this->elements) - 1] ?? null;
  177.     }
  178.     /**
  179.      * @param array-key $key
  180.      */
  181.     public function remove($key): void
  182.     {
  183.         unset($this->elements[$key]);
  184.     }
  185.     /**
  186.      * @return \Generator<TElement>
  187.      */
  188.     public function getIterator(): \Traversable
  189.     {
  190.         yield from $this->elements;
  191.     }
  192.     /**
  193.      * @return class-string<TElement>|null
  194.      */
  195.     protected function getExpectedClass(): ?string
  196.     {
  197.         return null;
  198.     }
  199.     /**
  200.      * @param iterable<TElement> $elements
  201.      *
  202.      * tag v6.6.0 Return type will be natively typed to `static`
  203.      *
  204.      * @return static
  205.      */
  206.     #[\ReturnTypeWillChange]
  207.     protected function createNew(iterable $elements = [])
  208.     {
  209.         return new static($elements);
  210.     }
  211.     /**
  212.      * @param TElement $element
  213.      */
  214.     protected function validateType($element): void
  215.     {
  216.         $expectedClass $this->getExpectedClass();
  217.         if ($expectedClass === null) {
  218.             return;
  219.         }
  220.         if (!$element instanceof $expectedClass) {
  221.             $elementClass \get_class($element);
  222.             throw new \InvalidArgumentException(
  223.                 sprintf('Expected collection element of type %s got %s'$expectedClass$elementClass)
  224.             );
  225.         }
  226.     }
  227. }