<?php declare(strict_types=1);
namespace DISco\GA4\Storefront\Controller;
use ReflectionMethod;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\Log\Package;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Controller\CookieController;
use Shopware\Storefront\Framework\Captcha\GoogleReCaptchaV2;
use Shopware\Storefront\Framework\Captcha\GoogleReCaptchaV3;
use Shopware\Storefront\Framework\Cookie\CookieProviderInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Environment;
/**
* Support v6.4.1
* @Shopware\Core\Framework\Routing\Annotation\RouteScope(scopes={"storefront"})
*/
#[Route(defaults: ['_routeScope' => ['storefront']])]
#[Package('storefront')]
class CookieControllerDecorator extends CookieController
{
private CookieProviderInterface $cookieProvider;
private CookieController $originalService;
private SystemConfigService $systemConfigService;
private TranslatorInterface $translator;
private EntityRepository $salesChannelAnalyticsRepository;
public function __construct(
CookieController $service,
CookieProviderInterface $cookieProvider,
SystemConfigService $systemConfigService,
TranslatorInterface $translator,
EntityRepository $salesChannelAnalyticsRepository
) {
$numberOfParameters = (new ReflectionMethod(parent::class, '__construct'))->getNumberOfRequiredParameters();
if (3 === $numberOfParameters) { // For SW 6.6.*
parent::__construct($cookieProvider, $systemConfigService, $salesChannelAnalyticsRepository);
} else {
parent::__construct($cookieProvider, $systemConfigService);
}
$this->originalService = $service;
$this->cookieProvider = $cookieProvider;
$this->systemConfigService = $systemConfigService;
$this->translator = $translator;
}
public function setTwig(Environment $twig): void
{
if (is_callable('parent::setTwig')) {
parent::setTwig($twig);
}
}
public function getDecorated(): CookieController
{
return $this->originalService;
}
/**
* @Route("/cookie/offcanvas", name="frontend.cookie.offcanvas", options={"seo"="false"}, methods={"GET"}, defaults={"XmlHttpRequest"=true})
*/
#[Route(path: '/cookie/offcanvas', name: 'frontend.cookie.offcanvas', options: ['seo' => false], defaults: ['XmlHttpRequest' => true], methods: ['GET'])]
public function offcanvas(SalesChannelContext $context): Response
{
$cookieGroups = $this->cookieProvider->getCookieGroups();
$cookieGroups = $this->filterGoogleAnalyticsCookie($context, $cookieGroups);
$cookieGroups = $this->filterComfortFeaturesCookie($context->getSalesChannelId(), $cookieGroups);
$cookieGroups = $this->filterGoogleReCaptchaCookie($context->getSalesChannelId(), $cookieGroups);
$cookieGroups = $this->filterGA4GoogleTagCookie($context->getSalesChannelId(), $cookieGroups);
$cookieGroups = $this->filterGA4GoogleAdsCookie($context->getSalesChannelId(), $cookieGroups);
$cookieGroups = $this->filterGA4GoogleAnalyticsCookie($context->getSalesChannelId(), $cookieGroups);
$response = $this->renderStorefront('@Storefront/storefront/layout/cookie/cookie-configuration.html.twig', ['cookieGroups' => $cookieGroups]);
$response->headers->set('x-robots-tag', 'noindex,follow');
return $response;
}
/**
* @Route("/cookie/permission", name="frontend.cookie.permission", options={"seo"="false"}, methods={"GET"}, defaults={"XmlHttpRequest"=true})
*/
#[Route(path: '/cookie/permission', name: 'frontend.cookie.permission', options: ['seo' => false], defaults: ['XmlHttpRequest' => true], methods: ['GET'])]
public function permission(SalesChannelContext $context): Response
{
$cookieGroups = $this->cookieProvider->getCookieGroups();
$cookieGroups = $this->filterGoogleAnalyticsCookie($context, $cookieGroups);
$cookieGroups = $this->filterComfortFeaturesCookie($context->getSalesChannelId(), $cookieGroups);
$cookieGroups = $this->filterGoogleReCaptchaCookie($context->getSalesChannelId(), $cookieGroups);
$cookieGroups = $this->filterGA4GoogleTagCookie($context->getSalesChannelId(), $cookieGroups);
$cookieGroups = $this->filterGA4GoogleAdsCookie($context->getSalesChannelId(), $cookieGroups);
$cookieGroups = $this->filterGA4GoogleAnalyticsCookie($context->getSalesChannelId(), $cookieGroups);
$response = $this->renderStorefront('@Storefront/storefront/layout/cookie/cookie-permission.html.twig', ['cookieGroups' => $cookieGroups]);
$response->headers->set('x-robots-tag', 'noindex,follow');
return $response;
}
private function filterGA4GoogleTagCookie(string $salesChannelId, array $cookieGroups): array
{
if ($this->systemConfigService->get('DIScoGA4.config.googleTagEnabled',$salesChannelId)) {
return $cookieGroups;
}
$filteredGroups = [];
foreach ($cookieGroups as $cookieGroup) {
if ($this->translator->trans($cookieGroup['snippet_name']) == $this->translator->trans('cookie.googletag_name')) {
$cookieGroup['entries'] = array_filter($cookieGroup['entries'], function ($item) {
return $item['snippet_name'] !== 'cookie.cookie-gtag';
});
// Only add cookie group if it has entries
if (\count($cookieGroup['entries']) > 0) {
$filteredGroups[] = $cookieGroup;
}
continue;
}
$filteredGroups[] = $cookieGroup;
}
return $filteredGroups;
}
private function filterGA4GoogleAdsCookie(string $salesChannelId, array $cookieGroups): array
{
if ($this->systemConfigService->get('DIScoGA4.config.googleAdsEnabled',$salesChannelId)) {
return $cookieGroups;
}
$filteredGroups = [];
foreach ($cookieGroups as $cookieGroup) {
if ($this->translator->trans($cookieGroup['snippet_name']) == $this->translator->trans('cookie.marketing_name')) {
$cookieGroup['entries'] = array_filter($cookieGroup['entries'], function ($item) {
return $item['snippet_name'] !== 'cookie.cookie-gads';
});
// Only add cookie group if it has entries
if (\count($cookieGroup['entries']) > 0) {
$filteredGroups[] = $cookieGroup;
}
continue;
}
$filteredGroups[] = $cookieGroup;
}
return $filteredGroups;
}
private function filterGA4GoogleAnalyticsCookie(string $salesChannelId, array $cookieGroups): array
{
if ($this->systemConfigService->get('DIScoGA4.config.googleAnalyticsEnabled',$salesChannelId)) {
return $cookieGroups;
}
$filteredGroups = [];
foreach ($cookieGroups as $cookieGroup) {
if ($this->translator->trans($cookieGroup['snippet_name']) == $this->translator->trans('cookie.statistics_name')) {
$cookieGroup['entries'] = array_filter($cookieGroup['entries'], function ($item) {
return $item['snippet_name'] !== 'cookie.cookie-ga';
});
// Only add cookie group if it has entries
if (\count($cookieGroup['entries']) > 0) {
$filteredGroups[] = $cookieGroup;
}
continue;
}
$filteredGroups[] = $cookieGroup;
}
return $filteredGroups;
}
private function filterGoogleAnalyticsCookie(SalesChannelContext $context, array $cookieGroups): array
{
if ($context->getSalesChannel()->getAnalytics() && $context->getSalesChannel()->getAnalytics()->isActive()) {
return $cookieGroups;
}
$filteredGroups = [];
foreach ($cookieGroups as $cookieGroup) {
if ($cookieGroup['snippet_name'] === 'cookie.groupStatistical') {
$cookieGroup['entries'] = array_filter($cookieGroup['entries'], function ($item) {
return $item['snippet_name'] !== 'cookie.groupStatisticalGoogleAnalytics';
});
// Only add statistics cookie group if it has entries
if (\count($cookieGroup['entries']) > 0) {
$filteredGroups[] = $cookieGroup;
}
continue;
}
$filteredGroups[] = $cookieGroup;
}
return $filteredGroups;
}
private function filterComfortFeaturesCookie(string $salesChannelId, array $cookieGroups): array
{
foreach ($cookieGroups as $groupIndex => $cookieGroup) {
if ($cookieGroup['snippet_name'] !== 'cookie.groupComfortFeatures') {
continue;
}
foreach ($cookieGroup['entries'] as $entryIndex => $entry) {
if ($entry['snippet_name'] !== 'cookie.groupComfortFeaturesWishlist') {
continue;
}
if (!$this->systemConfigService->get('core.cart.wishlistEnabled', $salesChannelId)) {
unset($cookieGroups[$groupIndex]['entries'][$entryIndex]);
}
}
if (\count($cookieGroups[$groupIndex]['entries']) === 0) {
unset($cookieGroups[$groupIndex]);
}
}
return $cookieGroups;
}
private function filterGoogleReCaptchaCookie(string $salesChannelId, array $cookieGroups): array
{
foreach ($cookieGroups as $groupIndex => $cookieGroup) {
if ($cookieGroup['snippet_name'] !== 'cookie.groupRequired') {
continue;
}
foreach ($cookieGroup['entries'] as $entryIndex => $entry) {
if ($entry['snippet_name'] !== 'cookie.groupRequiredCaptcha') {
continue;
}
$activeGreCaptchaV2 = $this->systemConfigService->get('core.basicInformation.activeCaptchasV2.' . GoogleReCaptchaV2::CAPTCHA_NAME . '.isActive', $salesChannelId) ?? false;
$activeGreCaptchaV3 = $this->systemConfigService->get('core.basicInformation.activeCaptchasV2.' . GoogleReCaptchaV3::CAPTCHA_NAME . '.isActive', $salesChannelId) ?? false;
if (!$activeGreCaptchaV2 && !$activeGreCaptchaV3) {
unset($cookieGroups[$groupIndex]['entries'][$entryIndex]);
}
}
if (\count($cookieGroups[$groupIndex]['entries']) === 0) {
unset($cookieGroups[$groupIndex]);
}
}
return $cookieGroups;
}
}