<?php
namespace App\Twig;
use App\Entity\Main\Cart;
use App\Entity\Main\DiscountCode;
use App\Entity\Main\User;
use App\Exceptions\Main\DiscountCode\DiscountCodeAlreadyUsedException;
use App\Exceptions\Main\DiscountCode\DiscountCodeNotValidRegistrationException;
use App\Exceptions\Main\DiscountCode\DiscountCodeWrongUserException;
use App\Services\CartManager;
use App\Services\TrackingManager;
use App\Services\ABTestManager;
use App\Services\DiscountCodeManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\NonUniqueResultException;
use Twig\Extension\AbstractExtension;
use Symfony\Component\HttpFoundation\Request;
use Twig\TwigFunction;
class DiscountCodeExtension extends AbstractExtension
{
/**
* @var DiscountCodeManager
*/
private $discountCodeManager;
/**
* @var ABTestManager
*/
private $ABTestManager;
/**
* @var TrackingManager
*/
private $trackingFactory;
/**
* @var EntityManagerInterface
*/
private $entityManager;
/**
* @var CartManager
*/
private $cartFactory;
/**
* DiscountCodeExtension constructor.
* @param DiscountCodeManager $discountCodeManager
* @param ABTestManager $ABTestManager
* @param TrackingManager $trackingFactory
* @param EntityManagerInterface $entityManager
* @param CartManager $cartFactory
*/
public function __construct(
DiscountCodeManager $discountCodeManager,
ABTestManager $ABTestManager,
TrackingManager $trackingFactory,
EntityManagerInterface $entityManager,
CartManager $cartFactory
) {
$this->discountCodeManager = $discountCodeManager;
$this->ABTestManager = $ABTestManager;
$this->trackingFactory = $trackingFactory;
$this->entityManager = $entityManager;
$this->cartFactory = $cartFactory;
}
/**
* @return array|TwigFunction[]
*/
public function getFunctions(): array
{
return [
new TwigFunction('getPromoCodesOfDay', [$this, 'getPromoCodesOfDay']),
new TwigFunction('isPromoCodeExpired', [$this, 'isPromoCodeExpired']),
new TwigFunction('getPromoCodeValueText', [$this, 'getPromoCodeValueText']),
new TwigFunction('canShowPromoCodeAlertFromGetParam', [$this, 'canShowPromoCodeAlertFromGetParam'])
];
}
/**
* @return array|null
*/
public function getPromoCodesOfDay()
{
return $this->discountCodeManager->getPromoCodesOfDay();
}
/**
* @param DiscountCode $discountCode
* @return bool
*/
public function isPromoCodeExpired(DiscountCode $discountCode)
{
return $this->discountCodeManager->isPromoCodeExpired($discountCode);
}
/**
* @param string $discountCodeName
* @return string|null
* @throws NonUniqueResultException
*/
public function getPromoCodeValueText(string $discountCodeName)
{
$discountCode = $this->discountCodeManager->getActivePromoCodeByName($discountCodeName);
$text = null;
if (DiscountCode::PERCENTAGE_RATE == $discountCode->getDiscountCodeType()) {
$text = $discountCode->getDiscountCodeValue() . '%';
} elseif (DiscountCode::FIXED_AMOUNT == $discountCode->getDiscountCodeType()) {
$text = $discountCode->getDiscountCodeValue() / 100 . '€';
}
return $text;
}
/**
* @param Request $request
* @param $user
* @return bool
* @throws NonUniqueResultException
*/
public function canShowPromoCodeAlertFromGetParam(Request $request, $user)
{
if ($request->getSession()) {
$dcodeParam = $request->getSession()->get('dcode');
}
// Purchase is over, remove the code to prevent having it flying around ...
if ('brulafine_over' === $request->get('_route')) {
$request->getSession()->set('dcode', null);
return false;
}
// check if dcode exists.
if (empty($dcodeParam)) {
return false;
}
// check if the code has been already applied for the current session.
if ($request->getSession()->get(DiscountCode::DISCOUNT_CODE_HIDE_ALERT)) {
return false;
}
$cart = $this->cartFactory->resolveCurrentCart();
$discountCode = $this->discountCodeManager->getActivePromoCodeByName($dcodeParam);
if (!$discountCode instanceof DiscountCode) {
return false;
}
if ($this->discountCodeManager->isDiscountCodeExpired($discountCode)) {
return false;
}
// if has cart and user is logged in.
if ($cart instanceof Cart && $cart->getUser() instanceof User) {
// check if this code is applied in the cart.
if ($cart->getDiscountCode() instanceof DiscountCode && $cart->getDiscountCode()->getDiscountCodeName() == $dcodeParam) {
$request->getSession()->set(DiscountCode::DISCOUNT_CODE_HIDE_ALERT, true);
return false;
} else {
// check if this code can be applied in the cart.
try {
$this->cartFactory->checkCanApplyCodeToCart($discountCode, $cart);
} catch (DiscountCodeAlreadyUsedException $e) {
// check if discount code already used.
return false;
} catch (DiscountCodeWrongUserException $e) {
// check if discount code is for this user.
return false;
} catch (\Exception $e) {
$request->getSession()->set(DiscountCode::DISCOUNT_CODE_HIDE_ALERT, true);
return false;
}
}
// if has no cart and user is logged in
} elseif ($user instanceof User) {
// check if can apply SINGLE_USAGE and SINGLE_CLIENT_USAGE
if (!$this->discountCodeManager->canApplySingleUsageCode($discountCode)) {
return false;
}
try {
$this->discountCodeManager->canCodeBeUsedByUser($user, $discountCode);
// check if discount code already used by this user.
} catch (DiscountCodeAlreadyUsedException $e) {
return false;
} catch (DiscountCodeNotValidRegistrationException $e) {
return false;
} catch (\Exception $e) {
$request->getSession()->set(DiscountCode::DISCOUNT_CODE_HIDE_ALERT, true);
return false;
}
}
return true;
}
/**
* @return string
*/
public function getName()
{
return 'discount_code_extension';
}
}