custom/plugins/AcrisProductBadgesCS/src/Components/ProductBadges/ProductBadgesService.php line 34

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Acris\ProductBadges\Components\ProductBadges;
  3. use Acris\ProductBadges\Components\ProductBadges\Struct\ProductStreamStruct;
  4. use Acris\ProductBadges\Custom\ProductBadgesCollection;
  5. use Acris\ProductBadges\Custom\ProductBadgesEntity;
  6. use Acris\ProductBadges\Storefront\Subscriber\ProductBadgeSubscriber;
  7. use Shopware\Core\Checkout\Promotion\PromotionEntity;
  8. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  9. use Shopware\Core\Content\ProductStream\ProductStreamCollection;
  10. use Shopware\Core\Framework\Context;
  11. use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
  12. use Shopware\Core\Framework\Struct\ArrayEntity;
  13. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  14. class ProductBadgesService
  15. {
  16.     public const PRODUCT_BADGE_DISPLAY_CONDITION_RULES_AND_DYNAMIC_PRODUCT_GROUPS 'product_group_and_rule';
  17.     public const PRODUCT_BADGE_DISPLAY_CONDITION_PROMOTIONS 'promotion';
  18.     public const PRODUCT_BADGE_DISPLAY_CONDITION_REPLACE_DEFAULT_BADGE 'replace_default_badges';
  19.     /**
  20.      * @var ProductBadgesGateway
  21.      */
  22.     private $productBadgesGateway;
  23.     public function __construct(
  24.         ProductBadgesGateway $productBadgesGateway
  25.     ) {
  26.         $this->productBadgesGateway $productBadgesGateway;
  27.     }
  28.     public function addBadgesToProducts(EntityCollection $productCollectionSalesChannelContext $salesChannelContext)
  29.     {
  30.         $productStreamStruct $this->getAllProductStreams($productCollection$salesChannelContext->getContext());
  31.         $originalProductBadgesCollection $this->productBadgesGateway->getAllProductBadges($productStreamStruct->getAllProductStreamIds(), $salesChannelContext);
  32.         if ($originalProductBadgesCollection->count() === 0) return;
  33.         /** @var SalesChannelProductEntity $product */
  34.         foreach ($productCollection->getElements() as $product) {
  35.             if ($product->hasExtension(ProductBadgeSubscriber::ACRIS_STREAM_IDS_EXTENSION) && !empty($product->getExtension(ProductBadgeSubscriber::ACRIS_STREAM_IDS_EXTENSION))) {
  36.                 $productStreamIds $product->getExtension(ProductBadgeSubscriber::ACRIS_STREAM_IDS_EXTENSION)->get('ids');
  37.             } else {
  38.                 $productStreamIds $productStreamStruct->getProductStreamIdsForProductId($product->getId());
  39.                 $product->addExtension(ProductBadgeSubscriber::ACRIS_STREAM_IDS_EXTENSION, new ArrayEntity(['ids' => $productStreamIds]));
  40.             }
  41.             $productBadgesCollection $this->getProductBadgesForProduct($originalProductBadgesCollection$productStreamIds);
  42.             if ($productBadgesCollection->count() === 0) {
  43.                 continue;
  44.             }
  45.             $this->replaceDefaultBadges($productBadgesCollection$salesChannelContext);
  46.             $this->assignProductBadgesToProducts($product$productBadgesCollection);
  47.         }
  48.     }
  49.     private function assignProductBadgesToProducts(SalesChannelProductEntity $productEntityCollection $productBadgesCollection)
  50.     {
  51.         /** @var ProductBadgesEntity $productBadge */
  52.         foreach ($productBadgesCollection->getElements() as $productBadge) {
  53.             if ($this->checkIndividualPromotionDisplay($product$productBadge) == false) {
  54.                 continue;
  55.             }
  56.             $this->addBadgeToExtension($product$productBadge);
  57.         }
  58.         /* We have to proof the sale badge - should be only displayed if product has no promotions or   */
  59.         /** @var ProductBadgesEntity $productBadge */
  60.         foreach ($productBadgesCollection->getElements() as $productBadge) {
  61.             if ($productBadge->getIsDefault() !== true || $productBadge->getInternalName() !== 'Sale') {
  62.                 continue;
  63.             }
  64.             if ($this->shouldRemoveSaleBadge($product) === true) {
  65.                 $this->removeBadgeFromExtension($product$productBadge);
  66.             }
  67.         }
  68.     }
  69.     private function addBadgeToExtension(SalesChannelProductEntity $productProductBadgesEntity $productBadge): void
  70.     {
  71.         if ($product->hasExtension('acrisProductBadges')) {
  72.             /** @var ProductBadgesCollection $productBadges */
  73.             $productBadges $product->getExtension('acrisProductBadges');
  74.             $productBadges->add($productBadge);
  75.         } else {
  76.             $productBadges = new ProductBadgesCollection();
  77.             $productBadges->add($productBadge);
  78.             $product->addExtension('acrisProductBadges'$productBadges);
  79.         }
  80.     }
  81.     private function removeBadgeFromExtension(SalesChannelProductEntity $productProductBadgesEntity $productBadge): void
  82.     {
  83.         if ($product->hasExtension('acrisProductBadges')) {
  84.             /** @var ProductBadgesCollection $productBadges */
  85.             $productBadges $product->getExtension('acrisProductBadges');
  86.             if ($productBadges->has($productBadge->getId())) {
  87.                 $productBadges->remove($productBadge->getId());
  88.             }
  89.         }
  90.     }
  91.     private function checkIndividualPromotionDisplay(SalesChannelProductEntity $productProductBadgesEntity $productBadge): bool
  92.     {
  93.         if ($productBadge->getDisplayCondition() === self::PRODUCT_BADGE_DISPLAY_CONDITION_PROMOTIONS) {
  94.             if ($product->hasExtension('acrisPromotion') && $product->getExtension('acrisPromotion') instanceof ArrayEntity) {
  95.                 $promotionIds $product->getExtension('acrisPromotion')->get('promotionIds');
  96.                 foreach ($promotionIds as $promotionId) {
  97.                     if (in_array($promotionId$productBadge->getPromotions()->getIds()) === true) {
  98.                         return true;
  99.                     }
  100.                 }
  101.             }
  102.             return false;
  103.         }
  104.         return true;
  105.     }
  106.     private function shouldRemoveSaleBadge(SalesChannelProductEntity $product): bool
  107.     {
  108.         // in a second step we add the sale badge again
  109.         if ($product->hasExtension('acrisPromotion') === false || !$product->getExtension('acrisPromotion') instanceof ArrayEntity || empty($product->getExtension('acrisPromotion')->get('promotionIds')) === true) {
  110.             return false;
  111.         }
  112.         if ($product->hasExtension('acrisProductBadges') !== true || empty($product->getExtension('acrisProductBadges')) === true) {
  113.             return false;
  114.         }
  115.         $promotionIds $product->getExtension('acrisPromotion')->get('promotionIds');
  116.         $productBadges $product->getExtension('acrisProductBadges');
  117.         /** @var ProductBadgesEntity $productBadge */
  118.         foreach ($productBadges as $productBadge) {
  119.             if ($productBadge->getDisplayCondition() === self::PRODUCT_BADGE_DISPLAY_CONDITION_PROMOTIONS) {
  120.                 /** @var PromotionEntity $promotion */
  121.                 foreach ($productBadge->getPromotions() as $promotion) {
  122.                     if (in_array($promotion->getId(), $promotionIds)) {
  123.                         if (($key array_search($promotion->getId(), $promotionIds)) !== false) {
  124.                             unset($promotionIds[$key]);
  125.                         }
  126.                     }
  127.                 }
  128.             }
  129.         }
  130.         if (empty($promotionIds) === true) {
  131.             return true;
  132.         }
  133.         return false;
  134.     }
  135.     private function replaceDefaultBadges(EntityCollection $productBadgesCollectionSalesChannelContext $salesChannelContext): void
  136.     {
  137.         if (!$productBadgesCollection instanceof ProductBadgesCollection) return;
  138.         foreach ($productBadgesCollection->getElements() as $productBadge) {
  139.             if ($productBadge->getDisplayCondition() === self::PRODUCT_BADGE_DISPLAY_CONDITION_REPLACE_DEFAULT_BADGE && !empty($productBadge->getReplaceDefaultBadgeId()) && $productBadgesCollection->has($productBadge->getReplaceDefaultBadgeId()) && $productBadge->getId() !== $productBadge->getReplaceDefaultBadgeId()) {
  140.                 $defaultBadge $productBadgesCollection->get($productBadge->getReplaceDefaultBadgeId());
  141.                 $rulesExists $productBadge->getReplaceRules()->count() <= 0;
  142.                 if ($productBadge->getReplaceRules()->count() > 0) {
  143.                     foreach ($productBadge->getReplaceRules() as $rule) {
  144.                         if (in_array($rule->getId(), $salesChannelContext->getRuleIds())) $rulesExists true;
  145.                     }
  146.                 }
  147.                 if ($rulesExists) {
  148.                     $productBadge->setDefaultType($defaultBadge->getDefaultType());
  149.                     $productBadge->setIsDefault(true);
  150.                     $productBadge->setInternalName($defaultBadge->getInternalName());
  151.                     $productBadgesCollection->remove($productBadge->getReplaceDefaultBadgeId());
  152.                 }
  153.                 if ($productBadge->getActive() !== true || $defaultBadge->getActive() !== true || $rulesExists !== true$productBadgesCollection->remove($productBadge->getId());
  154.             } else {
  155.                 if ($productBadge->getActive() !== true$productBadgesCollection->remove($productBadge->getId());
  156.             }
  157.         }
  158.     }
  159.     private function getAllProductStreams(EntityCollection $productCollectionContext $context): ProductStreamStruct
  160.     {
  161.         $productStreamStruct = new ProductStreamStruct();
  162.         $productIds = [];
  163.         /** @var SalesChannelProductEntity $product */
  164.         foreach ($productCollection->getElements() as $product) {
  165.             if ($product->hasExtension(ProductBadgeSubscriber::ACRIS_STREAM_IDS_EXTENSION)) {
  166.                 $productStreamStruct->addProductStreamIds($product->getId(), $product->getExtension(ProductBadgeSubscriber::ACRIS_STREAM_IDS_EXTENSION)->get('ids'));
  167.             // new way of ACRIS - the association is directly added to the product criteria by sales_channel.product.process.criteria
  168.             } elseif($product->getStreams() instanceof ProductStreamCollection) {
  169.                 $productStreamStruct->addProductStreamIds($product->getId(), $product->getStreams()->getIds());
  170.             } else {
  171.                 $productIds[] = $product->getId();
  172.             }
  173.         }
  174.         if (!empty($productIds)) {
  175.             $this->productBadgesGateway->getProductStreamIds($productStreamStruct$productIds$context);
  176.         }
  177.         return $productStreamStruct;
  178.     }
  179.     private function getProductBadgesForProduct(EntityCollection $originalCollection, array $productStreamIds): EntityCollection
  180.     {
  181.         return $originalCollection->filter(
  182.             function (ProductBadgesEntity $productBadge) use ($productStreamIds) {
  183.                 if ($productBadge->getDisplayCondition() !== self::PRODUCT_BADGE_DISPLAY_CONDITION_RULES_AND_DYNAMIC_PRODUCT_GROUPS) return true;
  184.                 if (empty($productBadge->getProductStreams()) || $productBadge->getProductStreams()->count() === 0) return false;
  185.                 return count(array_intersect($productBadge->getProductStreams()->getIds(), $productStreamIds)) > 0;
  186.             }
  187.         );
  188.     }
  189. }