From e1b6e8c9b05b575417a2d487506974bffea9aa73 Mon Sep 17 00:00:00 2001 From: Oliver Skroblin Date: Tue, 27 Oct 2020 10:31:10 +0100 Subject: [PATCH] NEXT-11653 - Fix priority in cart and rule loading --- src/Core/Checkout/Cart/CartRuleLoader.php | 28 +++++++++++++++++------ src/Core/Content/Rule/RuleCollection.php | 15 ++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/Core/Checkout/Cart/CartRuleLoader.php b/src/Core/Checkout/Cart/CartRuleLoader.php index be1acf1c1cb..243780e2189 100644 --- a/src/Core/Checkout/Cart/CartRuleLoader.php +++ b/src/Core/Checkout/Cart/CartRuleLoader.php @@ -12,7 +12,7 @@ class CartRuleLoader { public const CHECKOUT_RULE_LOADER_CACHE_KEY = 'all-rules'; - private const MAX_ITERATION = 5; + private const MAX_ITERATION = 7; /** * @var CartPersisterInterface @@ -84,29 +84,43 @@ private function load(SalesChannelContext $context, Cart $cart, CartBehavior $be { $rules = $this->loadRules($context->getContext()); + // save all rules for later usage + $all = $rules; + + // update rules in current context $context->setRuleIds($rules->getIds()); $iteration = 1; + // start first cart calculation to have all objects enriched $cart = $this->processor->process($cart, $context, $behaviorContext); do { + $compare = $cart; + if ($iteration > self::MAX_ITERATION) { break; } - //find rules which matching current cart and context state + // filter rules which matches to current scope $rules = $rules->filterMatchingRules($cart, $context); - //place rules into context for further usages + // update matching rules in context $context->setRuleIds($rules->getIds()); - //recalculate cart for new context rules - $new = $this->processor->process($cart, $context, $behaviorContext); + // calculate cart again + $cart = $this->processor->process($cart, $context, $behaviorContext); - $recalculate = $this->cartChanged($cart, $new); + // check if the cart changed, in this case we have to recalculate the cart again + $recalculate = $this->cartChanged($cart, $compare); - $cart = $new; + // check if rules changed for the last calculated cart, in this case we have to recalculate + $ruleCompare = $all->filterMatchingRules($cart, $context); + + if (!$rules->equals($ruleCompare)) { + $recalculate = true; + $rules = $ruleCompare; + } ++$iteration; } while ($recalculate); diff --git a/src/Core/Content/Rule/RuleCollection.php b/src/Core/Content/Rule/RuleCollection.php index cad38094200..c0af079e857 100644 --- a/src/Core/Content/Rule/RuleCollection.php +++ b/src/Core/Content/Rule/RuleCollection.php @@ -34,6 +34,21 @@ public function sortByPriority(): void }); } + public function equals(RuleCollection $rules): bool + { + if ($this->count() !== $rules->count()) { + return false; + } + + foreach ($this->elements as $element) { + if (!$rules->has($element->getId())) { + return false; + } + } + + return true; + } + public function getApiAlias(): string { return 'rule_collection';