custom/plugins/DreiscSeoPro/src/Subscriber/Installment/RichSnippet/RichSnippetSubscriber.php line 98

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace DreiscSeoPro\Subscriber\Installment\RichSnippet;
  3. use DreiscSeoPro\Core\Breadcrumb\PlainBreadcrumbCalculator;
  4. use DreiscSeoPro\Core\CustomSetting\CustomSettingLoader;
  5. use DreiscSeoPro\Core\RichSnippet\Breadcrumb\BreadcrumbRichSnippetLdBuilderInterface;
  6. use DreiscSeoPro\Core\RichSnippet\Breadcrumb\BreadcrumbRichSnippetLdBuilderStruct;
  7. use DreiscSeoPro\Core\RichSnippet\LocalBusiness\LocalBusinessRichSnippetLdBuilderInterface;
  8. use DreiscSeoPro\Core\RichSnippet\LocalBusiness\LocalBusinessRichSnippetLdBuilderStruct;
  9. use DreiscSeoPro\Core\RichSnippet\Logo\LogoRichSnippetLdBuilderInterface;
  10. use DreiscSeoPro\Core\RichSnippet\Logo\LogoRichSnippetLdBuilderStruct;
  11. use DreiscSeoPro\Core\RichSnippet\Product\ProductRichSnippetLdBuilderInterface;
  12. use DreiscSeoPro\Core\RichSnippet\Product\ProductRichSnippetLdBuilderStruct;
  13. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  15. use Shopware\Core\SalesChannelRequest;
  16. use Shopware\Storefront\Page\Navigation\NavigationPageLoadedEvent;
  17. use Shopware\Storefront\Page\Page;
  18. use Shopware\Storefront\Page\PageLoadedEvent;
  19. use Shopware\Storefront\Page\Product\ProductPage;
  20. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  21. use Shopware\Storefront\Page\Product\Review\ProductReviewLoader;
  22. use Shopware\Storefront\Page\Product\Review\ReviewLoaderResult;
  23. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  24. class RichSnippetSubscriber implements EventSubscriberInterface
  25. {
  26.     public const DREISC_SEO_INSTALLMENT_RICH_SNIPPET_DATA 'dreiscSeoInstallmentRichSnippetData';
  27.     /**
  28.      * @var ProductRichSnippetLdBuilderInterface
  29.      */
  30.     private $productRichSnippetLdBuilder;
  31.     /**
  32.      * @var BreadcrumbRichSnippetLdBuilderInterface
  33.      */
  34.     private $breadcrumbRichSnippetLdBuilder;
  35.     /**
  36.      * @var LogoRichSnippetLdBuilderInterface
  37.      */
  38.     private $logoRichSnippetLdBuilder;
  39.     /**
  40.      * @var PlainBreadcrumbCalculator
  41.      */
  42.     private $plainBreadcrumbCalculator;
  43.     /**
  44.      * @var CustomSettingLoader
  45.      */
  46.     private $customSettingLoader;
  47.     /**
  48.      * @var LocalBusinessRichSnippetLdBuilderInterface
  49.      */
  50.     protected $localBusinessRichSnippetLdBuilder;
  51.     /**
  52.      * @var ProductReviewLoader
  53.      */
  54.     protected $productReviewLoader;
  55.     /**
  56.      * @param ProductRichSnippetLdBuilderInterface $productRichSnippetLdBuilder
  57.      * @param BreadcrumbRichSnippetLdBuilderInterface $breadcrumbRichSnippetLdBuilder
  58.      * @param LogoRichSnippetLdBuilderInterface $logoRichSnippetLdBuilder
  59.      * @param PlainBreadcrumbCalculator $plainBreadcrumbCalculator
  60.      * @param CustomSettingLoader $customSettingLoader
  61.      * @param LocalBusinessRichSnippetLdBuilderInterface $localBusinessRichSnippetLdBuilder
  62.      * @param ProductReviewLoader $productReviewLoader
  63.      */
  64.     public function __construct(ProductRichSnippetLdBuilderInterface $productRichSnippetLdBuilderBreadcrumbRichSnippetLdBuilderInterface $breadcrumbRichSnippetLdBuilderLogoRichSnippetLdBuilderInterface $logoRichSnippetLdBuilderPlainBreadcrumbCalculator $plainBreadcrumbCalculatorCustomSettingLoader $customSettingLoaderLocalBusinessRichSnippetLdBuilderInterface $localBusinessRichSnippetLdBuilderProductReviewLoader $productReviewLoader)
  65.     {
  66.         $this->productRichSnippetLdBuilder $productRichSnippetLdBuilder;
  67.         $this->breadcrumbRichSnippetLdBuilder $breadcrumbRichSnippetLdBuilder;
  68.         $this->logoRichSnippetLdBuilder $logoRichSnippetLdBuilder;
  69.         $this->plainBreadcrumbCalculator $plainBreadcrumbCalculator;
  70.         $this->customSettingLoader $customSettingLoader;
  71.         $this->localBusinessRichSnippetLdBuilder $localBusinessRichSnippetLdBuilder;
  72.         $this->productReviewLoader $productReviewLoader;
  73.     }
  74.     public static function getSubscribedEvents()
  75.     {
  76.         return [
  77.             ProductPageLoadedEvent::class => 'addInstallment',
  78.             NavigationPageLoadedEvent::class => 'addInstallment',
  79.         ];
  80.     }
  81.     /**
  82.      * @param PageLoadedEvent $event
  83.      * @throws InconsistentCriteriaIdsException
  84.      */
  85.     public function addInstallment(PageLoadedEvent $event)
  86.     {
  87.         $ld = [];
  88.         /** @var Page|ProductPage $page */
  89.         $page $event->getPage();
  90.         /** @var SalesChannelProductEntity $productEntity */
  91.         $productEntity null;
  92.         $salesChannelEntity $event->getSalesChannelContext()->getSalesChannel();
  93.         $salesChannelDomainId $event->getRequest()->attributes->get(SalesChannelRequest::ATTRIBUTE_DOMAIN_ID);
  94.         $plainBreadcrumb null;
  95.         /** Load the custom settings */
  96.         $customSettings $this->customSettingLoader->load($salesChannelEntity->getId(), true);
  97.         /** Abort, if json ld support was not activated */
  98.         if (false === $customSettings->getRichSnippets()->getGeneral()->isActive()) {
  99.             return;
  100.         }
  101.         /** Try to fetch the navigation tree and the active category */
  102.         if (null !== $page->getHeader() && null !== $page->getHeader()->getNavigation()) {
  103.             $navigationTree $page->getHeader()->getNavigation()->getTree();
  104.             $category $page->getHeader()->getNavigation()->getActive();
  105.         } else {
  106.             $navigationTree null;
  107.             $category null;
  108.         }
  109.         /** Product page */
  110.         if ($page instanceof ProductPage) {
  111.             /** Calculate product ld data */
  112.             $productEntity $page->getProduct();
  113.             $currencyEntity $event->getSalesChannelContext()->getCurrency();
  114.             /** @todo: Shopware Bug > getReviews is null */
  115. //            $reviewLoaderResult = $event->getPage()->getReviews();
  116.             $reviewLoaderResult $this->productReviewLoader->load(
  117.                 $event->getRequest(),
  118.                 $event->getSalesChannelContext()
  119.             );
  120.             /** Build the product ld data */
  121.             $ld[] = $this->productRichSnippetLdBuilder->build(
  122.                 new ProductRichSnippetLdBuilderStruct(
  123.                     $customSettings,
  124.                     $productEntity,
  125.                     $salesChannelEntity,
  126.                     $currencyEntity,
  127.                     $reviewLoaderResult,
  128.                     $salesChannelDomainId
  129.                 )
  130.             );
  131.             /** Calculate breadcrumb ld data */
  132. //            if (null !== $navigationTree) {
  133. //                $plainBreadcrumb = $this->plainBreadcrumbCalculator->getProductBreadcrumb($navigationTree, $productEntity);
  134. //            }
  135.         } else {
  136.             /** Calculate breadcrumb ld data */
  137. //            if (null !== $navigationTree && null !== $category) {
  138. //                $plainBreadcrumb = $this->plainBreadcrumbCalculator->getCategoryBreadcrumb($category, $salesChannelEntity);
  139. //            }
  140.         }
  141.         if(null !== $category && null !== $salesChannelEntity) {
  142.             $plainBreadcrumb $this->plainBreadcrumbCalculator->getCategoryBreadcrumb($category$salesChannelEntity);
  143.         }
  144.         /** Build the breadcrumb ld, if data available */
  145.         if (null !== $plainBreadcrumb) {
  146.             $ld[] = $this->breadcrumbRichSnippetLdBuilder->build(
  147.                 new BreadcrumbRichSnippetLdBuilderStruct(
  148.                     $customSettings,
  149.                     $plainBreadcrumb,
  150.                     $salesChannelEntity,
  151.                     $salesChannelDomainId,
  152.                     $productEntity
  153.                 )
  154.             );
  155.         }
  156.         /** Build the logo ld data */
  157.         $ld[] = $this->logoRichSnippetLdBuilder->build(
  158.             new LogoRichSnippetLdBuilderStruct(
  159.                 $customSettings,
  160.                 $salesChannelEntity
  161.             )
  162.         );
  163.         /** Build the local business ld data */
  164.         $ld[] = $this->localBusinessRichSnippetLdBuilder->build(
  165.             new LocalBusinessRichSnippetLdBuilderStruct(
  166.                 $customSettings,
  167.                 $salesChannelEntity
  168.             )
  169.         );
  170.         /** Move organization url to local business image */
  171.         $ld $this->copyOrganizationUrlToLocalBusinessImage($ld);
  172.         if(!empty($ld)) {
  173.             /** Wrap the ld data in a struct */
  174.             $richSnippetDataStruct = new RichSnippetDataStruct($ld);
  175.             if(!empty($richSnippetDataStruct->getLdJson())) {
  176.                 $page->addExtension(
  177.                     self::DREISC_SEO_INSTALLMENT_RICH_SNIPPET_DATA,
  178.                     $richSnippetDataStruct
  179.                 );
  180.             }
  181.         }
  182.     }
  183.     private function copyOrganizationUrlToLocalBusinessImage(array $ld)
  184.     {
  185.         $organizationUrl null;
  186.         foreach($ld as $ldItem) {
  187.             if(empty($ldItem)) {
  188.                 continue;
  189.             }
  190.             if ('Organization' === $ldItem['@type'] && !empty($ldItem['url'])) {
  191.                 $organizationUrl $ldItem['url'];
  192.             }
  193.         }
  194.         if (null !== $organizationUrl) {
  195.             foreach($ld as &$ldItem) {
  196.                 if(empty($ldItem)) {
  197.                     continue;
  198.                 }
  199.                 if ('LocalBusiness' === $ldItem['@type']) {
  200.                     $ldItem['image'] = $organizationUrl;
  201.                 }
  202.             }
  203.         }
  204.         return $ld;
  205.     }
  206. }