src/Controller/ShopReviewController.php line 63

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Shop;
  4. use App\Entity\ShopReview;
  5. use App\Form\ShopReviewType;
  6. use App\Repository\ShopReviewRepository;
  7. use App\Service\ShopReviewService;
  8. use Doctrine\ORM\EntityManagerInterface;
  9. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  10. use Symfony\Component\HttpFoundation\JsonResponse;
  11. use Symfony\Component\HttpFoundation\Request;
  12. use Symfony\Component\HttpFoundation\Response;
  13. use Symfony\Component\Routing\Annotation\Route;
  14. use Symfony\Component\Security\Http\Attribute\IsGranted;
  15. #[Route('/shop/{slug}/reviews'name'shop_reviews_')]
  16. class ShopReviewController extends AbstractController
  17. {
  18.     private ShopReviewService $shopReviewService;
  19.     private EntityManagerInterface $entityManager;
  20.     private ShopReviewRepository $shopReviewRepository;
  21.     public function __construct(ShopReviewService $shopReviewServiceEntityManagerInterface $entityManager)
  22.     {
  23.         $this->shopReviewService $shopReviewService;
  24.         $this->entityManager $entityManager;
  25.         $this->shopReviewRepository $entityManager->getRepository(ShopReview::class);
  26.     }
  27.     #[Route(''name'index'methods: ['GET'])]
  28.     public function index(string $slugRequest $request): Response
  29.     {
  30.         $shop $this->entityManager->getRepository(Shop::class)->findOneBy(['slug' => $slug]);
  31.         
  32.         if (!$shop) {
  33.             throw $this->createNotFoundException('Boutique non trouvée. Le slug "' $slug '" ne correspond à aucune boutique.');
  34.         }
  35.         $page = (int) $request->query->get('page'1);
  36.         $limit 10;
  37.         
  38.         $filters = [
  39.             'rating' => $request->query->get('rating'),
  40.             'verified' => $request->query->get('verified') === '1',
  41.             'search' => $request->query->get('search')
  42.         ];
  43.         $reviewsData $this->shopReviewService->getShopReviews($shop$page$limit$filters);
  44.         $stats $this->shopReviewService->getShopReviewStats($shop);
  45.         // Vérifier si l'utilisateur connecté peut laisser un avis
  46.         $canReview false;
  47.         $userReview null;
  48.         
  49.         if ($this->getUser()) {
  50.             $canReview = !$this->shopReviewRepository->hasUserReviewedShop($this->getUser(), $shop);
  51.             if (!$canReview) {
  52.                 $userReview $this->shopReviewRepository->findOneBy(['user' => $this->getUser(), 'shop' => $shop]);
  53.             }
  54.         }
  55.         return $this->render('shop/reviews/index.html.twig', [
  56.             'shop' => $shop,
  57.             'reviews' => $reviewsData['reviews'],
  58.             'stats' => $stats,
  59.             'pagination' => [
  60.                 'page' => $reviewsData['page'],
  61.                 'pages' => $reviewsData['pages'],
  62.                 'total' => $reviewsData['total']
  63.             ],
  64.             'filters' => $filters,
  65.             'canReview' => $canReview,
  66.             'userReview' => $userReview
  67.         ]);
  68.     }
  69.     #[Route('/new'name'new'methods: ['GET''POST'])]
  70.     #[IsGranted('ROLE_USER')]
  71.     public function new(string $slugRequest $request): Response
  72.     {
  73.         $shop $this->entityManager->getRepository(Shop::class)->findOneBy(['slug' => $slug]);
  74.         
  75.         if (!$shop) {
  76.             throw $this->createNotFoundException('Boutique non trouvée.');
  77.         }
  78.         // Vérifier si l'utilisateur peut laisser un avis
  79.         if ($this->shopReviewRepository->hasUserReviewedShop($this->getUser(), $shop)) {
  80.             $this->addFlash('error''Vous avez déjà laissé un avis pour cette boutique');
  81.             return $this->redirectToRoute('shop_reviews_index', ['slug' => $shop->getSlug()]);
  82.         }
  83.         $review = new ShopReview();
  84.         $form $this->createForm(ShopReviewType::class, $review);
  85.         $form->handleRequest($request);
  86.         if ($form->isSubmitted() && $form->isValid()) {
  87.             $data = [
  88.                 'rating' => $review->getRating(),
  89.                 'comment' => $review->getComment(),
  90.                 'reviewType' => $review->getReviewType()
  91.             ];
  92.             $result $this->shopReviewService->createReview($this->getUser(), $shop$data);
  93.             if ($result['success']) {
  94.                 $this->addFlash('success'$result['message']);
  95.                 return $this->redirectToRoute('shop_reviews_index', ['slug' => $shop->getSlug()]);
  96.             } else {
  97.                 $this->addFlash('error'$result['message']);
  98.             }
  99.         }
  100.         return $this->render('shop/reviews/new.html.twig', [
  101.             'shop' => $shop,
  102.             'form' => $form->createView()
  103.         ]);
  104.     }
  105.     #[Route('/{id}/edit'name'edit'methods: ['GET''POST'])]
  106.     #[IsGranted('ROLE_USER')]
  107.     public function edit(string $slugShopReview $reviewRequest $request): Response
  108.     {
  109.         $shop $this->entityManager->getRepository(Shop::class)->findOneBy(['slug' => $slug]);
  110.         
  111.         if (!$shop) {
  112.             throw $this->createNotFoundException('Boutique non trouvée.');
  113.         }
  114.         // Vérifier que l'utilisateur est le propriétaire de l'avis
  115.         if ($review->getUser() !== $this->getUser()) {
  116.             throw $this->createAccessDeniedException('Vous ne pouvez pas modifier cet avis');
  117.         }
  118.         $form $this->createForm(ShopReviewType::class, $review);
  119.         $form->handleRequest($request);
  120.         if ($form->isSubmitted() && $form->isValid()) {
  121.             $data = [
  122.                 'rating' => $review->getRating(),
  123.                 'comment' => $review->getComment(),
  124.                 'reviewType' => $review->getReviewType()
  125.             ];
  126.             $result $this->shopReviewService->updateReview($review$data);
  127.             if ($result['success']) {
  128.                 $this->addFlash('success'$result['message']);
  129.                 return $this->redirectToRoute('shop_reviews_index', ['slug' => $shop->getSlug()]);
  130.             } else {
  131.                 $this->addFlash('error'$result['message']);
  132.             }
  133.         }
  134.         return $this->render('shop/reviews/edit.html.twig', [
  135.             'shop' => $shop,
  136.             'review' => $review,
  137.             'form' => $form->createView()
  138.         ]);
  139.     }
  140.     #[Route('/{id}/delete'name'delete'methods: ['POST'])]
  141.     #[IsGranted('ROLE_USER')]
  142.     public function delete(string $slugShopReview $reviewRequest $request): Response
  143.     {
  144.         $shop $this->entityManager->getRepository(Shop::class)->findOneBy(['slug' => $slug]);
  145.         
  146.         if (!$shop) {
  147.             throw $this->createNotFoundException('Boutique non trouvée.');
  148.         }
  149.         // Vérifier que l'utilisateur est le propriétaire de l'avis
  150.         if ($review->getUser() !== $this->getUser()) {
  151.             throw $this->createAccessDeniedException('Vous ne pouvez pas supprimer cet avis');
  152.         }
  153.         if ($this->isCsrfTokenValid('delete' $review->getId(), $request->request->get('_token'))) {
  154.             $result $this->shopReviewService->deleteReview($review);
  155.             $this->addFlash('success'$result['message']);
  156.         }
  157.         return $this->redirectToRoute('shop_reviews_index', ['slug' => $shop->getSlug()]);
  158.     }
  159.     #[Route('/{id}/helpful'name'helpful'methods: ['POST'])]
  160.     public function markAsHelpful(string $slugShopReview $reviewRequest $request): JsonResponse
  161.     {
  162.         $shop $this->entityManager->getRepository(Shop::class)->findOneBy(['slug' => $slug]);
  163.         
  164.         if (!$shop) {
  165.             return new JsonResponse(['success' => false'message' => 'Boutique non trouvée']);
  166.         }
  167.         if ($request->isXmlHttpRequest()) {
  168.             $user $this->getUser();
  169.             $result $this->shopReviewService->markAsHelpful($review$user);
  170.             return new JsonResponse($result);
  171.         }
  172.         return new JsonResponse(['success' => false'message' => 'Requête invalide']);
  173.     }
  174.     #[Route('/{id}/not-helpful'name'not_helpful'methods: ['POST'])]
  175.     public function markAsNotHelpful(string $slugShopReview $reviewRequest $request): JsonResponse
  176.     {
  177.         $shop $this->entityManager->getRepository(Shop::class)->findOneBy(['slug' => $slug]);
  178.         
  179.         if (!$shop) {
  180.             return new JsonResponse(['success' => false'message' => 'Boutique non trouvée']);
  181.         }
  182.         if ($request->isXmlHttpRequest()) {
  183.             $user $this->getUser();
  184.             $result $this->shopReviewService->markAsNotHelpful($review$user);
  185.             return new JsonResponse($result);
  186.         }
  187.         return new JsonResponse(['success' => false'message' => 'Requête invalide']);
  188.     }
  189.     #[Route('/stats'name'stats'methods: ['GET'])]
  190.     public function stats(string $slug): JsonResponse
  191.     {
  192.         $shop $this->entityManager->getRepository(Shop::class)->findOneBy(['slug' => $slug]);
  193.         
  194.         if (!$shop) {
  195.             return new JsonResponse(['success' => false'message' => 'Boutique non trouvée']);
  196.         }
  197.         $stats $this->shopReviewService->getShopReviewStats($shop);
  198.         return new JsonResponse($stats);
  199.     }
  200.     #[Route('/filter'name'filter'methods: ['GET'])]
  201.     public function filter(string $slugRequest $request): JsonResponse
  202.     {
  203.         $shop $this->entityManager->getRepository(Shop::class)->findOneBy(['slug' => $slug]);
  204.         
  205.         if (!$shop) {
  206.             return new JsonResponse(['success' => false'message' => 'Boutique non trouvée']);
  207.         }
  208.         $page = (int) $request->query->get('page'1);
  209.         $limit 10;
  210.         
  211.         $filters = [
  212.             'rating' => $request->query->get('rating'),
  213.             'verified' => $request->query->get('verified') === '1',
  214.             'search' => $request->query->get('search')
  215.         ];
  216.         $reviewsData $this->shopReviewService->getShopReviews($shop$page$limit$filters);
  217.         return new JsonResponse([
  218.             'reviews' => $reviewsData['reviews'],
  219.             'pagination' => [
  220.                 'page' => $reviewsData['page'],
  221.                 'pages' => $reviewsData['pages'],
  222.                 'total' => $reviewsData['total']
  223.             ]
  224.         ]);
  225.     }
  226. }