<?php declare(strict_types=1);namespace Shopware\Core\Checkout\Cart\LineItem;use Shopware\Core\Checkout\Cart\CartException;use Shopware\Core\Checkout\Cart\Exception\InvalidQuantityException;use Shopware\Core\Checkout\Cart\Exception\LineItemNotStackableException;use Shopware\Core\Checkout\Cart\Exception\MixedLineItemTypeException;use Shopware\Core\Checkout\Cart\Price\Struct\PriceCollection;use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;use Shopware\Core\Framework\Feature;use Shopware\Core\Framework\Struct\Collection;/** * @extends Collection<LineItem> */class LineItemCollection extends Collection{ public function __construct(iterable $elements = []) { parent::__construct(); foreach ($elements as $lineItem) { $this->add($lineItem); } } /** * @param LineItem $lineItem * * @throws MixedLineItemTypeException * @throws InvalidQuantityException * @throws LineItemNotStackableException */ public function add($lineItem): void { $this->validateType($lineItem); $exists = $this->get($lineItem->getId()); if ($exists && $exists->getType() !== $lineItem->getType()) { if (Feature::isActive('v6.5.0.0')) { throw CartException::mixedLineItemType($lineItem->getId(), $lineItem->getType()); } throw new MixedLineItemTypeException($lineItem->getId(), $exists->getType()); } if ($exists) { $exists->setQuantity($lineItem->getQuantity() + $exists->getQuantity()); return; } $this->elements[$this->getKey($lineItem)] = $lineItem; } /** * @param int|string $key * @param LineItem $lineItem */ public function set($key, $lineItem): void { $this->validateType($lineItem); $this->elements[$this->getKey($lineItem)] = $lineItem; } public function removeElement(LineItem $lineItem): void { $this->remove($this->getKey($lineItem)); } public function exists(LineItem $lineItem): bool { return $this->has($this->getKey($lineItem)); } public function get($identifier): ?LineItem { if ($this->has($identifier)) { return $this->elements[$identifier]; } return null; } /** * @return LineItem[] */ public function filterFlatByType(string $type): array { $lineItems = $this->getFlat(); $filtered = []; foreach ($lineItems as $lineItem) { if ($lineItem->getType() === $type) { $filtered[] = $lineItem; } } return $filtered; } public function filterType(string $type): LineItemCollection { return $this->filter( function (LineItem $lineItem) use ($type) { return $lineItem->getType() === $type; } ); } public function getPayload(): array { return $this->map(function (LineItem $lineItem) { return $lineItem->getPayload(); }); } public function getPrices(): PriceCollection { return new PriceCollection( array_filter(array_map(static function (LineItem $lineItem) { return $lineItem->getPrice(); }, array_values($this->getElements()))) ); } /** * @return LineItem[] */ public function getFlat(): array { return $this->buildFlat($this); } public function sortByPriority(): void { $lineItemsByPricePriority = []; /** @var LineItem $lineItem */ foreach ($this->elements as $lineItem) { $priceDefinitionPriority = QuantityPriceDefinition::SORTING_PRIORITY; if ($lineItem->getPriceDefinition()) { $priceDefinitionPriority = $lineItem->getPriceDefinition()->getPriority(); } if (!\array_key_exists($priceDefinitionPriority, $lineItemsByPricePriority)) { $lineItemsByPricePriority[$priceDefinitionPriority] = []; } $lineItemsByPricePriority[$priceDefinitionPriority][] = $lineItem; } // Sort all line items by their price definition priority krsort($lineItemsByPricePriority); if (\count($lineItemsByPricePriority)) { $this->elements = array_merge(...$lineItemsByPricePriority); } } public function filterGoods(): self { return $this->filter( function (LineItem $lineItem) { return $lineItem->isGood(); } ); } /** * @return LineItem[] */ public function filterGoodsFlat(): array { $lineItems = $this->getFlat(); $filtered = []; foreach ($lineItems as $lineItem) { if ($lineItem->isGood()) { $filtered[] = $lineItem; } } return $filtered; } public function getTypes(): array { return $this->fmap( function (LineItem $lineItem) { return $lineItem->getType(); } ); } public function getReferenceIds(): array { return $this->fmap( function (LineItem $lineItem) { return $lineItem->getReferencedId(); } ); } public function getApiAlias(): string { return 'cart_line_item_collection'; } public function getTotalQuantity(): int { return $this->reduce(function ($result, $item) { return $result + $item->getQuantity(); }, 0); } protected function getKey(LineItem $element): string { return $element->getId(); } protected function getExpectedClass(): ?string { return LineItem::class; } private function buildFlat(LineItemCollection $lineItems): array { $flat = []; foreach ($lineItems as $lineItem) { $flat[] = $lineItem; foreach ($this->buildFlat($lineItem->getChildren()) as $nest) { $flat[] = $nest; } } return $flat; }}