<?php
namespace App\EventSubscribers\Main;
use App\Entity\Main\AffiliateNotificationConfig;
use App\Entity\Main\Product;
use App\Entity\Main\User;
use App\Entity\Main\UserCreditNote;
use App\Events\Main\Cart\CartChargedBackEvent;
use App\Events\Main\Cart\CartCreatedEvent;
use App\Events\Main\Cart\CartCreditNoteUsedEvent;
use App\Events\Main\Cart\CartItemAddedEvent;
use App\Events\Main\Cart\CartItemQuantityUpdatedEvent;
use App\Events\Main\Cart\CartItemRemovedEvent;
use App\Events\Main\Cart\CartRefundedEvent;
use App\Events\Main\Coaching\CoachingClickedOffEvent;
use App\Events\Main\Coaching\CoachingClickedOnEvent;
use App\Services\CartManager;
use App\Services\AffiliateNotificationManager;
use App\Services\ReferralProgramManager;
use App\Services\UserCreditNoteManager;
use App\Services\UserManager;
use phpDocumentor\Reflection\Types\This;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
* Class CartSubscriber
* @package App\EventSubscribers\Main
*/
class CartSubscriber implements EventSubscriberInterface
{
const
CART_ITEM_QTY_UPDATED = 'cart.updateItemQuantity',
CART_ITEM_ADDED = 'cart.itemAdded',
CART_ITEM_REMOVED = 'cart.itemRemoved',
CART_CREATED = 'cart.created',
CART_REFUND = 'cart.refund',
CART_CHARGEBACK = 'cart.chargeback',
CART_CREDIT_NOTE_USED = 'cart.creditNoteUsed'
;
/**
* @var SessionInterface
*/
private $session;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* @var CartManager
*/
private $cartFactory;
/**
* @var UserManager
*/
private $userManager;
/**
* @var ReferralProgramManager
*/
private $referralProgramManager;
/**
* @var AffiliateNotificationManager
*/
private $notificationManager;
private UserCreditNoteManager $userCreditNoteManager;
private ?Request $request;
/**
* CartSubscriber constructor.
* @param RequestStack $requestStack
* @param EventDispatcherInterface $eventDispatcher
* @param CartManager $cartFactory
* @param UserManager $userManager
* @param ReferralProgramManager $referralProgramManager
* @param AffiliateNotificationManager $notificationManager
* @param UserCreditNoteManager $userCreditNoteManager
*/
public function __construct(
private RequestStack $requestStack,
EventDispatcherInterface $eventDispatcher,
CartManager $cartFactory,
UserManager $userManager,
ReferralProgramManager $referralProgramManager,
AffiliateNotificationManager $notificationManager,
UserCreditNoteManager $userCreditNoteManager
) {
$this->request = $this->requestStack->getCurrentRequest();
if ($this->request instanceof Request) {
$this->session = $this->request->getSession();
}
$this->eventDispatcher = $eventDispatcher;
$this->cartFactory = $cartFactory;
$this->userManager = $userManager;
$this->referralProgramManager = $referralProgramManager;
$this->notificationManager = $notificationManager;
$this->userCreditNoteManager = $userCreditNoteManager;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
return array(
self::CART_ITEM_QTY_UPDATED => "itemQuantityUpdated",
self::CART_ITEM_REMOVED => "itemRemoved",
self::CART_ITEM_ADDED => "itemAdded",
self::CART_CREATED => "cartCreated",
self::CART_REFUND => "cartRefund",
self::CART_CHARGEBACK => "cartChargeBack",
self::CART_CREDIT_NOTE_USED => "cartCreditNoteUsed"
);
}
/**
* Process stuff when a product quantity is changed.
* @param CartItemQuantityUpdatedEvent $event
*/
public function itemQuantityUpdated(CartItemQuantityUpdatedEvent $event)
{
if ($event->getOldQuantity() == 0 && $event->getNewQuantity() > 0) {
$newEvent = new CartItemAddedEvent($event->getCart(), $event->getPackProduct());
$this->eventDispatcher->dispatch($newEvent, self::CART_ITEM_ADDED);
} elseif ($event->getOldQuantity() > 0 && $event->getNewQuantity() == 0) {
$newEvent = new CartItemRemovedEvent($event->getCart(), $event->getPackProduct());
$this->eventDispatcher->dispatch($newEvent, self::CART_ITEM_REMOVED);
}
if ($event->getPackProduct()->getProduct()->getProductType() == Product::ELECTRONIC_PRODUCT) {
// if he didn't change quantity but validated coaching we mark it :)
$this->session->set(CartManager::COACHING_CHOICE_SESSION_KEY, true);
if (0 == $event->getOldQuantity() && 1 == $event->getNewQuantity()) {
$event = new CoachingClickedOnEvent($event->getCart());
$this->eventDispatcher->dispatch($event, CoachingSubscriber::COACHING_CLICKED_ON);
} else {
$event = new CoachingClickedOffEvent($event->getCart());
$this->eventDispatcher->dispatch($event, CoachingSubscriber::COACHING_CLICKED_OFF);
}
}
// process what we want when wuantity is updated here :)
}
/**
* Process stuff when an item is removed from cart
* @param CartItemRemovedEvent $event
*/
public function itemRemoved(CartItemRemovedEvent $event)
{
// Check if it is a coaching product. (for now it is electronic product)
if ($event->getPackProduct()->getProduct()->getProductType() == Product::ELECTRONIC_PRODUCT) {
$this->session->set(CartManager::NO_COACHING_SESSION_KEY, true);
$this->session->set(CartManager::COACHING_CHOICE_SESSION_KEY, true);
}
}
/**
* Process stuff when an item is added to the cart
* @param CartItemAddedEvent $event
*/
public function itemAdded(CartItemAddedEvent $event)
{
// Check if it is a coaching product. (for now it is electronic product)
if ($event->getPackProduct()->getProduct()->getProductType() == Product::ELECTRONIC_PRODUCT && $event->getPackProduct()->getProductQuantity() > 0) {
$this->session->set(CartManager::NO_COACHING_SESSION_KEY, false);
$this->session->set(CartManager::COACHING_CHOICE_SESSION_KEY, true);
}
$this->notificationManager->addNotification($event->getCart()->getTracking(), $event->getCart(), AffiliateNotificationConfig::ADD_CART_ITEM);
}
/**
* @param CartCreatedEvent $event
* @throws \Exception
*/
public function cartCreated(CartCreatedEvent $event)
{
if (($event->getUser() instanceof User && !$this->cartFactory->checkUserIsEligibleForCoaching($event->getUser()))
|| $this->session->get(CartManager::NO_COACHING_SESSION_KEY)
) {
$this->cartFactory->removeCoaching($event->getCart());
}
}
/**
* @param CartRefundedEvent $event
*/
public function cartRefund(CartRefundedEvent $event)
{
$cart = $event->getCart();
//disable promo code generated for the cart if it has been refunded.
$this->referralProgramManager->disablePromoCodeByCart($cart);
}
/**
* @param CartChargedBackEvent $event
*/
public function cartChargeBack(CartChargedBackEvent $event)
{
$cart = $event->getCart();
//disable promo code generated for the cart if it has been charged back.
$this->referralProgramManager->disablePromoCodeByCart($cart);
}
/**
* @param CartCreditNoteUsedEvent $event
*/
public function cartCreditNoteUsed(CartCreditNoteUsedEvent $event)
{
$cart = $event->getCart();
$cartTotal = $event->getCartTotal();
$this->userCreditNoteManager->calculateLeftCreditNoteAmount($cart, $cartTotal);
}
}