custom/plugins/LenzPlatformDistributionRestrictions/src/Subscriber/CheckoutSubscriber.php line 58

Open in your IDE?
  1. <?php
  2. namespace Lenz\DistributionRestrictions\Subscriber;
  3. use Lenz\DistributionRestrictions\Core\Checkout\Cart\DistributionRestrictionError;
  4. use Shopware\Core\Checkout\Cart\AbstractRuleLoader;
  5. use Shopware\Core\Checkout\Cart\CachedRuleLoader;
  6. use Shopware\Core\Checkout\Cart\Cart;
  7. use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
  8. use Shopware\Core\Checkout\Cart\Rule\CartRuleScope;
  9. use Shopware\Core\Checkout\Cart\RuleLoader;
  10. use Shopware\Core\Content\Rule\RuleCollection;
  11. use Shopware\Core\Content\Rule\RuleEntity;
  12. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  13. use Shopware\Core\Framework\Rule\Container\AndRule;
  14. use Shopware\Core\Framework\Rule\Container\OrRule;
  15. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  16. use Shopware\Core\System\SystemConfig\SystemConfigService;
  17. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Contracts\Translation\TranslatorInterface;
  20. /**
  21.  * @RouteScope(scopes={"storefront"})
  22.  */
  23. class CheckoutSubscriber implements EventSubscriberInterface
  24. {
  25.     /**
  26.      * @var SystemConfigService
  27.      */
  28.     private $systemConfigService;
  29.     /**
  30.      * @var AbstractRuleLoader
  31.      */
  32.     private $ruleLoader;
  33.     /**
  34.      * @var TranslatorInterface
  35.      */
  36.     private $translator;
  37.     public function __construct(
  38.         SystemConfigService $systemConfigService,
  39.         AbstractRuleLoader $ruleLoader,
  40.         TranslatorInterface $translator
  41.     )
  42.     {
  43.         $this->systemConfigService $systemConfigService;
  44.         $this->ruleLoader $ruleLoader;
  45.         $this->translator $translator;
  46.     }
  47.     public static function getSubscribedEvents()
  48.     {
  49.         return [
  50.             CheckoutConfirmPageLoadedEvent::class => 'onEvent',
  51.         ];
  52.     }
  53.     public function onEvent(CheckoutConfirmPageLoadedEvent $event) {
  54.     $salesChannelContext $event->getSalesChannelContext();
  55.         /** @var RuleCollection $rules */
  56.         $rules $this->ruleLoader->load($salesChannelContext->getContext());
  57.         $cart $event->getPage()->getCart();
  58.         $restrictionRules1 $this->systemConfigService->get('LenzPlatformDistributionRestrictions.config.restrictionRules1'$salesChannelContext->getSalesChannel()->getId()) ?? [];
  59.         $restrictionRules2 $this->systemConfigService->get('LenzPlatformDistributionRestrictions.config.restrictionRules2'$salesChannelContext->getSalesChannel()->getId()) ?? [];
  60.         $restrictionRules3 $this->systemConfigService->get('LenzPlatformDistributionRestrictions.config.restrictionRules3'$salesChannelContext->getSalesChannel()->getId()) ?? [];
  61.         $restrictionRules4 $this->systemConfigService->get('LenzPlatformDistributionRestrictions.config.restrictionRules4'$salesChannelContext->getSalesChannel()->getId()) ?? [];
  62.         $restrictionRules5 $this->systemConfigService->get('LenzPlatformDistributionRestrictions.config.restrictionRules5'$salesChannelContext->getSalesChannel()->getId()) ?? [];
  63.         $currentRules $salesChannelContext->getRuleIds();
  64.         $errors = [];
  65.         // Rule 1.
  66.         if($this->doesRuleMatch($currentRules$restrictionRules1))
  67.         {
  68.             $lineItems $this->getMatchingLineItems($cart$rules$restrictionRules1$salesChannelContext);
  69.             $error = new DistributionRestrictionError(
  70.                 '1',
  71.                 [
  72.                     'name' => $this->getRuleNotice($lineItems),
  73.                 ]
  74.             );
  75.             $errors[] = $error;
  76.         }
  77.         // Rule 2.
  78.         if($this->doesRuleMatch($currentRules$restrictionRules2))
  79.         {
  80.             $lineItems $this->getMatchingLineItems($cart$rules$restrictionRules2$salesChannelContext);
  81.             $error = new DistributionRestrictionError(
  82.                 '2',
  83.                 [
  84.                     'name' => $this->getRuleNotice($lineItems),
  85.                 ]
  86.             );
  87.             $errors[] = $error;
  88.         }
  89.         // Rule 3.
  90.         if($this->doesRuleMatch($currentRules$restrictionRules3))
  91.         {
  92.             $lineItems $this->getMatchingLineItems($cart$rules$restrictionRules3$salesChannelContext);
  93.             $error = new DistributionRestrictionError(
  94.                 '3',
  95.                 [
  96.                     'name' => $this->getRuleNotice($lineItems),
  97.                 ]
  98.             );
  99.             $errors[] = $error;
  100.         }
  101.         // Rule 4.
  102.         if($this->doesRuleMatch($currentRules$restrictionRules4))
  103.         {
  104.             $lineItems $this->getMatchingLineItems($cart$rules$restrictionRules4$salesChannelContext);
  105.             $error = new DistributionRestrictionError(
  106.                 '4',
  107.                 [
  108.                     'name' => $this->getRuleNotice($lineItems),
  109.                 ]
  110.             );
  111.             $errors[] = $error;
  112.         }
  113.         // Rule 5.
  114.         if($this->doesRuleMatch($currentRules$restrictionRules5))
  115.         {
  116.             $lineItems $this->getMatchingLineItems($cart$rules$restrictionRules5$salesChannelContext);
  117.             $error = new DistributionRestrictionError(
  118.                 '5',
  119.                 [
  120.                     'name' => $this->getRuleNotice($lineItems),
  121.                 ]
  122.             );
  123.             $errors[] = $error;
  124.         }
  125.         $event->getPage()->getCart()->addErrors(
  126.             ...$errors
  127.         );
  128.     }
  129.     private function getMatchingLineItems(Cart $cart$rules$aRuleIdsSalesChannelContext $salesChannelContext) {
  130.         // Save line items to revert later.
  131.         $lineItems $cart->getLineItems();
  132.         $matchingLineItems = [];
  133.         /** @var RuleEntity $rule */
  134.         foreach ($rules as $rule)
  135.         {
  136.             if(!in_array($rule->getId(), $aRuleIds)) {
  137.                 continue;
  138.             }
  139.             if(!$this->hasLineItemRule($rule->getPayload())) {
  140.                 continue;
  141.             }
  142.             foreach ($lineItems as $lineItem) {
  143.                 $currentCart $cart;
  144.                 $cart->setLineItems(new LineItemCollection([$lineItem]));
  145.                 if(
  146.                     $rule->getPayload()->match(
  147.                         new CartRuleScope($cart$salesChannelContext)
  148.                     )
  149.                 ) {
  150.                     $matchingLineItems[] = $lineItem;
  151.                 }
  152.             }
  153.         }
  154.         // Revert line items to original.
  155.         $cart->setLineItems($lineItems);
  156.         return $matchingLineItems;
  157.     }
  158.     /**
  159.      * @param $rule \Shopware\Core\Framework\Rule\Rule
  160.      * @return false
  161.      */
  162.     private function hasLineItemRule($rule) {
  163.         $hasLineItemRule false;
  164.         if($rule instanceof AndRule || $rule instanceof OrRule) {
  165.             foreach ($rule->getRules() as $subRule) {
  166.                 if($this->hasLineItemRule($subRule)) {
  167.                     $hasLineItemRule true;
  168.                 }
  169.             }
  170.         } elseif(strpos(get_class($rule), '\LineItem') !== false) {
  171.             $hasLineItemRule true;
  172.         }
  173.         return $hasLineItemRule;
  174.     }
  175.     private function doesRuleMatch($currentRules$restrictionRules)
  176.     {
  177.         foreach ($currentRules as $currentRule) {
  178.             foreach ($restrictionRules as $restrictionRule) {
  179.                 if($restrictionRule === $currentRule) {
  180.                     return true;
  181.                 }
  182.             }
  183.         }
  184.         return false;
  185.     }
  186.     private function getMatchingRules($currentRules$restrictionRules)
  187.     {
  188.         $matchingRules = [];
  189.         foreach ($currentRules as $currentRule) {
  190.             foreach ($restrictionRules as $restrictionRule) {
  191.                 if($restrictionRule === $currentRule) {
  192.                     $matchingRules[] = $currentRule;
  193.                 }
  194.             }
  195.         }
  196.         return $matchingRules;
  197.     }
  198.     private function getRuleNotice(array $lineItems): ?string
  199.     {
  200.         if(count($lineItems) < 1) {
  201.             return null;
  202.         }
  203.         $aLineItemLabels array_map(function($e) {
  204.             return $e->getLabel();
  205.         }, $lineItems);
  206.         $lineItemLabels $this->translator->trans(
  207.             'checkout.lenz-distribution-restrictions-affected-line-items',
  208.             [
  209.                 '%lineItems%' => implode($this->translator->trans('checkout.lenz-distribution-restrictions-affected-line-items-separator'), $aLineItemLabels),
  210.             ]
  211.         );
  212.         return $lineItemLabels;
  213.     }
  214. }