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

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