custom/plugins/LoyxxRichBreadcrumb/src/Subscriber/ProductPageLoadedEvent.php line 153

Open in your IDE?
  1. <?php
  2. namespace LoyxxRichBreadcrumb\Subscriber;
  3. use Doctrine\DBAL\Connection;
  4. use LoyxxRichBreadcrumb\Struct\Breadcrumb;
  5. use LoyxxRichBreadcrumb\Struct\Data;
  6. use LoyxxRichBreadcrumb\Traits\Microdata;
  7. use Shopware\Core\Content\Seo\SeoUrl\SeoUrlEntity;
  8. use Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface;
  9. use Shopware\Core\Framework\Adapter\Cache\CacheClearer;
  10. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  15. use Shopware\Core\Framework\Struct\ArrayStruct;
  16. use Shopware\Core\System\SystemConfig\SystemConfigService;
  17. use Shopware\Storefront\Framework\Routing\RequestTransformer;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Component\HttpKernel\KernelEvents;
  20. /**
  21.  * Class ProductPageLoadedEvent
  22.  * @package LoyxxRichBreadcrumb\Subscriber
  23.  */
  24. class ProductPageLoadedEvent implements EventSubscriberInterface
  25. {
  26.     use Microdata;
  27.     public const SESSION_SEO_CATEGORY 'seoCategory';
  28.     public const SESSION_SEO_CATEGORY_ID 'seoCategoryId';
  29.     /**
  30.      * @var SeoUrlPlaceholderHandlerInterface
  31.      */
  32.     private $seoUrlPlaceholderHandler;
  33.     /**
  34.      * @var SystemConfigService
  35.      */
  36.     private $systemConfigService;
  37.     /**
  38.      * @var EntityRepositoryInterface
  39.      */
  40.     private $seoUrlRepository;
  41.     /**
  42.      * @var Connection
  43.      */
  44.     private $connection;
  45.     /**
  46.      * @var EntityRepositoryInterface
  47.      */
  48.     private  $categoryRepository;
  49.     /**
  50.      * @var CacheClearer
  51.      */
  52.     private  $cacheClearer;
  53.     /**
  54.      * ProductPageLoadedEvent constructor.
  55.      * @param SeoUrlPlaceholderHandlerInterface $seoUrlPlaceholderHandler
  56.      * @param SystemConfigService $systemConfigService
  57.      * @param EntityRepositoryInterface $seoUrlRepository
  58.      * @param Connection $connection
  59.      */
  60.     public function __construct(
  61.         SeoUrlPlaceholderHandlerInterface $seoUrlPlaceholderHandler,
  62.         SystemConfigService $systemConfigService,
  63.         EntityRepositoryInterface $seoUrlRepository,
  64.         EntityRepositoryInterface $categoryRepository,
  65.         Connection $connection,
  66.         CacheClearer $cacheClearer
  67.     )
  68.     {
  69.         $this->seoUrlPlaceholderHandler $seoUrlPlaceholderHandler;
  70.         $this->systemConfigService $systemConfigService;
  71.         $this->seoUrlRepository $seoUrlRepository;
  72.         $this->connection $connection;
  73.         $this->categoryRepository $categoryRepository;
  74.         $this->cacheClearer $cacheClearer;
  75.     }
  76.     /**
  77.      * @return array|string[]
  78.      */
  79.     public static function getSubscribedEvents(): array
  80.     {
  81.         return [
  82.             \Shopware\Storefront\Page\Product\ProductPageLoadedEvent::class => 'onProductPageLoadedEvent',
  83.             KernelEvents::CONTROLLER => 'onControllerEvent'
  84.         ];
  85.     }
  86.     /**
  87.      * @param \Shopware\Storefront\Page\Product\ProductPageLoadedEvent $event
  88.      */
  89.     public function onProductPageLoadedEvent(\Shopware\Storefront\Page\Product\ProductPageLoadedEvent $event)
  90.     {
  91.         // create microdata for breadcrumb
  92.         $host $event->getRequest()->attributes->get(RequestTransformer::SALES_CHANNEL_ABSOLUTE_BASE_URL) .
  93.             $event->getRequest()->attributes->get(RequestTransformer::SALES_CHANNEL_BASE_URL);
  94.         $uri $event->getRequest()->getRequestUri();
  95.         if ( $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME '.config.modifyProductDetailBreadcrumb')){
  96.             $this->checkAndUpdateSeoBreadcrumbNavigation($event$host);
  97.         }
  98.         $navigationTree $event->getPage()->getHeader()->getNavigation()->getTree();
  99.         $product $event->getPage()->getProduct();
  100.         $productBreadcrumb = [];
  101.         $this->createBreadcrumbTree($navigationTree$product$productBreadcrumb);
  102.         /**
  103.          * Hide breadcrumb on home page
  104.          *
  105.          * $breadcrumbIsVisible = $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME.'.config.isInvisible');
  106.          * if ($this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME . '.config.isHiddenOnHomePage') && $event->getRequest()->attributes->get('_route') === 'frontend.home.page'){
  107.          * $breadcrumbIsVisible = false;
  108.          * }
  109.          *  */
  110.         $breadcrumbStruct = new Breadcrumb(
  111.             $this->createMicrodata(
  112.                 $event,
  113.                 $productBreadcrumb,
  114.                 $host,
  115.                 $event->getSalesChannelContext(),
  116.                 $uri
  117.             ),
  118.             $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME '.config.isInvisible'),
  119.             $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME '.config.showProductTitle'),
  120.             $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME '.config.separator'),
  121.             $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME '.config.isVisibleHomeLink'),
  122.             $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME '.config.isHiddenOnHomePage'),
  123.             $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME '.config.homeLabel'),
  124.             $host,
  125.             $uri
  126.         );
  127.         $event->getPage()->addExtension('breadcrumb'$breadcrumbStruct);
  128.         $event->getPage()->getProduct()->addExtension('breadcrumb'$breadcrumbStruct);
  129.         $event->getSalesChannelContext()->addExtensions([
  130.             'breadcrumb' => $breadcrumbStruct,
  131.             'breadcrumbProduct' => new ArrayStruct(['product' => $event->getPage()->getProduct()])
  132.         ]);
  133.     }
  134.     private function checkAndUpdateSeoBreadcrumbNavigation(\Shopware\Storefront\Page\Product\ProductPageLoadedEvent $eventstring $host)
  135.     {
  136.         $referer $event->getRequest()->server->get('HTTP_REFERER');
  137.         $session $event->getRequest()->getSession();
  138.         $sessionCategoryId $session->get(self::SESSION_SEO_CATEGORY_ID);
  139.         if ($sessionCategoryId && in_array($sessionCategoryId$event->getPage()->getProduct()->getCategoryTree())){
  140.             $category $this->categoryRepository->search(new Criteria([$sessionCategoryId]), $event->getContext())->first();
  141.             if ($category){
  142.                 $event->getRequest()->getSession()->set(static::SESSION_SEO_CATEGORY$category);
  143.             }
  144.         }else{
  145.             $session->remove(self::SESSION_SEO_CATEGORY_ID);
  146.             $session->remove(self::SESSION_SEO_CATEGORY);
  147.         }
  148.         if (($referer && $referer !== $host) && is_null($sessionCategoryId)) {
  149.             $referer str_replace($host""$referer);
  150.             // remove ? and # from fragment from the URI
  151.             $referer ltrim(substr(substr($referer0strrpos($referer'?') ?: strlen($referer)), 0strrpos($referer'#') ?: strlen($referer)), "/");
  152.             if ($referer){
  153.                 // get the navigation id if it present in the seoUrl page
  154.                 $criteria = new Criteria();
  155.                 $criteria->setLimit(1);
  156.                 $criteria->setTotalCountMode(1);
  157.                 $criteria->addFilter(new MultiFilter(MultiFilter::CONNECTION_OR, [
  158.                     new EqualsFilter('seoPathInfo'"$referer"),
  159.                     new EqualsFilter('seoPathInfo'"{$referer}/")
  160.                 ]));
  161.                 /** @var SeoUrlEntity $seoUrl */
  162.                 $seoUrl $this->seoUrlRepository->search($criteria$event->getContext())->first();
  163.                 if(is_null($seoUrl)){
  164.                     // the received $lastPart was a uuid
  165.                     $criteria = new Criteria();
  166.                     $criteria->setLimit(1);
  167.                     $criteria->setTotalCountMode(1);
  168.                     $criteria->addFilter(new ContainsFilter('pathInfo'$referer));
  169.                     $seoUrl $this->seoUrlRepository->search($criteria$event->getContext())->first();
  170.                 }
  171.                 if ($seoUrl){
  172.                     $categoryId $seoUrl->getForeignKey();
  173.                     // check existence of the category
  174.                     $rows $this->connection->executeQuery("SELECT count(id) as row_count FROM category WHERE hex(id) = ?", [$categoryId]);
  175.                     $row $rows->fetch(\PDO::FETCH_ASSOC);
  176.                     if (isset($row['row_count']) && $row['row_count']){
  177.                         $category $this->categoryRepository->search(new Criteria([$categoryId]), $event->getContext())->first();
  178.                         if ($category){
  179.                             $event->getRequest()->getSession()->set(static::SESSION_SEO_CATEGORY$category);
  180.                         }
  181.                     }
  182.                 }
  183.             }
  184.         }
  185.     }
  186.     /**
  187.      * @param array $navigationTree
  188.      * @param \Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity $product
  189.      * @param $productBreadcrumb
  190.      */
  191.     private function createBreadcrumbTree(array $navigationTree\Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity $product, &$productBreadcrumb)
  192.     {
  193.         if ($navigationTree) {
  194.             $productCategoryTree $product->getCategoryTree();
  195.             if ($productCategoryTree){
  196.                 $lastProductCategoryTree end($productCategoryTree);
  197.                 foreach ($navigationTree as $item) {
  198.                     if ($item->getCategory()->getId() == $lastProductCategoryTree) {
  199.                         $breadcrumb $item->getCategory()->getPlainBreadcrumb($item->getCategory()->getId());
  200.                         $breadcrumb array_slice($breadcrumb1);
  201.                         if ($breadcrumb) {
  202.                             foreach ($breadcrumb as $key => $value) {
  203.                                 $productBreadcrumb[$key] = $value;
  204.                             }
  205.                         }
  206.                     } else if ($item->getChildren()) {
  207.                         $this->createBreadcrumbTree($item->getChildren(), $product$productBreadcrumb);
  208.                     }
  209.                 }
  210.             }
  211.         }
  212.     }
  213.     public function onControllerEvent($event) {
  214.         if ( $this->systemConfigService->get(PageLoadedEventSubscriber::BUNDLE_NAME '.config.modifyProductDetailBreadcrumb')){
  215.             $this->cacheClearer->clear();
  216.         }
  217.     }
  218. }