src/Controller/Blo/CartController.php line 32

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controller\Blo;
  4. use App\Entity\Blo\Cart;
  5. use App\Entity\Blo\CartItem;
  6. use App\Repository\Blo\CartRepository;
  7. use App\Repository\Blo\ProductRepository;
  8. use App\Repository\Blo\ProductVariantRepository;
  9. use Doctrine\ORM\EntityManagerInterface;
  10. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  11. use Symfony\Component\HttpFoundation\RequestStack;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\HttpFoundation\Response;
  14. use Symfony\Component\Routing\Annotation\Route;
  15. #[Route('/cart')]
  16. class CartController extends AbstractController
  17. {
  18.     public function __construct(
  19.         private readonly CartRepository $cartRepository,
  20.         private readonly ProductRepository $productRepository,
  21.         private readonly ProductVariantRepository $productVariantRepository,
  22.         private readonly EntityManagerInterface $em,
  23.         private readonly RequestStack $requestStack,
  24.     ) {
  25.     }
  26.     #[Route(''name'blo_cart'methods: ['GET'])]
  27.     public function index(): Response
  28.     {
  29.         $cart $this->getOrCreateCart();
  30.         return $this->render('blo/cart/index.html.twig', [
  31.             'cart' => $cart,
  32.         ]);
  33.     }
  34.     #[Route('/add/{productId}'name'blo_cart_add'methods: ['POST'])]
  35.     public function add(int $productIdRequest $request): Response
  36.     {
  37.         $product $this->productRepository->find($productId);
  38.         if (!$product || $product->getStatus() !== 'APPROVED') {
  39.             $this->addFlash('error''Produit introuvable ou indisponible.');
  40.             return $this->redirectToRoute('blo_catalog');
  41.         }
  42.         $variantId $request->request->getInt('variant_id');
  43.         $variant null;
  44.         if ($variantId) {
  45.             $variant $this->productVariantRepository->find($variantId);
  46.             if (!$variant || $variant->getProduct()->getId() !== $product->getId()) {
  47.                 $this->addFlash('error''Variante invalide.');
  48.                 return $this->redirectToRoute('blo_product_show', ['slug' => $product->getSlug()]);
  49.             }
  50.         } elseif ($product->hasVariants()) {
  51.             $this->addFlash('error''Veuillez sélectionner une taille et une couleur.');
  52.             return $this->redirectToRoute('blo_product_show', ['slug' => $product->getSlug()]);
  53.         }
  54.         $maxStock $variant $variant->getStockQty() : $product->getStockQty();
  55.         $qty max(1, (int) $request->request->get('qty'1));
  56.         if ($qty $maxStock) {
  57.             $this->addFlash('error''Stock insuffisant.');
  58.             return $this->redirectToRoute('blo_product_show', ['slug' => $product->getSlug()]);
  59.         }
  60.         $cart $this->getOrCreateCart();
  61.         $existing null;
  62.         foreach ($cart->getItems() as $item) {
  63.             if ($item->getProduct()->getId() !== $productId) {
  64.                 continue;
  65.             }
  66.             $itemVariantId $item->getProductVariant()?->getId();
  67.             if (($variant?->getId() ?? 0) === ($itemVariantId ?? 0)) {
  68.                 $existing $item;
  69.                 break;
  70.             }
  71.         }
  72.         if ($existing) {
  73.             $newQty $existing->getQty() + $qty;
  74.             $limit $existing->getProductVariant() ? $existing->getProductVariant()->getStockQty() : $existing->getProduct()->getStockQty();
  75.             if ($newQty $limit) {
  76.                 $this->addFlash('error''Stock insuffisant.');
  77.                 return $this->redirectToRoute('blo_cart');
  78.             }
  79.             $existing->setQty($newQty);
  80.         } else {
  81.             $item = new CartItem();
  82.             $item->setCart($cart);
  83.             $item->setProduct($product);
  84.             $item->setProductVariant($variant);
  85.             $item->setQty($qty);
  86.             $item->setPriceSnapshot($product->getEffectivePrice());
  87.             $cart->addItem($item);
  88.         }
  89.         $cart->setUpdatedAt(new \DateTimeImmutable());
  90.         $this->em->flush();
  91.         $this->addFlash('success''Produit ajouté au panier.');
  92.         if ($request->request->get('action') === 'buy_now') {
  93.             return $this->redirectToRoute('blo_checkout');
  94.         }
  95.         return $this->redirect($request->headers->get('Referer'$this->generateUrl('blo_catalog')));
  96.     }
  97.     #[Route('/update/{itemId}'name'blo_cart_update'methods: ['POST'])]
  98.     public function update(int $itemIdRequest $request): Response
  99.     {
  100.         if (!$this->isCsrfTokenValid('blo_cart_update_' $itemId$request->request->get('_csrf_token'))) {
  101.             $this->addFlash('error''Jeton de sécurité invalide.');
  102.             return $this->redirectToRoute('blo_cart');
  103.         }
  104.         $cart $this->getOrCreateCart();
  105.         $item null;
  106.         foreach ($cart->getItems() as $i) {
  107.             if ($i->getId() === $itemId) {
  108.                 $item $i;
  109.                 break;
  110.             }
  111.         }
  112.         if (!$item) {
  113.             return $this->redirectToRoute('blo_cart');
  114.         }
  115.         $qty max(0, (int) $request->request->get('qty'0));
  116.         if ($qty === 0) {
  117.             $cart->removeItem($item);
  118.             $this->em->remove($item);
  119.         } else {
  120.             $maxStock $item->getProductVariant() ? $item->getProductVariant()->getStockQty() : $item->getProduct()->getStockQty();
  121.             if ($qty $maxStock) {
  122.                 $this->addFlash('error''Stock insuffisant.');
  123.                 return $this->redirectToRoute('blo_cart');
  124.             }
  125.             $item->setQty($qty);
  126.         }
  127.         $cart->setUpdatedAt(new \DateTimeImmutable());
  128.         $this->em->flush();
  129.         return $this->redirectToRoute('blo_cart');
  130.     }
  131.     #[Route('/remove/{itemId}'name'blo_cart_remove'methods: ['POST'])]
  132.     public function remove(int $itemIdRequest $request): Response
  133.     {
  134.         if (!$this->isCsrfTokenValid('blo_cart_remove_' $itemId$request->request->get('_csrf_token'))) {
  135.             $this->addFlash('error''Jeton de sécurité invalide.');
  136.             return $this->redirectToRoute('blo_cart');
  137.         }
  138.         $cart $this->getOrCreateCart();
  139.         foreach ($cart->getItems() as $item) {
  140.             if ($item->getId() === $itemId) {
  141.                 $cart->removeItem($item);
  142.                 $this->em->remove($item);
  143.                 break;
  144.             }
  145.         }
  146.         $cart->setUpdatedAt(new \DateTimeImmutable());
  147.         $this->em->flush();
  148.         return $this->redirectToRoute('blo_cart');
  149.     }
  150.     private function getOrCreateCart(): Cart
  151.     {
  152.         $user $this->getUser();
  153.         $sessionId $this->requestStack->getSession()->getId();
  154.         if ($user) {
  155.             $cart $this->cartRepository->findByCustomer($user);
  156.             if (!$cart) {
  157.                 $cart $this->cartRepository->findBySessionId($sessionId);
  158.                 if ($cart) {
  159.                     $cart->setCustomer($user);
  160.                     $cart->setSessionId(null);
  161.                     $this->em->flush();
  162.                 }
  163.             }
  164.         } else {
  165.             $cart $this->cartRepository->findBySessionId($sessionId);
  166.         }
  167.         if (!$cart) {
  168.             $cart = new Cart();
  169.             $cart->setCustomer($user);
  170.             if (!$user) {
  171.                 $cart->setSessionId($sessionId);
  172.             }
  173.             $this->em->persist($cart);
  174.             $this->em->flush();
  175.         }
  176.         return $cart;
  177.     }
  178. }