vendor/shopware/core/Content/Product/DataAbstractionLayer/CheapestPrice/CheapestPriceContainer.php line 12

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Product\DataAbstractionLayer\CheapestPrice;
  3. use Shopware\Core\Checkout\Cart\Price\Struct\CartPrice;
  4. use Shopware\Core\Defaults;
  5. use Shopware\Core\Framework\Context;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Pricing\Price;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Pricing\PriceCollection;
  8. use Shopware\Core\Framework\Struct\Struct;
  9. class CheapestPriceContainer extends Struct
  10. {
  11.     /**
  12.      * @var array<mixed>
  13.      */
  14.     protected array $value;
  15.     /**
  16.      * @var array<mixed>|null
  17.      */
  18.     protected ?array $default null;
  19.     /**
  20.      * @var list<string>|null
  21.      */
  22.     private ?array $ruleIds null;
  23.     /**
  24.      * @param array<mixed> $value
  25.      */
  26.     public function __construct(array $value)
  27.     {
  28.         if (isset($value['default'])) {
  29.             $this->default $value['default'];
  30.             unset($value['default']);
  31.         }
  32.         $this->value $value;
  33.     }
  34.     public function resolve(Context $context): ?CheapestPrice
  35.     {
  36.         $ruleIds $context->getRuleIds();
  37.         $ruleIds[] = 'default';
  38.         $prices = [];
  39.         $defaultWasAdded false;
  40.         foreach ($this->value as $variantId => $group) {
  41.             foreach ($ruleIds as $ruleId) {
  42.                 $price $this->filterByRuleId($group$ruleId$defaultWasAdded);
  43.                 if ($price === null) {
  44.                     continue;
  45.                 }
  46.                 // overwrite the variantId in case the default price was added
  47.                 $price['variant_id'] = $variantId;
  48.                 $prices[] = $price;
  49.                 break;
  50.             }
  51.         }
  52.         if (empty($prices)) {
  53.             return null;
  54.         }
  55.         $cheapest array_shift($prices);
  56.         $reference $this->getPriceValue($cheapest$context);
  57.         $hasRange = (bool) $cheapest['is_ranged'];
  58.         // NEXT-21735 - This is covered randomly
  59.         // @codeCoverageIgnoreStart
  60.         foreach ($prices as $price) {
  61.             $current $this->getPriceValue($price$context);
  62.             if ($current === null) {
  63.                 continue;
  64.             }
  65.             if ($current !== $reference || $price['is_ranged']) {
  66.                 $hasRange true;
  67.             }
  68.             if ($current $reference) {
  69.                 $reference $current;
  70.                 $cheapest $price;
  71.             }
  72.         }
  73.         // @codeCoverageIgnoreEnd
  74.         $object = new CheapestPrice();
  75.         $object->setRuleId($cheapest['rule_id']);
  76.         $object->setVariantId($cheapest['variant_id']);
  77.         $object->setParentId($cheapest['parent_id']);
  78.         $object->setHasRange($hasRange);
  79.         $object->setPurchase($cheapest['purchase_unit'] ? (float) $cheapest['purchase_unit'] : null);
  80.         $object->setReference($cheapest['reference_unit'] ? (float) $cheapest['reference_unit'] : null);
  81.         $object->setUnitId($cheapest['unit_id'] ?? null);
  82.         $prices = [];
  83.         $blueprint = new Price(''11true);
  84.         foreach ($cheapest['price'] as $row) {
  85.             $price = clone $blueprint;
  86.             $price->setCurrencyId($row['currencyId']);
  87.             $price->setGross((float) $row['gross']);
  88.             $price->setNet((float) $row['net']);
  89.             $price->setLinked((bool) $row['linked']);
  90.             if (isset($row['listPrice'])) {
  91.                 $list = clone $blueprint;
  92.                 $list->setCurrencyId($row['currencyId']);
  93.                 $list->setGross((float) $row['listPrice']['gross']);
  94.                 $list->setNet((float) $row['listPrice']['net']);
  95.                 $list->setLinked((bool) $row['listPrice']['linked']);
  96.                 $price->setListPrice($list);
  97.             }
  98.             if (isset($row['regulationPrice'])) {
  99.                 $regulation = clone $blueprint;
  100.                 $regulation->setCurrencyId($row['currencyId']);
  101.                 $regulation->setGross((float) $row['regulationPrice']['gross']);
  102.                 $regulation->setNet((float) $row['regulationPrice']['net']);
  103.                 $regulation->setLinked((bool) $row['regulationPrice']['linked']);
  104.                 $price->setRegulationPrice($regulation);
  105.             }
  106.             if (isset($row['percentage'])) {
  107.                 $price->setPercentage([
  108.                     'gross' => $row['percentage']['gross'],
  109.                     'net' => $row['percentage']['net'],
  110.                 ]);
  111.             }
  112.             $prices[] = $price;
  113.         }
  114.         $object->setPrice(new PriceCollection($prices));
  115.         return $object;
  116.     }
  117.     public function getApiAlias(): string
  118.     {
  119.         return 'cheapest_price_container';
  120.     }
  121.     /**
  122.      * @return array<mixed>
  123.      */
  124.     public function getValue(): array
  125.     {
  126.         return $this->value;
  127.     }
  128.     /**
  129.      * @return array<mixed>
  130.      */
  131.     public function getPricesForVariant(string $variantId): array
  132.     {
  133.         return $this->value[$variantId] ?? [];
  134.     }
  135.     /**
  136.      * @return array<string>
  137.      */
  138.     public function getVariantIds(): array
  139.     {
  140.         return \array_keys($this->value);
  141.     }
  142.     /**
  143.      * @return array<mixed>
  144.      */
  145.     public function getDefault(): ?array
  146.     {
  147.         return $this->default;
  148.     }
  149.     /**
  150.      * @return list<string>
  151.      */
  152.     public function getRuleIds(): array
  153.     {
  154.         if ($this->ruleIds === null) {
  155.             $ruleIds = [];
  156.             foreach ($this->value as $group) {
  157.                 foreach ($group as $price) {
  158.                     /** @var string|null $ruleId */
  159.                     $ruleId $price['rule_id'] ?? null;
  160.                     if ($ruleId === null) {
  161.                         continue;
  162.                     }
  163.                     $ruleIds[$price['rule_id']] = true;
  164.                 }
  165.             }
  166.             /** @var list<string> $ruleIds */
  167.             $ruleIds array_keys($ruleIds);
  168.             $this->ruleIds $ruleIds;
  169.         }
  170.         return $this->ruleIds;
  171.     }
  172.     /**
  173.      * @param array<mixed> $prices
  174.      *
  175.      * @return array<mixed>|null
  176.      */
  177.     private function filterByRuleId(array $pricesstring $ruleIdbool &$defaultWasAdded): ?array
  178.     {
  179.         if (\array_key_exists($ruleId$prices)) {
  180.             // Null Price is the marker that the default price is inherited
  181.             if ($prices[$ruleId] === null && !$defaultWasAdded) {
  182.                 // Make sure to add the default price only once, to not bloat up the intermediate prices array
  183.                 $defaultWasAdded true;
  184.                 return $this->default;
  185.             }
  186.             return $prices[$ruleId];
  187.         }
  188.         return null;
  189.     }
  190.     /**
  191.      * @param array<mixed> $price
  192.      */
  193.     private function getPriceValue(array $priceContext $context): ?float
  194.     {
  195.         $currency $this->getCurrencyPrice($price['price'], $context->getCurrencyId());
  196.         if (!$currency) {
  197.             return null;
  198.         }
  199.         $value $context->getTaxState() === CartPrice::TAX_STATE_GROSS $currency['gross'] : $currency['net'];
  200.         if ($currency['currencyId'] !== $context->getCurrencyId()) {
  201.             $value *= $context->getCurrencyFactor();
  202.         }
  203.         return $value;
  204.     }
  205.     /**
  206.      * @param array<mixed> $collection
  207.      *
  208.      * @return array<mixed>|null
  209.      */
  210.     private function getCurrencyPrice(array $collectionstring $currencyIdbool $fallback true): ?array
  211.     {
  212.         foreach ($collection as $price) {
  213.             if ($price['currencyId'] === $currencyId) {
  214.                 return $price;
  215.             }
  216.         }
  217.         if (!$fallback) {
  218.             return null;
  219.         }
  220.         return $this->getCurrencyPrice($collectionDefaults::CURRENCYfalse);
  221.     }
  222. }