<?php
declare(strict_types=1);
namespace App\EventListener;
use App\DatalayerGTM\AddEvent;
use App\Entity\Product\Product;
use App\Events\PostContactEvent;
use App\Events\ProductViewItemListEvent;
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Sylius\Component\Product\Model\ProductInterface;
use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Contracts\EventDispatcher\Event;
final class GtmEventListener
{
public const POST_CONTACT_SENDING = 'post_contact_sending';
public const POST_CUSTOMER_REGISTER = 'post_customer_register';
public const POST_CUSTOMER_LOGIN = 'post_customer_login';
public const POST_CART_REMOVE = 'post_cart_remove';
public const POST_CART_SAVE = 'post_cart_save';
private OrderRepositoryInterface $orderRepository;
private AddEvent $addEvent;
private ChannelContextInterface $channelContext;
private SessionInterface $session;
private RequestStack $requestStack;
private RouterInterface $router;
private TaxonRepositoryInterface $taxonRepository;
private LocaleContextInterface $localeContext;
/**
* @param OrderRepositoryInterface $orderRepository
* @param AddEvent $addEvent
* @param ChannelContextInterface $channelContext
* @param SessionInterface $session
* @param RequestStack $requestStack
* @param RouterInterface $router
* @param TaxonRepositoryInterface $taxonRepository
* @param LocaleContextInterface $localeContext
*/
public function __construct(OrderRepositoryInterface $orderRepository, AddEvent $addEvent, ChannelContextInterface $channelContext, SessionInterface $session, RequestStack $requestStack, RouterInterface $router, TaxonRepositoryInterface $taxonRepository, LocaleContextInterface $localeContext)
{
$this->orderRepository = $orderRepository;
$this->addEvent = $addEvent;
$this->channelContext = $channelContext;
$this->session = $session;
$this->requestStack = $requestStack;
$this->router = $router;
$this->taxonRepository = $taxonRepository;
$this->localeContext = $localeContext;
}
public function onKernelRequest(RequestEvent $event)
{
if (!$event->isMainRequest()) {
return;
}
if($this->isAdminRoute($event)){
return;
}
if(!$this->hasGtmId()){
return;
}
$this->addEvent->addEventReady($event);
//use session
if ($this->session->has(self::POST_CONTACT_SENDING)) {
$subject = $this->session->get(self::POST_CONTACT_SENDING);
$this->session->remove(self::POST_CONTACT_SENDING);
$this->addEvent->addEventContact($subject);
}
if ($this->session->has(self::POST_CUSTOMER_REGISTER)) {
$subject = $this->session->get(self::POST_CUSTOMER_REGISTER);
$this->session->remove(self::POST_CUSTOMER_REGISTER);
$this->addEvent->addEventRegister($subject);
}
if ($this->session->has(self::POST_CUSTOMER_LOGIN)) {
$subject = $this->session->get(self::POST_CUSTOMER_LOGIN);
$this->session->remove(self::POST_CUSTOMER_LOGIN);
$this->addEvent->addEventLogin($subject);
}
if ($this->session->has(self::POST_CART_REMOVE)) {
$subject = $this->session->get(self::POST_CART_REMOVE);
$this->session->remove(self::POST_CART_REMOVE);
$this->addEvent->addEventRemoveFromCart($subject);
}
if ($this->session->has(self::POST_CART_SAVE)) {
$this->session->remove(self::POST_CART_SAVE);
$this->addEvent->addEventSaveCart();
}
if($event->getRequest()->get('_route') === "sylius_shop_cart_summary"){
$this->addEvent->addEventViewCart();
}
if($event->getRequest()->get('_route') === "app_cart_management.cart.save"){
$this->session->set(self::POST_CART_SAVE, 'cart');
}
if($event->getRequest()->get('_route') === "sylius_shop_checkout_address"){
$this->addEvent->addEventBeginCheckout();
}
if($event->getRequest()->get('_route') === "sylius_shop_checkout_select_payment"){
$this->addEvent->addEventShippingInfo();
$this->addEvent->prepareAddPaymentInfo(); //un peu spécifique, ici on va juste préparer un cart qu'on cachera dans les données afin de pouvoir par la suite ajouter l'event addPaymentInfo lors du clique sur "payer"
}
if($event->getRequest()->get('_route') === "sylius_shop_order_thank_you"){
$orderId = $event->getRequest()->getSession()->get('sylius_order_id');
if ($orderId === null) {
return;
}
$order = $this->orderRepository->find($orderId);
if (!$order instanceof OrderInterface) {
return;
}
$this->addEvent->addEventPurchase($order);
}
}
public function productShow(ResourceControllerEvent $event): void
{
//exit;
//if($this->isAdminRoute($event)){
// return;
//}
if(!$this->hasGtmId()){
return;
}
$referer = $this->requestStack->getCurrentRequest()->headers->get('referer');
$product = $event->getSubject();
if(!$product instanceof ProductInterface){
return;
}
if($referer){
$refererPath = parse_url($referer, PHP_URL_PATH);
$routeInfo = $this->router->match($refererPath);
if (isset($routeInfo['_route'])) {
$routeName = $routeInfo['_route'];
if($routeName === "monsieurbiz_sylius_search_taxon" && array_key_exists('slug', $routeInfo)){
$taxon = $this->taxonRepository->findOneBySlug($routeInfo['slug'], $this->localeContext->getLocaleCode());
if($taxon){
$this->addEvent->addEventSelectItem($product, $taxon);
}
}
}
}
$this->addEvent->addEventViewItem($product);
}
public function postCartRemove(ResourceControllerEvent $event): void
{
//if($this->isAdminRoute($event)){
// return;
//}
if(!$this->hasGtmId()){
return;
}
$this->session->set(self::POST_CART_REMOVE, $event->getSubject()->getProduct()->getId()); //on est obligé de passer l'id et non le product, sinon bug bizarre lié à la locale
}
public function addToWishlist(Product $product): ?array //un peu spécifique, il n'est pas appelé via un event, mais directement dans le controller AddProductToWishlistAction
{
if(!$this->hasGtmId()){
return null;
}
return $this->addEvent->addEventAddToWishlist($product);
}
public function addToCart(Product $product): ?array //un peu spécifique, il n'est pas appelé via un event, mais directement dans le controller OrderItemController
{
if(!$this->hasGtmId()){
return null;
}
return $this->addEvent->addEventAddToCart($product);
}
public function contactPostSending(PostContactEvent $event): void
{
//if($this->isAdminRoute($event)){
// return;
//}
if(!$this->hasGtmId()){
return;
}
$this->session->set(self::POST_CONTACT_SENDING, $event->getSubject()->getSubject());
}
public function productViewItemList(ProductViewItemListEvent $event)
{
//if($this->isAdminRoute($event)){
// return;
//}
if(!$this->hasGtmId()){
return;
}
$allProducts = $event->getProducts();
if(array_key_exists('result', $allProducts) || array_key_exists('productsPalinal', $allProducts) || array_key_exists('productsSubCategory', $allProducts) ){
$this->addEvent->addEventViewItemList($allProducts);
}
}
public function customerPostRegister(ResourceControllerEvent $event): void
{
//if($this->isAdminRoute($event)){
// return;
//}
if(!$this->hasGtmId()){
return;
}
$this->session->set(self::POST_CUSTOMER_REGISTER, $event->getSubject());
}
public function customerPostLogin(InteractiveLoginEvent $event): void
{
if($this->isAdminRoute($event)){
return;
}
if(!$this->hasGtmId()){
return;
}
$this->session->set(self::POST_CUSTOMER_LOGIN, $event->getAuthenticationToken()->getUser()->getId());
}
protected function hasGtmId() :bool
{
if($this->channelContext->getChannel()->getGoogleTagManagerId()){
return true;
}
return false;
}
protected function isAdminRoute(Event $event): bool
{
$routeName = $event->getRequest()->get('_route');
if (null === $routeName) {
return false;
}
if (strpos($routeName, 'admin') !== false) {
return true;
}
return false;
}
}