src/Core/Checkout/Cart/Processor.php line 48

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Cart;
  3. use Shopware\Core\Checkout\Cart\Hook\CartHook;
  4. use Shopware\Core\Checkout\Cart\Price\AmountCalculator;
  5. use Shopware\Core\Checkout\Cart\Transaction\TransactionProcessor;
  6. use Shopware\Core\Framework\Log\Package;
  7. use Shopware\Core\Framework\Script\Execution\ScriptExecutor;
  8. use Shopware\Core\Profiling\Profiler;
  9. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  10. #[Package('checkout')]
  11. class Processor
  12. {
  13.     /**
  14.      * @internal
  15.      *
  16.      * @param iterable<CartProcessorInterface> $processors
  17.      * @param iterable<CartDataCollectorInterface> $collectors
  18.      */
  19.     public function __construct(private readonly Validator $validator, private readonly AmountCalculator $amountCalculator, private readonly TransactionProcessor $transactionProcessor, private readonly iterable $processors, private readonly iterable $collectors, private readonly ScriptExecutor $executor)
  20.     {
  21.     }
  22.     public function process(Cart $originalSalesChannelContext $contextCartBehavior $behavior): Cart
  23.     {
  24.         return Profiler::trace('cart::process', function () use ($original$context$behavior) {
  25.             $cart = new Cart($original->getToken());
  26.             $cart->setCustomerComment($original->getCustomerComment());
  27.             $cart->setAffiliateCode($original->getAffiliateCode());
  28.             $cart->setCampaignCode($original->getCampaignCode());
  29.             $cart->setBehavior($behavior);
  30.             $cart->addState(...$original->getStates());
  31.             // move data from previous calculation into new cart
  32.             $cart->setData($original->getData());
  33.             $this->runProcessors($original$cart$context$behavior);
  34.             if ($behavior->hookAware()) {
  35.                 $this->executor->execute(new CartHook($cart$context));
  36.             }
  37.             $this->calculateAmount($context$cart);
  38.             $cart->addErrors(
  39.                 ...$this->validator->validate($cart$context)
  40.             );
  41.             $cart->setTransactions(
  42.                 $this->transactionProcessor->process($cart$context)
  43.             );
  44.             $cart->setRuleIds($context->getRuleIds());
  45.             return $cart;
  46.         }, 'cart');
  47.     }
  48.     private function runProcessors(Cart $originalCart $cartSalesChannelContext $contextCartBehavior $behavior): void
  49.     {
  50.         if ($original->getLineItems()->count() <= 0) {
  51.             $cart->addErrors(...array_values($original->getErrors()->getPersistent()->getElements()));
  52.             $cart->setExtensions($original->getExtensions());
  53.             return;
  54.         }
  55.         // enrich cart with all required data
  56.         foreach ($this->collectors as $collector) {
  57.             $collector->collect($cart->getData(), $original$context$behavior);
  58.         }
  59.         $cart->addErrors(...array_values($original->getErrors()->getPersistent()->getElements()));
  60.         $cart->setExtensions($original->getExtensions());
  61.         $this->calculateAmount($context$cart);
  62.         // start processing, cart will be filled step by step with line items of original cart
  63.         foreach ($this->processors as $processor) {
  64.             $processor->process($cart->getData(), $original$cart$context$behavior);
  65.             $this->calculateAmount($context$cart);
  66.         }
  67.     }
  68.     private function calculateAmount(SalesChannelContext $contextCart $cart): void
  69.     {
  70.         $amount $this->amountCalculator->calculate(
  71.             $cart->getLineItems()->getPrices(),
  72.             $cart->getDeliveries()->getShippingCosts(),
  73.             $context
  74.         );
  75.         $cart->setPrice($amount);
  76.     }
  77. }