vendor/boldr/shop-bundle/src/ShopContext.php line 142

Open in your IDE?
  1. <?php
  2. namespace Boldr\Shop\ShopBundle;
  3. use Symfony\Contracts\Service\ServiceSubscriberInterface;
  4. use Symfony\Component\Security\Core\Security;
  5. use Symfony\Component\HttpFoundation\RequestStack;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Boldr\Shop\ShopBundle\Entity\{ CustomerOrder };
  8. use Psr\Container\ContainerInterface;
  9. use Boldr\Shop\ShopBundle\OrderFlow\OrderFlowManagerInterface;
  10. class ShopContext implements ServiceSubscriberInterface
  11. {
  12.     const GUEST_CUSTOMER_ID_SESSION 'boldr_shop_guest_customer_id';
  13.     const CART_ORDER_ID_SESSION 'cart_order_id';
  14.     public static function getSubscribedServices(): array
  15.     {
  16.         return [
  17.             'request_stack' => RequestStack::class,
  18.             'security' => Security::class,
  19.             'entity_manager' => EntityManagerInterface::class,
  20.             'order_flow_manager' => OrderFlowManagerInterface::class
  21.         ];
  22.     }
  23.     private ContainerInterface $container;
  24.     /** @var Customer|null Cached customer object */
  25.     private ?Customer $customer null;
  26.     private string $defaultCurrency;
  27.     private array $currencies;
  28.     private ?Order $currentOrder null;
  29.     public function __construct(ContainerInterface $containerstring $defaultCurrency, array $currencies)
  30.     {
  31.         $this->container $container;
  32.         $this->defaultCurrency $defaultCurrency;
  33.         $this->currencies $currencies;
  34.     }
  35.     public function getSupportedCurrencies(): array
  36.     {
  37.         return $this->currencies;
  38.     }
  39.     public function getCurrency(): string
  40.     {
  41.         return $this->getCustomerCurrency($this->getCustomer());
  42.     }
  43.     private function getCustomerCurrency(?Customer $customer): string
  44.     {
  45.         $currency $this->defaultCurrency;
  46.         // If the Customer has a preferred currency set, verify it can be used.
  47.         $preferredCurrency $customer === null null $customer->getPreferredCurrency();
  48.         if ($preferredCurrency !== null)
  49.         {
  50.             // If the customer's preferred currency is available, use it for the order
  51.             if (isset($this->currencies[$preferredCurrency]))
  52.             {
  53.                 $currency $preferredCurrency;
  54.             }
  55.             // Currency not available anymore, restore currency to default currency
  56.             else
  57.             {
  58.                 $customer->setPreferredCurrency($currency);
  59.             }
  60.         }
  61.         return $currency;
  62.     }
  63.     private function createOrder(Customer $customerstring $state)
  64.     {
  65.         $currency $this->getCurrency();
  66.         $order = new Order($customer$state$currency);
  67.         $customer->getOrders()->add($order);
  68.         return $order;
  69.     }
  70.     public function getCurrentOrder(): Order
  71.     {
  72.         if (!isset($this->currentOrder))
  73.         {
  74.             $this->currentOrder $this->_getCurrentOrder();
  75.         }
  76.         return $this->currentOrder;
  77.     }
  78.     public function _getCurrentOrder(): Order
  79.     {
  80.         $cartState $this->container->get('order_flow_manager')->getCartState();
  81.         // Get (or create) customer object
  82.         $customer $this->getCustomer(true);
  83.         $session $this->container->get('request_stack')->getSession();
  84.         // If carts are stored in the session only
  85.         // @TODO Make global option to share cart across the Customer
  86.         if ($customer->getSeparateCartPerSession())
  87.         {
  88.             $em $this->container->get('entity_manager');
  89.             $session $this->container->get('request_stack')->getSession();
  90.             // Find the cart order if there is one in the session and it belongs to the customer
  91.             $cartOrderId $session->get(self::CART_ORDER_ID_SESSIONnull);
  92.             if ($cartOrderId !== null)
  93.             {
  94.                 $orderRepository $em->getRepository(Order::class);
  95.                 $cartOrder $orderRepository->find($cartOrderId);
  96.                 if ($cartOrder !== null && $cartOrder->getCustomer() === $customer)
  97.                 {
  98.                     $cartOrder $this->container->get('order_flow_manager')->getCurrentOrder($customer, [$cartOrder]);
  99.                     if ($cartOrder !== null)
  100.                         return $cartOrder;
  101.                 }
  102.             }
  103.             // If no cart was stored in the session, create a new cart and store it in the session
  104.             $cartOrder $this->createOrder($customer$cartState);
  105.             $em->flush();
  106.             $session->set(self::CART_ORDER_ID_SESSION$cartOrder->getId());
  107.             return $cartOrder;
  108.         }
  109.         else
  110.         {
  111.             $orders null;
  112.             if ($session->has(self::CART_ORDER_ID_SESSION))
  113.             {
  114.                 $cartOrderId $session->get(self::CART_ORDER_ID_SESSION);
  115.                 $cartOrder $customer->getOrders()->filter(fn($order) => $order->getId() == $cartOrderId)->first();
  116.                 if ($cartOrder !== false)
  117.                 {
  118.                     $orders = [$cartOrder];
  119.                 }
  120.             }
  121.             // If user is logged in as guest, only access current cart. If none selected, create.
  122.             if ($session->has(self::GUEST_CUSTOMER_ID_SESSION))
  123.             {
  124.                 $cartOrder null;
  125.                 if ($orders !== null)
  126.                 {
  127.                     $cartOrder $this->container->get('order_flow_manager')->getCurrentOrder($customer$orders);
  128.                 }
  129.                 if ($cartOrder === null)
  130.                 {
  131.                     $cartOrder $this->createOrder($customer$cartState);
  132.                     $this->container->get('entity_manager')->flush();
  133.                     $session->set(self::CART_ORDER_ID_SESSION$cartOrder->getId());
  134.                     return $cartOrder;
  135.                 }
  136.             }
  137.             // Find Order with cart state
  138.             $cartOrder $this->container->get('order_flow_manager')->getCurrentOrder($customer$orders);
  139.             // Create a new order if no cart order exists yet
  140.             if ($cartOrder === null)
  141.             {
  142.                 if ($session->has(self::CART_ORDER_ID_SESSION))
  143.                 {
  144.                     $session->remove(self::CART_ORDER_ID_SESSION);
  145.                     $cartOrder $this->container->get('order_flow_manager')->getCurrentOrder($customer);
  146.                 }
  147.                 if ($cartOrder === null)
  148.                 {
  149.                     $cartOrder $this->createOrder($customer$cartState);
  150.                 }
  151.             }
  152.             return $cartOrder;
  153.         }
  154.     }
  155.     public function getCustomer(bool $createIfNotExists false): ?Customer
  156.     {
  157.         if ($this->customer !== null)
  158.         {
  159.             return $this->customer;
  160.         }
  161.         $em $this->container->get('entity_manager');
  162.         $repoCustomers $em->getRepository(Customer::class);
  163.         $session $this->container->get('request_stack')->getSession();
  164.         // 1. Check for user customer
  165.         $user $this->container->get('security')->getUser();
  166.         if ($user !== null)
  167.         {
  168.             $customer $repoCustomers->createQueryBuilder('c')
  169.                 ->leftJoin('c.customerUsers''cu')
  170.                 ->leftJoin('cu.user''u')
  171.                 ->where('u = ?1')
  172.                 ->setParameter(1$user)
  173.                 ->setMaxResults(1)
  174.                 ->getQuery()
  175.                 ->getOneOrNullResult();
  176.             if ($customer !== null)
  177.             {
  178.                 if ($session->has(self::GUEST_CUSTOMER_ID_SESSION))
  179.                 {
  180.                     $id $session->get(self::GUEST_CUSTOMER_ID_SESSION);
  181.                     $guestCustomer $repoCustomers->find($id);
  182.                     if ($guestCustomer !== null)
  183.                     {
  184.                         // Transfer current order to other customer
  185.                         $currentOrder $this->container->get('order_flow_manager')->getCurrentOrder($guestCustomer);
  186.                         if ($currentOrder !== null)
  187.                         {
  188.                             $currentOrder->setCustomer($customer);
  189.                             $customer->getOrders()->add($currentOrder);
  190.                             $session->set(self::CART_ORDER_ID_SESSION$currentOrder->getId());
  191.                         }
  192.                         $em->flush();
  193.                     }
  194.                 }
  195.                 $this->customer $customer;
  196.                 return $customer;
  197.             }
  198.         }
  199.         // 2. Check for guest customer
  200.         if ($session->has(self::GUEST_CUSTOMER_ID_SESSION))
  201.         {
  202.             $id $session->get(self::GUEST_CUSTOMER_ID_SESSION);
  203.             $customer $repoCustomers->find($id);
  204.             if ($customer !== null)
  205.             {
  206.                 if ($customer->getUsers()->count() !== 0)
  207.                 {
  208.                     $session->remove(self::GUEST_CUSTOMER_ID_SESSION);
  209.                 }
  210.                 else
  211.                 {
  212.                     if ($customer !== null)
  213.                     {
  214.                         // 2.1. Attach guest customer to user if logged in
  215.                         if ($user !== null)
  216.                         {
  217.                             $customer->addUser($user);
  218.                             $em->flush($customer);
  219.                         }
  220.                         $this->customer $customer;
  221.                         return $customer;
  222.                     }
  223.                 }
  224.             }
  225.         }
  226.         // If a customer is not really necessary, just return null
  227.         if (!$createIfNotExists)
  228.         {
  229.             return null;
  230.         }
  231.         // If a customer object is neccessary for data persistence, e.g. when adding products to the cart
  232.         // create a new customer object and store it in the session
  233.         // 3. Create a new customer
  234.         $session $this->container->get('request_stack')->getSession();
  235.         $locale $this->container->get('request_stack')->getCurrentRequest()->getLocale();
  236.         $newCustomer = new Customer();
  237.         $newCustomer->setLocale($locale);
  238.         $em->persist($newCustomer);
  239.         $this->customer $newCustomer;
  240.         // 3.1. Attach the customer to the user if logged in
  241.         if ($user !== null)
  242.         {
  243.             $newCustomer->addUser($user);
  244.             $em->flush($newCustomer);
  245.             return $newCustomer;
  246.         }
  247.         // 3.2. Store the new guest customer in the session
  248.         // Obtain an ID
  249.         $em->flush($newCustomer);
  250.         $id $newCustomer->getId();
  251.         $session->set(self::GUEST_CUSTOMER_ID_SESSION$id);
  252.         return $newCustomer;
  253.     }
  254.     public function setGuestCustomer(Customer $customer): void
  255.     {
  256.         $session $this->container->get('request_stack')->getSession();
  257.         $session->set(self::GUEST_CUSTOMER_ID_SESSION$customer->getId());
  258.     }
  259. }