<?php
namespace App\EventSubscriber\Order;
use App\Ecommerce\Model\Order;
use App\Model\Customer;
use Exception;
use Factory\CartBundle\Classes\CartEvents;
use Factory\CartBundle\Classes\DataMapper\CartDataMapper;
use Symfony\Component\HttpFoundation\JsonResponse;
use Factory\CartBundle\Event\CartEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Factory\CartBundle\Repository\CartRepository;
use Pimcore\Bundle\EcommerceFrameworkBundle\EnvironmentInterface;
use Pimcore\Bundle\EcommerceFrameworkBundle\Factory;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\HttpFoundation\Request;
use App\Ecommerce\PriceSystem\PriceSystemRule\Processor as PriceSystemRuleProcessor;
use App\Repository\OrderRepository;
use Pimcore\Model\DataObject\PriceSystemRule;
class CartActionSubscriber implements EventSubscriberInterface
{
/**
* @var Security
*/
protected $security;
/**
* @var RequestStack
*/
protected $requestStack;
/**
* @var CartRepository
*/
protected $cartRepository;
/**
* @var EnvironmentInterface
*/
protected $environment;
/**
* @var OrderRepository
*/
protected $orderRepository;
protected $customer;
public static function getSubscribedEvents()
{
return [
CartEvents::CART_BEFORE_FETCH => [
['updateCurrency', 11],
['fetchOrder', 10]
],
CartEvents::CART_BEFORE_UPDATE => [
['updateOrderItem', 10]
],
CartEvents::CART_BEFORE_REMOVE => [
['removeOrderItem', 10]
]
];
}
public function __construct(
Security $security,
RequestStack $requestStack,
CartRepository $cartRepository,
OrderRepository $orderRepository,
EnvironmentInterface $environment
) {
$this->security = $security;
$this->requestStack = $requestStack;
$this->cartRepository = $cartRepository;
$this->environment = $environment;
$this->orderRepository = $orderRepository;
}
protected function getRequest(): Request
{
return $this->requestStack->getMasterRequest();
}
protected function getOrderFromReferer()
{
$httpReferer = $this->getRequest()->server->get('HTTP_REFERER');
if (!preg_match('/\/order\-quote\/(\d+)/', $httpReferer, $matches)) {
return null;
}
return Order::getById($matches[1]);
}
public function updateCurrency(CartEvent $event)
{
if (!$order = $this->getOrderFromReferer()) {
return;
}
$this->updateEnvironmentWithAddress($order);
$this->updateEnvironmentWithShipping($order);
$currentCurrency = $nextCurrency = $order->getCurrency();
$address_id = $this->getRequest()->get('address_id');
$nextCurrency = $currentCurrency;
if ($address_id && $address_id != 'new') {
$nextCurrency = $this->orderRepository->detectCurrency($order, $address_id);
}
if ($currentCurrency == $nextCurrency) {
$event->stopPropagation();
$event->setResponse(new JsonResponse([
'currency' => $nextCurrency,
'data' => (new CartDataMapper($order))->all($this->getRequest())
]));
return;
}
$this->orderRepository->convertOrderCurrency($order, $nextCurrency, false);
$order->getPriceCalculator()->reset();
$event->stopPropagation();
$event->setResponse(new JsonResponse([
'currency' => $nextCurrency,
'data' => (new CartDataMapper($order))->all($this->getRequest())
]));
}
protected function updateEnvironmentWithAddress($order)
{
$env = Factory::getInstance()->getEnvironment();
if ($billingAddressId = $this->getRequest()->cookies->get('__order_billing_address_id')) {
if ($billingAddressId == 'customer') {
$billingAddress = $this->orderRepository->createAddressFromOrder('customer', $order);
} else {
$billingAddress = $this->getCustomerAddress($billingAddressId);
}
$env->setBillingAddress($billingAddress);
}
if ($shippingAddressId = $this->getRequest()->cookies->get('__order_shipping_address_id')) {
if ($shippingAddressId == 'delivery') {
$shippingAddress = $this->orderRepository->createAddressFromOrder('delivery', $order);
} else {
$shippingAddress = $this->getCustomerAddress($shippingAddressId);
}
$env->setShippingAddress($shippingAddress);
}
}
protected function updateEnvironmentWithShipping($order)
{
return;
if ($this->isPaymentStep()) {
return;
}
$env = Factory::getInstance()->getEnvironment();
$index = 'apply_factory_shipping__ord_'.$order->getId();
$env->setCustomItem($index, null);
}
protected function isPaymentStep()
{
$httpReferer = $this->getRequest()->server->get('HTTP_REFERER');
return preg_match('/\/order\-quote\/(\d+)\/payment/', $httpReferer, $matches);
}
protected function getCurrentCustomer(): Customer
{
if (!$this->customer) {
$env = Factory::getInstance()->getEnvironment();
$this->customer = Customer::getById($env->getCurrentUserId());
}
return $this->customer;
}
protected function getCustomerAddress(string $addressId)
{
$customer = $this->getCurrentCustomer();
return $customer->getAddress($addressId);
}
public function fetchOrder(CartEvent $event)
{
if (!$order = $this->getOrderFromReferer()) {
return;
}
$event->stopPropagation();
$event->setResponse(new JsonResponse([
'data' => (new CartDataMapper($order))->all($this->getRequest())
]));
}
public function updateOrderItem(CartEvent $event)
{
if (!$order = $this->getOrderFromReferer()) {
return;
}
$quantities = $this->getRequest()->get('quantities');
foreach ($order->getItems() as $orderItem) {
if (!isset($quantities[$orderItem->getProductNumber()])) {
continue;
}
$quantity = intVal($quantities[$orderItem->getProductNumber()]);
if ($quantity == 0) {
$orderItem->delete();
continue;
}
$orderItem->setAmount($quantity);
$orderItem->save();
}
$event->stopPropagation();
$event->setResponse(new JsonResponse([
'data' => (new CartDataMapper(Order::getById($order->getId(), true)))->all($this->getRequest())
]));
}
public function removeOrderItem(CartEvent $event)
{
if (!$order = $this->getOrderFromReferer()) {
return;
}
throw new \Exception('Not implemented. Instead of this action, use update with quantity 0 (zero)!');
}
}