<?php
namespace LoyxxSW6SeoFaqManager\Subscribers;
use LoyxxSW6SeoFaqManager\Core\Content\Cms\Struct\CategorySeoFaqStruct;
use LoyxxSW6SeoFaqManager\Core\Content\FaqCategory\FaqCategoryCollection;
use LoyxxSW6SeoFaqManager\Core\Content\FaqCategory\FaqCategoryEntity;
use LoyxxSW6SeoFaqManager\Core\Content\FaqCategory\Item\FaqCategoryItemEntity;
use LoyxxSW6SeoFaqManager\Core\Content\FaqProduct\FaqProductCollection;
use LoyxxSW6SeoFaqManager\Core\Content\FaqProduct\FaqProductEntity;
use LoyxxSW6SeoFaqManager\Core\Content\FaqProduct\Item\FaqProductItemEntity;
use LoyxxSW6SeoFaqManager\Core\Content\FaqSet\FaqSetCollection;
use LoyxxSW6SeoFaqManager\Core\Content\FaqSet\FaqSetEntity;
use LoyxxSW6SeoFaqManager\Core\Content\FaqSet\FaqSetItem\FaqSetItemEntity;
use LoyxxSW6SeoFaqManager\Core\Content\Struct\RichSnippetStruct;
use Shopware\Core\Content\Cms\Aggregate\CmsSection\CmsSectionEntity;
use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotCollection;
use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Development\Kernel;
use Shopware\Storefront\Event\StorefrontRenderEvent;
use Shopware\Storefront\Page\Navigation\NavigationPage;
use Shopware\Storefront\Page\Product\ProductPage;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\KernelEvent;
class StorefrontPageLoadedEvent implements EventSubscriberInterface
{
/**
* @var SystemConfigService
*/
private $configService;
public function __construct(SystemConfigService $configService)
{
$this->configService = $configService;
}
public static function getSubscribedEvents(): array
{
return [
StorefrontRenderEvent::class => 'onStorefrontRender'
];
}
public function onStorefrontRender(StorefrontRenderEvent $event)
{
if ($this->configService->get('LoyxxSW6SeoFaqManager.config.useJsonLd')) {
/** @var NavigationPage|ProductPage|null $page */
$page = $event->getParameters()['page'] ?? NULL;
if (!is_null($page) && ($page instanceof NavigationPage || $page instanceof ProductPage)) {
$faqs = $page instanceof NavigationPage ? $this->_getFaqsFromNavigationPage($page) : $this->_getFaqsFromDetailPage($page);
if ($faqs) {
$event->getSalesChannelContext()->setExtensions(["faqJsonLd" => new RichSnippetStruct($this->_prepareJsonLdSnippet($faqs))]);
}
}
}
}
private function _getFaqsFromNavigationPage(NavigationPage $page): array
{
$sections = $page->getCmsPage()->getSections();
$faqs = [];
/** @var CmsSectionEntity $section */
foreach ($sections as $section) {
if ($section->getBlocks()->count()) {
/** @var CmsSlotCollection $categorySeoFaq */
$categorySeoFaq = $section->getBlocks()->getSlots()->filter(function (CmsSlotEntity $slot) {
return $slot && $slot->getSlot() === 'categorySeoFaq';
});
if ($categorySeoFaq->count()) {
$slotData = $categorySeoFaq->getSlot('categorySeoFaq')->getData();
if ($slotData instanceof CategorySeoFaqStruct) {
/** @var FaqCategoryCollection $faq */
$faq = $slotData->getCategory()->getExtension('faq');
if ($faq->count()) {
/** @var FaqCategoryEntity $item */
foreach ($faq as $item) {
$faqs = array_merge($faqs, $item->getItems()->getElements());
}
}
/** @var FaqSetCollection $faqSets */
$faqSets = $slotData->getCategory()->getExtension('faqSets');
if ($faqSets->count()) {
/** @var FaqSetEntity $item */
foreach ($faqSets as $item) {
$faqs = array_merge($faqs, $item->getItems()->getElements());
}
}
}
}
}
}
return $faqs;
}
private function _getFaqsFromDetailPage(ProductPage $page): array
{
$faqs = [];
/** @var FaqProductCollection $faq */
$faq = $page->getProduct()->getExtension('faq');
if ($faq->count()) {
/** @var FaqProductEntity $item */
foreach ($faq as $item) {
$faqs = array_merge($faqs, $item->getItems()->getElements());
}
}
/** @var FaqSetCollection $faqSets */
$faqSets = $page->getProduct()->getExtension('faqSets');
if ($faqSets->count()) {
/** @var FaqSetEntity $item */
foreach ($faqSets as $item) {
$faqs = array_merge($faqs, $item->getItems()->getElements());
}
}
return $faqs;
}
private function _prepareJsonLdSnippet(array $faqs) : array
{
$snippet = [
"@context" => "https://schema.org",
"@type" => "FAQPage",
"mainEntity" => []
];
/** @var FaqCategoryItemEntity|FaqProductItemEntity|FaqSetItemEntity $faq */
foreach ($faqs as $faq) {
$snippet['mainEntity'][] = [
"@type" => "Question",
"name" => $faq->getTranslation('question'),
"acceptedAnswer" => [
"@type" => "Answer",
"text" => $faq->getTranslation('answer')
]
];
}
return $snippet;
}
}