vendor/store.shopware.com/mindsshoppingcartgoals/src/Subscriber/Frontend.php line 189

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace MindsShoppingCartGoals\Subscriber;
  3. use MindsShoppingCartGoals\Main\SCGHelper;
  4. use MindsShoppingCartGoals\Main\structs\SCGData;
  5. use MindsShoppingCartGoals\Main\structs\SCGBoolean;
  6. use MindsShoppingCartGoals\Main\structs\SCGItem;
  7. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  8. use Shopware\Core\Framework\Adapter\Translation\Translator;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  10. use Shopware\Core\System\SystemConfig\SystemConfigService;
  11. use Shopware\Storefront\Theme\Event\ThemeCompilerEnrichScssVariablesEvent;
  12. use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
  15. use Shopware\Storefront\Page\Checkout\Register\CheckoutRegisterPageLoadedEvent;
  16. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  17. use Shopware\Storefront\Page\Product\ProductPageLoader;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  20. use Shopware\Core\DevOps\Environment\EnvironmentHelper;
  21. use Shopware\Core\Framework\Struct\ArrayEntity;
  22. /**
  23.  * Class Frontend
  24.  *
  25.  * @phpstan-ignore-next-line */
  26. class Frontend implements EventSubscriberInterface {
  27.     protected SystemConfigService $systemConfig;
  28.     private EntityRepository $productRepository;
  29.     private EntityRepository $freeProductRepository;
  30.     private Translator $translator;
  31.     private CartService $cartService;
  32.     // add the `SystemConfigService` to your constructor
  33.     public function __construct(SystemConfigService $systemConfigEntityRepository $productRepositoryEntityRepository $freeProductRepositoryTranslator $translatorCartService $cartService) {
  34.         $this->systemConfig $systemConfig;
  35.         $this->productRepository $productRepository;
  36.         $this->freeProductRepository $freeProductRepository;
  37.         $this->translator $translator;
  38.         $this->cartService $cartService;
  39.     }
  40.     public static function getSubscribedEvents(): array {
  41.         return [
  42.             ThemeCompilerEnrichScssVariablesEvent::class => 'onAddVariables',
  43.             CheckoutCartPageLoadedEvent::class => 'onCartLoadedEvent',
  44.             OffcanvasCartPageLoadedEvent::class => 'onOffcanvasCartLoadedEvent',
  45.             CheckoutRegisterPageLoadedEvent::class => 'onCheckoutRegisterPageLoadedEvent',
  46.             ProductPageLoadedEvent::class => 'onProductPageLoadedEvent'
  47.         ];
  48.     }
  49.     public function onAddVariables(ThemeCompilerEnrichScssVariablesEvent $event): void {
  50.         $databaseUrl EnvironmentHelper::getVariable('DATABASE_URL'getenv('DATABASE_URL'));
  51.         if (!$databaseUrl || $databaseUrl === 'mysql://_placeholder.test') {
  52.             // deployment server without database
  53.             return;
  54.         }
  55.         $configSCGBaseColor $this->systemConfig->get('MindsShoppingCartGoals.config.scgBaseColor'$event->getSalesChannelId());
  56.         $configSCGBadgeColor $this->systemConfig->get('MindsShoppingCartGoals.config.scgBadgeColor'$event->getSalesChannelId());
  57.         $configSCGProgressColor $this->systemConfig->get('MindsShoppingCartGoals.config.scgProgressColor'$event->getSalesChannelId());
  58.         $configSCGProgressCircleAsRectangle $this->systemConfig->get('MindsShoppingCartGoals.config.scgRectangleProgressPoints'$event->getSalesChannelId());
  59.         $configSCGBorderRadius $this->systemConfig->get('MindsShoppingCartGoals.config.scgBaseBorderRadius'$event->getSalesChannelId());
  60.         if ($configSCGBaseColor) {
  61.             $event->addVariable('scg-base-color'$configSCGBaseColor);
  62.         }
  63.         if ($configSCGProgressColor) {
  64.             $event->addVariable('scg-progress-color'$configSCGProgressColor);
  65.         }
  66.         if ($configSCGProgressCircleAsRectangle) {
  67.             $event->addVariable('scg-progress-circle-as-rectangle'$configSCGProgressCircleAsRectangle '1' '0');
  68.         }
  69.         if ($configSCGBadgeColor) {
  70.             $event->addVariable('scg-badge-color'$configSCGBadgeColor);
  71.         }
  72.         if ($configSCGBorderRadius) {
  73.             $event->addVariable('scg-border-radius'strval($configSCGBorderRadius) . '%');
  74.         }
  75.     }
  76.     private function loadSCGData(&$event) {
  77.         $scgData = new SCGData();
  78.         $positionPrice SCGHelper::getPositionPrice($event->getPage()->getCart(), $this->systemConfig$event->getContext());
  79.         $addOnlyHighestFreeProduct $this->systemConfig->get('MindsShoppingCartGoals.config.scgAddOnlyHighestFreeProduct'$event->getContext()->getSource()->getSalesChannelId());
  80.         $startsAtZero $this->systemConfig->get('MindsShoppingCartGoals.config.scgStartsAtZero'$event->getContext()->getSource()->getSalesChannelId());
  81.         $items SCGHelper::getSCGItems($this->systemConfig$this->productRepository$this->translator$event->getContext(), $positionPrice$this->freeProductRepository);
  82.         // Calculate the Difference to the next possible position when exists
  83.         $diffToNextPosition 0;
  84.         $nextPositionName "";
  85.         foreach ($items as $itemKey=>&$item) {
  86.             if (!empty($item->getRuleId())) {
  87.                 if (!in_array($item->getRuleId(), $event->getSalesChannelContext()->getRuleIds())) {
  88.                     unset($items[$itemKey]);
  89.                 }
  90.             }
  91.         }
  92.         $index 0;
  93.         foreach ($items as $itemKey=>&$item) {
  94.             if (!$item->isCartValueReached()) {
  95.                 $diffToNextPosition $item->getCartValue() - $positionPrice;
  96.                 $nextPositionName $item->getName();
  97.                 break;
  98.             } else {
  99.                 $index++;
  100.             }
  101.         }
  102.         if ($event->getPage()->getCart()) {
  103.             foreach ($items as $itemKey=>&$item) {
  104.                 foreach ($event->getPage()->getCart()->getLineItems() as $lineItem) {
  105.                     if (!empty($lineItem->getExtension('scgItem'))) {
  106.                         $item->updateIsInCart($lineItem->getReferencedId());
  107.                     }
  108.                 }
  109.             }
  110.         }
  111.         $items array_filter($items, function($var) {
  112.             if (!$var->isAddToShoppingCart()) return true;
  113.             if ($var->hasVariantItems()) {
  114.                 if ($var->hasVariantItemsWithStock()) {
  115.                     return true;
  116.                 } else {
  117.                     return false;
  118.                 }
  119.             } else {
  120.                 if (!$var->getCurrentStock() >= $var->getCount()) {
  121.                     return false;
  122.                 }
  123.             }
  124.             if ($var->isRemoved()) return false;
  125.             return true;
  126.         });
  127.         $freeItems array_filter($items, function($var) {
  128.             return $var->isCartValueReached();
  129.         });
  130.         $scgData->setFreeItems($addOnlyHighestFreeProduct ? [ end($freeItems) ] : $freeItems);
  131.         $displayAddFreeItems false;
  132.         foreach ($scgData->getFreeItems() as $itemKey=>&$item) {
  133.             if (!empty($item)) {
  134.                 if ($item->isActive() and $item->hasVariantItems() and $item->isCartValueReached() and $item->isAddToShoppingCart() and $item->hasVariantItemsWithStock()) {
  135.                     $displayAddFreeItems true;
  136.                 }
  137.             }
  138.         }
  139.         $scgData->setItems($items);
  140.         $scgData->setDisplayAddFreeProducts($displayAddFreeItems);
  141.         $scgData->setDiffToNextPosition($diffToNextPosition);
  142.         $scgData->setNextPositionName($nextPositionName);
  143.         $scgData->setItemCount(count($items));
  144.         $scgData->setAddOnlyHighestFreeProduct($addOnlyHighestFreeProduct);
  145.         $scgData->setStartsAtZero($startsAtZero);
  146.         $scgData->setHighestProductIndex($index);
  147.         $event->getPage()->addExtension('scg'$scgData);
  148.     }
  149.     public function onCartLoadedEvent(CheckoutCartPageLoadedEvent $event) {
  150.         $this->loadSCGData($event);
  151.     }
  152.     public function onOffcanvasCartLoadedEvent(OffcanvasCartPageLoadedEvent $event) {
  153.         $this->loadSCGData($event);
  154.     }
  155.     public function onCheckoutRegisterPageLoadedEvent(CheckoutRegisterPageLoadedEvent $event) {
  156.         $this->loadSCGData($event);
  157.         $scgShowProgressOnRegisterSite $this->systemConfig->get('MindsShoppingCartGoals.config.scgShowProgressOnRegisterSite'$event->getSalesChannelContext()->getSalesChannelId());
  158.         if (empty($scgShowProgressOnRegisterSite)) {
  159.             $scgShowProgressOnRegisterSite false;
  160.         }
  161.         $event->getPage()->addExtension('scgShow', new SCGBoolean($scgShowProgressOnRegisterSite));
  162.     }
  163.     public function onProductPageLoadedEvent(ProductPageLoadedEvent $event) {
  164.         $cri = new Criteria();
  165.         $cri->addFilter(new EqualsFilter('active'true));
  166.         $cri->addFilter(new EqualsFilter('preventSale'true));
  167.         $cri->addFilter(new EqualsFilter('productId'$event->getPage()->getProduct()->getId()));
  168.         if (!empty($this->freeProductRepository->search($cri$event->getContext())->first())) {
  169.             $event->getPage()->addExtension('m28_scg_prevent_sale', new SCGBoolean(true));
  170.         }
  171.         $showNextPositionNameOnProductPage $this->systemConfig->get('MindsShoppingCartGoals.config.scgShowNextPositionNameOnProductPage'$event->getSalesChannelContext()->getSalesChannelId());
  172.         if ($showNextPositionNameOnProductPage) {
  173.             $cart $this->cartService->getCart($event->getSalesChannelContext()->getToken(), $event->getSalesChannelContext());
  174.             $positionPrice SCGHelper::getPositionPrice($cart$this->systemConfig$event->getContext());
  175.             $items SCGHelper::getSCGItems($this->systemConfig$this->productRepository$this->translator$event->getContext(), $positionPrice$this->freeProductRepository);
  176.     
  177.             // Calculate the Difference to the next possible position when exists
  178.             $diffToNextPosition 0;
  179.             $nextPositionName "";
  180.     
  181.             foreach ($items as $itemKey=>&$item) {
  182.                 if (!empty($item->getRuleId())) {
  183.                     if (!in_array($item->getRuleId(), $event->getSalesChannelContext()->getRuleIds())) {
  184.                         unset($items[$itemKey]);
  185.                     }
  186.                 }
  187.             }
  188.     
  189.             $index 0;
  190.             foreach ($items as $itemKey=>&$item) {
  191.                 if (!$item->isCartValueReached()) {
  192.                     $diffToNextPosition $item->getCartValue() - $positionPrice;
  193.     
  194.                     $nextPositionName $item->getName();
  195.                     break;
  196.                 } else {
  197.                     $index++;
  198.                 }
  199.             }
  200.             $event->getPage()->addExtension('m28_scg_display_next_position', new ArrayEntity([ 'diffToNextPosition' => $diffToNextPosition'nextPositionName' => $nextPositionName ])); 
  201.         }
  202.     }
  203. }