Newer
Older
TillQliro / Model / Quote / Agent.php
@Jonas Jonsson Jonas Jonsson on 2 Apr 2024 6 KB Initial
<?php
/**
 * Copyright © Qliro AB. All rights reserved.
 * See LICENSE.txt for license details.
 */

namespace Qliro\QliroOne\Model\Quote;

use Magento\Checkout\Model\Session;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory;
use Magento\Framework\Stdlib\CookieManagerInterface;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\Quote;
use Qliro\QliroOne\Api\LinkRepositoryInterface;
use Qliro\QliroOne\Model\Logger\Manager;

/**
 * Quote Agent class for temporarily persist quote for post order creation phase
 */
class Agent
{
    const COOKIE_NAME = 'QOMR';  // Stands for "Qliro One Merchant Reference"
    const COOKIE_LIFETIME = 10800; // 3 hours for now

    /**
     * @var \Magento\Quote\Model\Quote
     */
    private $relevantQuote;

    /**
     * @var \Magento\Framework\Stdlib\CookieManagerInterface
     */
    private $cookieManager;

    /**
     * @var \Qliro\QliroOne\Api\LinkRepositoryInterface
     */
    private $linkRepository;

    /**
     * @var \Magento\Quote\Api\CartRepositoryInterface
     */
    private $quoteRepository;

    /**
     * @var \Qliro\QliroOne\Model\Logger\Manager
     */
    private $logManager;

    /**
     * @var \Magento\Checkout\Model\Session
     */
    private $checkoutSession;

    /**
     * @var \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory
     */
    private $cookieMetadataFactory;

    /**
     * Inject dependnecies
     *
     * @param \Magento\Checkout\Model\Session $checkoutSession
     * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager
     * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory
     * @param \Qliro\QliroOne\Api\LinkRepositoryInterface $linkRepository
     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
     * @param \Qliro\QliroOne\Model\Logger\Manager $logManager
     */
    public function __construct(
        Session $checkoutSession,
        CookieManagerInterface $cookieManager,
        CookieMetadataFactory $cookieMetadataFactory,
        LinkRepositoryInterface $linkRepository,
        CartRepositoryInterface $quoteRepository,
        Manager $logManager
    ) {
        $this->checkoutSession = $checkoutSession;
        $this->cookieManager = $cookieManager;
        $this->cookieMetadataFactory = $cookieMetadataFactory;
        $this->linkRepository = $linkRepository;
        $this->quoteRepository = $quoteRepository;
        $this->logManager = $logManager;
    }

    /**
     * Store specific quote in a Quote cookie agent
     *
     * @param \Magento\Quote\Model\Quote $quote
     */
    public function store(Quote $quote)
    {
        $this->logManager->addTag('cookies');

        try {
            $link = $this->linkRepository->getByQuoteId($quote->getId());
            $merchantReference = $link->getReference();
            $this->logManager->setMerchantReference($merchantReference);

            $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata();
            $cookieMetadata->setDuration(self::COOKIE_LIFETIME);
            $cookieMetadata->setPath('/');

            $this->cookieManager->setPublicCookie(self::COOKIE_NAME, $merchantReference, $cookieMetadata);
        } catch (\Exception $exception) {
            $this->logManager->critical(
                $exception,
                [
                    'extra' => [
                        'qliro_merchant_reference' => $merchantReference ?? null,
                    ]
                ]
            );
        }

        $this->logManager->removeTag('cookies');
    }

    /**
     * Return the current quote if relevant, otherwise fetch a quote previously stored by the Quote cookie agent.
     * Lazy-loadable for better performance.
     *
     * @return \Magento\Quote\Model\Quote|null
     */
    public function fetchRelevantQuote()
    {
        if (!$this->relevantQuote) {
            $this->logManager->addTag('cookies');

            $quote = $this->checkoutSession->getQuote();

            if ($this->isQuoteRelevant($quote)) {
                return $quote;
            }

            $quote = null;

            try {
                $merchantReference = $this->cookieManager->getCookie(self::COOKIE_NAME);
                $link = $this->linkRepository->getByReference($merchantReference);
                $this->logManager->setMerchantReference($merchantReference);

                /** @var \Magento\Quote\Model\Quote $quote */
                $quote = $this->quoteRepository->get($link->getQuoteId());
            } catch (\Exception $exception) {
                $this->logManager->critical(
                    $exception,
                    [
                        'extra' => [
                            'qliro_merchant_reference' => $merchantReference ?? null,
                        ]
                    ]
                );
            }

            $this->logManager->removeTag('cookies');
            $this->relevantQuote = $quote;
        }

        return $this->relevantQuote;
    }

    /**
     * Clear the quote if it's stored
     */
    public function clear()
    {
        $this->logManager->addTag('cookies');
        $merchantReference = $this->cookieManager->getCookie(self::COOKIE_NAME);

        if ($merchantReference) {
            $this->logManager->setMerchantReference($merchantReference);
        }

        try {
            $cookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata();
            $cookieMetadata->setDuration(0);
            $cookieMetadata->setPath('/');
            $this->cookieManager->deleteCookie(self::COOKIE_NAME, $cookieMetadata);
        } catch (\Exception $exception) {
            $this->logManager->critical(
                $exception,
                [
                    'extra' => [
                        'qliro_merchant_reference' => $merchantReference ?? null,
                    ]
                ]
            );
        }

        $this->logManager->removeTag('cookies');
    }

    /**
     * Check if the quote relevant for QliroOne Checkout
     *
     * @param \Magento\Quote\Model\Quote $quote
     * @return bool
     */
    private function isQuoteRelevant(Quote $quote)
    {
        if (empty($quote->getAllVisibleItems())) {
            return false;
        }

        try {
            $this->linkRepository->getByQuoteId($quote->getId());
        } catch (NoSuchEntityException $exception) {
            return false;
        }

        return true;
    }
}