custom/plugins/AcrisRuleSurchargeDiscountCS/src/Core/Checkout/SurchargeDiscount/Cart/SurchargeDiscountCollector.php line 246

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Acris\RuleSurchargeDiscount\Core\Checkout\SurchargeDiscount\Cart;
  3. use Acris\RuleSurchargeDiscount\Storefront\Subscriber\SurchargeDiscountTagSubscriber;
  4. use Acris\RuleSurchargeDiscount\Components\Service\SurchargeDiscountRecalculationService;
  5. use Acris\RuleSurchargeDiscount\Custom\SurchargeDiscountCollection;
  6. use Acris\RuleSurchargeDiscount\Custom\SurchargeDiscountEntity;
  7. use Shopware\Core\Checkout\Cart\Cart;
  8. use Shopware\Core\Checkout\Cart\CartBehavior;
  9. use Shopware\Core\Checkout\Cart\CartDataCollectorInterface;
  10. use Shopware\Core\Checkout\Cart\LineItem\CartDataCollection;
  11. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  12. use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
  13. use Shopware\Core\Checkout\Cart\Price\Struct\AbsolutePriceDefinition;
  14. use Shopware\Core\Checkout\Customer\Aggregate\CustomerGroup\CustomerGroupDefinition;
  15. use Shopware\Core\Checkout\Promotion\Cart\PromotionCartInformationTrait;
  16. use Shopware\Core\Checkout\Promotion\Cart\PromotionProcessor;
  17. use Shopware\Core\Checkout\Promotion\Gateway\PromotionGatewayInterface;
  18. use Shopware\Core\Framework\Adapter\Cache\CacheValueCompressor;
  19. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  20. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  21. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  22. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  23. use Shopware\Core\System\Currency\CurrencyDefinition;
  24. use Shopware\Core\System\Language\LanguageDefinition;
  25. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  26. use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
  27. use Symfony\Contracts\Cache\ItemInterface;
  28. class SurchargeDiscountCollector implements CartDataCollectorInterface
  29. {
  30.     use PromotionCartInformationTrait;
  31.     public const BUILD_NAME 'acris-rule-surcharge-discount';
  32.     public const SKIP_SURCHARGE_DISCOUNT_ON_CART_RECALCULATION 'recalculation';
  33.     const ACRIS_SURCHAGE_DISCOUNT_RESULT 'acrisSurchageDiscountResult';
  34.     /**
  35.      * @var PromotionGatewayInterface
  36.      */
  37.     private PromotionGatewayInterface $gateway;
  38.     /**
  39.      * @var SurchargeDiscountItemBuilder
  40.      */
  41.     private SurchargeDiscountItemBuilder $itemBuilder;
  42.     /**
  43.      * @var EntityRepositoryInterface
  44.      */
  45.     private EntityRepositoryInterface $surchargeDiscountRepository;
  46.     /**
  47.      * @var TagAwareAdapterInterface
  48.      */
  49.     private TagAwareAdapterInterface $cache;
  50.     public function __construct(
  51.         PromotionGatewayInterface $gateway,
  52.         SurchargeDiscountItemBuilder $itemBuilder,
  53.         EntityRepositoryInterface $surchargeDiscountRepository,
  54.         TagAwareAdapterInterface $cache
  55.     )
  56.     {
  57.         $this->gateway $gateway;
  58.         $this->itemBuilder $itemBuilder;
  59.         $this->surchargeDiscountRepository $surchargeDiscountRepository;
  60.         $this->cache $cache;
  61.     }
  62.     /**
  63.      * @param CartDataCollection $data
  64.      * @param Cart $cart
  65.      * @param SalesChannelContext $context
  66.      * @param CartBehavior $behavior
  67.      */
  68.     public function collect(CartDataCollection $dataCart $cartSalesChannelContext $contextCartBehavior $behavior): void
  69.     {
  70.         $surchargeDiscountResult $this->getCachedValue($context);
  71.         // if we are in recalculation,
  72.         // we must not re-add any surcharges/discounts. just leave it as it is.
  73.         if ($behavior->hasPermission(AbstractSurchargeDiscountProcessor::SKIP_AUTOMATIC_SURCHARGE_DISCOUNT)) {
  74.             return;
  75.         }
  76.         $toggle false;
  77.         if ($context->hasExtension(SurchargeDiscountRecalculationService::TOGGLE_AUTOMATIC_SURCHARGE_DISCOUNT)) {
  78.             $toggle true;
  79.             $context->removeExtension(SurchargeDiscountRecalculationService::TOGGLE_AUTOMATIC_SURCHARGE_DISCOUNT);
  80.         }
  81.         $discountLineItems = [];
  82.         $lineItems $this->buildDiscountLineItems($surchargeDiscountResult->getEntities(), $cart$toggle$context);
  83.         /** @var LineItem $nested */
  84.         foreach ($lineItems as $nested) {
  85.             $discountLineItems[] = $nested;
  86.         }
  87.         if (count($discountLineItems) > 0) {
  88.             $data->set(AbstractSurchargeDiscountProcessor::DATA_KEY, new LineItemCollection($discountLineItems));
  89.         } else {
  90.             $data->remove(AbstractSurchargeDiscountProcessor::DATA_KEY);
  91.         }
  92.     }
  93.     /**
  94.      * @param SurchargeDiscountEntity $promotion
  95.      * @param Cart $cart
  96.      * @param SalesChannelContext $context
  97.      * @return array
  98.      */
  99.     private function buildDiscountLineItems(SurchargeDiscountCollection $collectionCart $cartbool $toggleSalesChannelContext $context): array
  100.     {
  101.         $lineItems = [];
  102.         $itemIds $this->getAllLineItemIds($cart);
  103.         $salesChannelId $context->getSalesChannel()->getId();
  104.         $rules = !empty($cart->getRuleIds()) ? $cart->getRuleIds() : $context->getRuleIds();
  105.         foreach ($collection->getElements() as $surchargeDiscount) {
  106.             $surchargeDiscountSalesChannels $surchargeDiscount->getSalesChannels();
  107.             $surchargeDiscountRules $surchargeDiscount->getRules();
  108.             $surchargeDiscountSalesChannelExists false;
  109.             foreach ($surchargeDiscountSalesChannels as $key => $surchargeDiscountSalesChannel) {
  110.                 if ($salesChannelId === $key) {
  111.                     $surchargeDiscountSalesChannelExists true;
  112.                 }
  113.             }
  114.             if (!$surchargeDiscountSalesChannelExists) continue;
  115.             $surchargeDiscountRulesExists false;
  116.             foreach ($surchargeDiscountRules as $key => $surchargeDiscountRule) {
  117.                 if (!empty($rules) && is_array($rules) && in_array($key$rules)) {
  118.                     $surchargeDiscountRulesExists true;
  119.                 }
  120.             }
  121.             if ($surchargeDiscountRules->count() === 0$surchargeDiscountRulesExists true;
  122.             if (!$surchargeDiscountRulesExists) {
  123.                 $originalLineItems = clone $cart->getLineItems();
  124.                 foreach ($cart->getLineItems() as $lineItem) {
  125.                     if ($lineItem->getType() !== LineItem::PRODUCT_LINE_ITEM_TYPE) {
  126.                         $cart->getLineItems()->remove($lineItem->getId());
  127.                     }
  128.                 }
  129.                 $match $surchargeDiscountRules->filterMatchingRules($cart$context)->count();
  130.                 $cart->setLineItems($originalLineItems);
  131.                 if (!$match 0) continue;
  132.             }
  133.             if (count($itemIds) <= 0) {
  134.                 continue;
  135.             }
  136.             $quantity 1;
  137.             $price null;
  138.             $changedPercentageToAbsolute null;
  139.             if ($cart->getName() === AbstractSurchargeDiscountProcessor::SKIP_SURCHARGE_DISCOUNT_ON_CART_RECALCULATION) {
  140.                 /** @var LineItem $surchargeDiscountLineItem */
  141.                 $surchargeDiscountLineItem $cart->getLineItems()->filter(function (LineItem $lineItem) use ($surchargeDiscount) {
  142.                     return $lineItem->hasPayloadValue('surchargeDiscountId') && $surchargeDiscount->getId() === $lineItem->getPayloadValue('surchargeDiscountId');
  143.                 })->first();
  144.                 if (!empty($surchargeDiscountLineItem)) {
  145.                     $quantity $surchargeDiscountLineItem->getQuantity();
  146.                     if (!empty($surchargeDiscountLineItem->getPriceDefinition()) && $surchargeDiscountLineItem->getPriceDefinition() instanceof AbsolutePriceDefinition) {
  147.                         $price $surchargeDiscountLineItem->getPriceDefinition()->getPrice();
  148.                     }
  149.                     if ($surchargeDiscountLineItem->getPayloadValue('discountType') === 'percentage' && !empty($surchargeDiscountLineItem->getPriceDefinition()) && $surchargeDiscountLineItem->getPriceDefinition() instanceof AbsolutePriceDefinition) {
  150.                         $price $surchargeDiscountLineItem->getPriceDefinition()->getPrice();
  151.                         $changedPercentageToAbsolute $price;
  152.                         $surchargeDiscount->setType('absolute');
  153.                     } elseif ($surchargeDiscountLineItem->getPayloadValue('discountType') === 'absolute' && $surchargeDiscountLineItem->hasPayloadValue('value')) {
  154.                         $price $surchargeDiscountLineItem->getPriceDefinition()->getPrice();
  155.                         $surchargeDiscount->setType('absolute');
  156.                     }
  157.                 }
  158.                 if (empty($surchargeDiscountLineItem) && $surchargeDiscount->getAssignMethod() === AbstractSurchargeDiscountProcessor::ASSIGN_METHOD_LINE_ITEM && !$toggle) {
  159.                     continue;
  160.                 }
  161.             }
  162.             /* @var LineItem $discountItem */
  163.             $discountItem $this->itemBuilder->buildLineItem(
  164.                 $surchargeDiscount,
  165.                 $context,
  166.                 $cart->getName() === AbstractSurchargeDiscountProcessor::SKIP_SURCHARGE_DISCOUNT_ON_CART_RECALCULATION,
  167.                 $quantity,
  168.                 $price
  169.             );
  170.             if (!empty($changedPercentageToAbsolute)) {
  171.                 $discountItem->setPayloadValue('changedValue'$changedPercentageToAbsolute);
  172.             }
  173.             $lineItems[] = $discountItem;
  174.         }
  175.         return $lineItems;
  176.     }
  177.     private function getAllLineItemIds(Cart $cart): array
  178.     {
  179.         return $cart->getLineItems()->fmap(
  180.             static function (LineItem $lineItem) {
  181.                 if ($lineItem->getType() === PromotionProcessor::LINE_ITEM_TYPE || $lineItem->getType() === AbstractSurchargeDiscountProcessor::LINE_ITEM_TYPE) {
  182.                     return null;
  183.                 }
  184.                 return $lineItem->getId();
  185.             }
  186.         );
  187.     }
  188.     private function getCachedValueSalesChannelContext $salesChannelContext){
  189.         $key $this->getCacheKey($salesChannelContext);
  190.         $value $this->cache->get($key, function (ItemInterface $item) use ($salesChannelContext) {
  191.             $criteria = new Criteria();
  192.             $criteria->addFilter(new EqualsFilter('active'true));
  193.             $criteria->addSorting(new FieldSorting('priority'FieldSorting::DESCENDING));
  194.             $criteria->addSorting(new FieldSorting('value'FieldSorting::ASCENDINGtrue));
  195.             $criteria->addAssociation('salesChannels');
  196.             $criteria->addAssociation('rules');
  197.             $criteria->addAssociation('discountRules');
  198.             $criteria->addAssociation('deliveryRules');
  199.             $criteria->addAssociation('tax');
  200.             $criteria->addAssociation('media');
  201.             $surchargeDiscountResult $this->surchargeDiscountRepository->search($criteria$salesChannelContext->getContext());
  202.             $item->tag([SurchargeDiscountTagSubscriber::ACRIS_SURCHARGE_DISCOUNT_ENTITY]);
  203.             $this->addCacheTagsForSalesChannelContext($item$salesChannelContext);
  204.             return CacheValueCompressor::compress($surchargeDiscountResult);
  205.         });
  206.         return CacheValueCompressor::uncompress($value);
  207.     }
  208.     private function getCacheKey(SalesChannelContext $salesChannelContext): string
  209.     {
  210.         return self::BUILD_NAME '-' md5(\json_encode([
  211.             $salesChannelContext->getSalesChannel()->getId(),
  212.             $salesChannelContext->getCurrentCustomerGroup()->getId(),
  213.             $salesChannelContext->getCurrency()->getId(),
  214.             $salesChannelContext->getContext()->getLanguageId(),
  215.             $salesChannelContext->getRuleIds()
  216.         ]));
  217.     }
  218.     private function addCacheTagsForSalesChannelContext(ItemInterface $itemSalesChannelContext $salesChannelContext)
  219.     {
  220.         $item->tag(CustomerGroupDefinition::ENTITY_NAME '-' $salesChannelContext->getCurrentCustomerGroup()->getId());
  221.         $item->tag(CurrencyDefinition::ENTITY_NAME '-' $salesChannelContext->getCurrency()->getId());
  222.         $item->tag(LanguageDefinition::ENTITY_NAME '-' $salesChannelContext->getContext()->getLanguageId());
  223.     }
  224. }