From 17eea8124694d1c76894c2f016cfe908acbf3c92 Mon Sep 17 00:00:00 2001 From: Jeff Coleman Date: Sun, 1 Dec 2019 21:17:46 -0800 Subject: [PATCH] If a cart/quote exists already, the module will now automatically apply the coupon to it as soon as a page is loaded with a valid coupon code in the URL --- Helper/Cart.php | 70 +++++++++++++++++++ .../Discountcodeurl/CheckoutCartSaveAfter.php | 45 +++--------- .../App/FrontControllerInterface.php | 54 +++++++++++++- 3 files changed, 132 insertions(+), 37 deletions(-) create mode 100644 Helper/Cart.php diff --git a/Helper/Cart.php b/Helper/Cart.php new file mode 100644 index 0000000..d407e90 --- /dev/null +++ b/Helper/Cart.php @@ -0,0 +1,70 @@ +quoteRepository = $quoteRepository; + $this->messageManager = $messageManager; + } + + /************************************************************************/ + + public function applyCoupon(\Magento\Quote\Model\Quote $quote, string $coupon): void { + + try { + $quote->setCouponCode($coupon); + $this->quoteRepository->save($quote->collectTotals()); + } + + catch (LocalizedException $e) { + $this->messageManager->addError( + __("Discount code $coupon couldn't be applied: " . + $e->getMessage()) + ); + } + + catch (\Exception $e) { + $this->messageManager->addError( + __("Discount code $coupon couldn't be applied or is invalid") + ); + } + + if ($quote->getCouponCode() != $coupon) { + $this->messageManager->addError( + __("Discount code $coupon is invalid. Verify that it's correct and try again.") + ); + } + } +} + diff --git a/Observer/Discountcodeurl/CheckoutCartSaveAfter.php b/Observer/Discountcodeurl/CheckoutCartSaveAfter.php index ad96715..ff7ee5b 100644 --- a/Observer/Discountcodeurl/CheckoutCartSaveAfter.php +++ b/Observer/Discountcodeurl/CheckoutCartSaveAfter.php @@ -17,45 +17,41 @@ class CheckoutCartSaveAfter implements \Magento\Framework\Event\ObserverInterfac */ private $config; - /** - * @var \Magento\Quote\Api\CartRepositoryInterface - */ - private $quoteRepository; - /** * @var \Crankycyclops\DiscountCodeUrl\Helper\Cookie */ private $cookieHelper; /** - * @var \Magento\Framework\Message\ManagerInterface + * @var \Crankycyclops\DiscountCodeUrl\Helper\Cart */ - private $messageManager; + private $cartHelper; /************************************************************************/ /** * Constructor * + * @param \Crankycyclops\DiscountCodeUrl\Helper\Config $config * @param \Crankycyclops\DiscountCodeUrl\Helper\Cookie $cookieHelper + * @param \Crankycyclops\DiscountCodeUrl\Helper\Cart $cartHelper */ public function __construct( \Crankycyclops\DiscountCodeUrl\Helper\Config $config, - \Magento\Quote\Api\CartRepositoryInterface $quoteRepository, \Crankycyclops\DiscountCodeUrl\Helper\Cookie $cookieHelper, - \Magento\Framework\Message\ManagerInterface $messageManager + \Crankycyclops\DiscountCodeUrl\Helper\Cart $cartHelper ) { $this->config = $config; - $this->quoteRepository = $quoteRepository; $this->cookieHelper = $cookieHelper; - $this->messageManager = $messageManager; + $this->cartHelper = $cartHelper; } /************************************************************************/ /** * If a coupon code was set in the URL at any point during the session, - * apply it as soon as the cart is created. + * apply it as soon as the cart is created and re-apply it every time it's + * updated to keep the total price current. * * @param \Magento\Framework\Event\Observer $observer * @@ -72,30 +68,7 @@ public function execute(\Magento\Framework\Event\Observer $observer): void { $cart = $observer->getData('cart'); if ($cart) { - - try { - $cart->getQuote()->setCouponCode($coupon); - $this->quoteRepository->save($cart->getQuote()->collectTotals()); - } - - catch (LocalizedException $e) { - $this->messageManager->addError( - __("Discount code $coupon couldn't be applied: " . - $e->getMessage()) - ); - } - - catch (\Exception $e) { - $this->messageManager->addError( - __("Discount code $coupon couldn't be applied or is invalid") - ); - } - - if ($cart->getQuote()->getCouponCode() != $coupon) { - $this->messageManager->addError( - __("Discount code $coupon is invalid. Verify that it's correct and try again.") - ); - } + $this->cartHelper->applyCoupon($cart->getQuote(), $coupon); } } } diff --git a/Plugin/Framework/App/FrontControllerInterface.php b/Plugin/Framework/App/FrontControllerInterface.php index dd2eaca..b334807 100644 --- a/Plugin/Framework/App/FrontControllerInterface.php +++ b/Plugin/Framework/App/FrontControllerInterface.php @@ -27,6 +27,11 @@ class FrontControllerInterface { */ private $cookieHelper; + /** + * @var \Crankycyclops\DiscountCodeUrl\Helper\Cart + */ + private $cartHelper; + /** * @var \Magento\SalesRule\Model\Coupon */ @@ -42,6 +47,11 @@ class FrontControllerInterface { */ private $registry; + /** + * @var \Magento\Checkout\Model\Session + */ + private $checkoutSession; + /************************************************************************/ /** @@ -50,24 +60,30 @@ class FrontControllerInterface { * @param \Magento\Framework\App\RequestInterface $request * @param \Crankycyclops\DiscountCodeUrl\Helper\Config $config * @param \Crankycyclops\DiscountCodeUrl\Helper\Cookie $cookieHelper + * @param \Crankycyclops\DiscountCodeUrl\Helper\Cart $cartHelper * @param \Magento\SalesRule\Model\Coupon $couponModel * @param \Magento\SalesRule\Model\Rule $ruleModel * @param \Magento\Framework\Registry $registry + * @param \Magento\Checkout\Model\Session $checkoutSession */ public function __construct( \Magento\Framework\App\RequestInterface $request, \Crankycyclops\DiscountCodeUrl\Helper\Config $config, \Crankycyclops\DiscountCodeUrl\Helper\Cookie $cookieHelper, + \Crankycyclops\DiscountCodeUrl\Helper\Cart $cartHelper, \Magento\SalesRule\Model\Coupon $couponModel, \Magento\SalesRule\Model\Rule $ruleModel, - \Magento\Framework\Registry $registry + \Magento\Framework\Registry $registry, + \Magento\Checkout\Model\Session $checkoutSession ) { $this->request = $request; $this->config = $config; $this->cookieHelper = $cookieHelper; + $this->cartHelper = $cartHelper; $this->couponModel = $couponModel; $this->ruleModel = $ruleModel; $this->registry = $registry; + $this->checkoutSession = $checkoutSession; } /************************************************************************/ @@ -216,5 +232,41 @@ public function beforeDispatch(\Magento\Framework\App\FrontControllerInterface $ } } } + + /************************************************************************/ + + /** + * If a quote already exists, we need to apply the discount code to it + * automatically (if possible) and before the response is rendered. This + * covers us in the case that a user applies a discount code to the URL + * after having a cart that's already full (which means the save cart + * observer won't execute and therefore won't update the quote's price.) I + * can't do this in beforeDispatch, because based on my own testing, it + * seems that the session classes don't get populated until after + * FrontController::dispatch() finishes. + * + * @param \Magento\Framework\App\FrontControllerInterface $subject (not used) + * @param ResponseInterface|ResultInterface Return value of FrontController::dispatch() + * + * @return ResponseInterface|ResultInterface + */ + public function afterDispatch(\Magento\Framework\App\FrontControllerInterface $subject, $result) { + + if ($this->config->isEnabled()) { + + // If a quote already exists, apply the + // discount automatically (if possible) + $coupon = $this->registry->registry('crankycyclops_discounturl_coupon'); + + if ($coupon && $this->checkoutSession->hasQuote()) { + $this->cartHelper->applyCoupon( + $this->checkoutSession->getQuote(), + $coupon + ); + } + } + + return $result; + } }