vendor/shopware/core/Checkout/Cart/Processor.php line 61

  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(
  20.         private readonly Validator $validator,
  21.         private readonly AmountCalculator $amountCalculator,
  22.         private readonly TransactionProcessor $transactionProcessor,
  23.         private readonly iterable $processors,
  24.         private readonly iterable $collectors,
  25.         private readonly ScriptExecutor $executor
  26.     ) {
  27.     }
  28.     public function process(Cart $originalSalesChannelContext $contextCartBehavior $behavior): Cart
  29.     {
  30.         return Profiler::trace('cart::process', function () use ($original$context$behavior) {
  31.             $cart = new Cart($original->getToken());
  32.             $cart->setCustomerComment($original->getCustomerComment());
  33.             $cart->setAffiliateCode($original->getAffiliateCode());
  34.             $cart->setCampaignCode($original->getCampaignCode());
  35.             $cart->setBehavior($behavior);
  36.             $cart->addState(...$original->getStates());
  37.             if ($behavior->hookAware()) {
  38.                 // reset modified state that apps always have the same entry state
  39.                 foreach ($original->getLineItems()->getFlat() as $item) {
  40.                     $item->markUnModifiedByApp();
  41.                 }
  42.             }
  43.             // move data from previous calculation into new cart
  44.             $cart->setData($original->getData());
  45.             $this->runProcessors($original$cart$context$behavior);
  46.             if ($behavior->hookAware()) {
  47.                 $this->executor->execute(new CartHook($cart$context));
  48.             }
  49.             $this->calculateAmount($context$cart);
  50.             $cart->addErrors(
  51.                 ...$this->validator->validate($cart$context)
  52.             );
  53.             $cart->setTransactions(
  54.                 $this->transactionProcessor->process($cart$context)
  55.             );
  56.             $cart->setRuleIds($context->getRuleIds());
  57.             return $cart;
  58.         }, 'cart');
  59.     }
  60.     private function runProcessors(Cart $originalCart $cartSalesChannelContext $contextCartBehavior $behavior): void
  61.     {
  62.         if ($original->getLineItems()->count() <= 0) {
  63.             $cart->addErrors(...array_values($original->getErrors()->getPersistent()->getElements()));
  64.             $cart->setExtensions($original->getExtensions());
  65.             return;
  66.         }
  67.         // enrich cart with all required data
  68.         foreach ($this->collectors as $collector) {
  69.             $collector->collect($cart->getData(), $original$context$behavior);
  70.         }
  71.         $cart->addErrors(...array_values($original->getErrors()->getPersistent()->getElements()));
  72.         $cart->setExtensions($original->getExtensions());
  73.         $this->calculateAmount($context$cart);
  74.         // start processing, cart will be filled step by step with line items of original cart
  75.         foreach ($this->processors as $processor) {
  76.             $processor->process($cart->getData(), $original$cart$context$behavior);
  77.             $this->calculateAmount($context$cart);
  78.         }
  79.     }
  80.     private function calculateAmount(SalesChannelContext $contextCart $cart): void
  81.     {
  82.         $amount $this->amountCalculator->calculate(
  83.             $cart->getLineItems()->getPrices(),
  84.             $cart->getDeliveries()->getShippingCosts(),
  85.             $context
  86.         );
  87.         $cart->setPrice($amount);
  88.     }
  89. }