<?php declare(strict_types=1);
namespace DISco\GA4\Subscriber;
use Exception;
use Psr\Log\LoggerInterface;
use Shopware\Core\Content\Cms\SalesChannel\Struct\CrossSellingStruct;
use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductBoxStruct;
use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductListingStruct;
use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductSliderStruct;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductSearchCriteriaEvent;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
use Shopware\Storefront\Page\Navigation\NavigationPageLoadedEvent;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Shopware\Storefront\Page\Search\SearchPageLoadedEvent;
use Shopware\Storefront\Page\Wishlist\WishlistPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Swag\EnterpriseSearch\Search\Page\SearchPageLoadedEvent as EnterpriseSearchPageLoadedEvent;
class FrontendSubscriber implements EventSubscriberInterface
{
private LoggerInterface $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public static function getSubscribedEvents(): array
{
return [
ProductListingCriteriaEvent::class => 'onProductListingCriteria',
ProductSearchCriteriaEvent::class => 'onProductSearchCriteriaEvent',
SearchPageLoadedEvent::class => 'onSearchPageLoadedEvent',
ProductPageLoadedEvent::class => 'onProductPageLoadedEvent',
NavigationPageLoadedEvent::class => 'onNavigationPageLoadedEvent',
EnterpriseSearchPageLoadedEvent::class => 'onEnterpriseSearchPageLoadedEvent',
WishlistPageLoadedEvent::class => 'onWishlistPageLoadedEvent'
];
}
public function onEnterpriseSearchPageLoadedEvent(EnterpriseSearchPageLoadedEvent $event): void
{
try {
$elements = $event->getPage()->getListing()->getElements();
if (empty($elements)) {
return;
}
$collection = array_filter($elements);
/* @phpstan-ignore-next-line */
$disGA4Extension = new EntityCollection($collection);
$event->getContext()->addExtension('disGA4ProductsExtension', $disGA4Extension);
} catch (Exception $e) {
$this->logger->error($e->getMessage(), ['trace' => $e->getTrace()]);
}
}
public function onProductSearchCriteriaEvent(ProductSearchCriteriaEvent $event): bool
{
$event->getCriteria()->addAssociation('categories');
$event->getCriteria()->addAssociation('seoCategory');
$event->getCriteria()->addAssociation('manufacturer');
return true;
}
public function onProductListingCriteria(ProductListingCriteriaEvent $event): bool
{
$event->getCriteria()->addAssociation('categories');
$event->getCriteria()->addAssociation('seoCategory');
$event->getCriteria()->addAssociation('manufacturer');
return true;
}
public function onWishlistPageLoadedEvent(WishlistPageLoadedEvent $event): bool
{
try {
$elements = $event->getPage()->getWishlist()->getProductListing()->getElements();
if (!empty($elements)) {
$collection = array_filter($elements);
$disGA4Extension = new EntityCollection($collection);
$event->getContext()->addExtension('disGA4ProductsExtension', $disGA4Extension);
}
} catch (Exception $e) {
$this->logger->error($e->getMessage(), ['trace' => $e->getTrace()]);
}
return true;
}
public function onSearchPageLoadedEvent(SearchPageLoadedEvent $event): bool
{
try {
$elements = $event->getPage()->getListing()->getElements();
if (!empty($elements)) {
$collection = array_filter($elements);
$disGA4Extension = new EntityCollection($collection);
$event->getContext()->addExtension('disGA4ProductsExtension', $disGA4Extension);
}
} catch (Exception $e) {
$this->logger->error($e->getMessage(), ['trace' => $e->getTrace()]);
}
return true;
}
public function onProductPageLoadedEvent(ProductPageLoadedEvent $event): bool
{
try {
$elements = [$event->getPage()->getProduct()];
$cmsList = ['product-box', 'product-slider', 'cross-selling'];
if ($event->getPage()->getProduct()->getCmsPage()) {
try {
$cmsElements = $event->getPage()->getCmsPage()->getSections()->getBlocks()->getSlots()->getElements();
foreach ($cmsElements as $key => $object) {
if (!in_array($object->getType(), $cmsList)) {
unset($cmsElements[$key]);
}
}
foreach ($cmsElements as $object) {
$data = $object->getData();
switch ($data) {
case $data instanceof CrossSellingStruct:
if ($data->getCrossSellings()) {
foreach ($data->getCrossSellings()->getElements() as $crossSelling) {
foreach ($crossSelling->getProducts() as $product) {
$elements[] = $product;
}
}
}
break;
case $data instanceof ProductBoxStruct:
if (null !== $data->getProduct()) {
$elements[] = $data->getProduct();
}
break;
case $data instanceof ProductSliderStruct :
foreach ($data->getProducts() as $product) {
$elements[] = $product;
}
break;
case $data instanceof ProductListingStruct:
foreach ($data->getListing()->getEntities() as $product) {
$elements[] = $product;
}
break;
}
}
} catch (Exception $e) {
$this->logger->error($e->getMessage(), ['trace' => $e->getTrace()]);
}
} else {
$crossSellings = $event->getPage()->getCrossSellings();
if (!empty($crossSellings->getElements())) {
$crossSellingsElements = $crossSellings->getElements();
foreach ($crossSellingsElements as $crossSellingsElement) {
foreach ($crossSellingsElement->getProducts() as $product) {
$elements[] = $product;
}
}
}
}
if (!empty($elements)) {
$collection = array_filter($elements);
$disGA4Extension = new EntityCollection($collection);
$event->getContext()->addExtension('disGA4ProductsExtension', $disGA4Extension);
}
} catch (Exception $e) {
$this->logger->error($e->getMessage(), ['trace' => $e->getTrace()]);
}
return true;
}
public function onNavigationPageLoadedEvent(NavigationPageLoadedEvent $event): bool
{
$cmsList = ['product-box', 'product-listing', 'product-slider', 'cross-selling'];
$elements = [];
try {
$cmsElements = $event->getPage()->getCmsPage()->getSections()->getBlocks()->getSlots()->getElements();
foreach ($cmsElements as $key => $object) {
if (!in_array($object->getType(), $cmsList)) {
unset($cmsElements[$key]);
}
}
foreach ($cmsElements as $object) {
$data = $object->getData();
switch ($data) {
case $data instanceof CrossSellingStruct:
if ($data->getCrossSellings()) {
foreach ($data->getCrossSellings()->getElements() as $crossSelling) {
foreach ($crossSelling->getProducts() as $product) {
$elements[] = $product;
}
}
}
break;
case $data instanceof ProductBoxStruct:
if (null !== $data->getProduct()) {
$elements[] = $data->getProduct();
}
break;
case $data instanceof ProductSliderStruct :
foreach ($data->getProducts() as $product) {
$elements[] = $product;
}
break;
case $data instanceof ProductListingStruct:
if ($data->getListing()) {
foreach ($data->getListing()->getEntities() as $product) {
$elements[] = $product;
}
}
break;
}
}
if ($event->getPage()->getCmsPage()->getProducts()) {
foreach ($event->getPage()->getCmsPage()->getProducts() as $product) {
$elements[] = $product;
}
}
if (!empty($elements)) {
$collection = array_filter($elements);
$disGA4Extension = new EntityCollection($collection);
$event->getContext()->addExtension('disGA4ProductsExtension', $disGA4Extension);
}
} catch (Exception $e) {
$this->logger->error($e->getMessage(), ['trace' => $e->getTrace()]);
}
return true;
}
}