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.         /** Build the breadcrumb ld, if data available */
  142.         if (null !== $plainBreadcrumb) {
  143.             $ld[] = $this->breadcrumbRichSnippetLdBuilder->build(
  144.                 new BreadcrumbRichSnippetLdBuilderStruct(
  145.                     $customSettings,
  146.                     $plainBreadcrumb,
  147.                     $salesChannelEntity,
  148.                     $salesChannelDomainId,
  149.                     $productEntity
  150.                 )
  151.             );
  152.         }
  153.         /** Build the logo ld data */
  154.         $ld[] = $this->logoRichSnippetLdBuilder->build(
  155.             new LogoRichSnippetLdBuilderStruct(
  156.                 $customSettings,
  157.                 $salesChannelEntity
  158.             )
  159.         );
  160.         /** Build the local business ld data */
  161.         $ld[] = $this->localBusinessRichSnippetLdBuilder->build(
  162.             new LocalBusinessRichSnippetLdBuilderStruct(
  163.                 $customSettings,
  164.                 $salesChannelEntity
  165.             )
  166.         );
  167.         /** Move organization url to local business image */
  168.         $ld $this->copyOrganizationUrlToLocalBusinessImage($ld);
  169.         if(!empty($ld)) {
  170.             /** Wrap the ld data in a struct */
  171.             $richSnippetDataStruct = new RichSnippetDataStruct($ld);
  172.             if(!empty($richSnippetDataStruct->getLdJson())) {
  173.                 $page->addExtension(
  174.                     self::DREISC_SEO_INSTALLMENT_RICH_SNIPPET_DATA,
  175.                     $richSnippetDataStruct
  176.                 );
  177.             }
  178.         }
  179.     }
  180.     private function copyOrganizationUrlToLocalBusinessImage(array $ld)
  181.     {
  182.         $organizationUrl null;
  183.         foreach($ld as $ldItem) {
  184.             if(empty($ldItem)) {
  185.                 continue;
  186.             }
  187.             if ('Organization' === $ldItem['@type'] && !empty($ldItem['url'])) {
  188.                 $organizationUrl $ldItem['url'];
  189.             }
  190.         }
  191.         if (null !== $organizationUrl) {
  192.             foreach($ld as &$ldItem) {
  193.                 if(empty($ldItem)) {
  194.                     continue;
  195.                 }
  196.                 if ('LocalBusiness' === $ldItem['@type']) {
  197.                     $ldItem['image'] = $organizationUrl;
  198.                 }
  199.             }
  200.         }
  201.         return $ld;
  202.     }
  203. }