render('website/escape_room/index.html.twig', [ 'publishedCount' => $rooms->countByStatus(EscapeRoomStatus::PUBLISHED), ]); } /** * Slim feed the map and the list are both built from. Cached at the edge for * a few minutes; the dataset only changes when the importer runs or an admin * edits a room. */ #[Route(path: '/escape-rooms/data.json', name: 'website_escaperooms_data', methods: ['GET'])] public function data(EscapeRoomRepository $rooms): JsonResponse { $response = new JsonResponse([ 'generatedAt' => (new \DateTimeImmutable())->format(\DateTimeInterface::ATOM), 'rooms' => $rooms->findMapData(), ]); $response->setPublic(); $response->setMaxAge(600); $response->setSharedMaxAge(600); return $response; } #[Route(path: '/escape-rooms/suggest', name: 'website_escaperoom_suggest', methods: ['GET', 'POST'])] public function suggest(Request $request, EntityManagerInterface $em): Response { $room = new EscapeRoom(); $form = $this->createForm(SuggestEscapeRoomType::class, $room); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $room->setSource(EscapeRoomSource::USER) ->setStatus(EscapeRoomStatus::PENDING); if ($this->getUser() instanceof User) { $room->setSubmittedBy($this->getUser()); } $em->persist($room); $em->flush(); $this->addFlash('success', 'Thanks! Your suggestion has been sent for review and will appear on the map once approved.'); return $this->redirectToRoute('website_escaperooms'); } return $this->render('website/escape_room/suggest.html.twig', [ 'form' => $form, ]); } #[Route(path: '/escape-rooms/{id}-{slug}', name: 'website_escaperoom_show', methods: ['GET'], requirements: ['id' => '\d+', 'slug' => '[a-z0-9-]*'])] public function show(EscapeRoom $room, EscapeRoomReviewRepository $reviews): Response { $this->guardVisible($room); return $this->renderRoom($room, $reviews, $this->createForm(EscapeRoomReviewType::class)); } #[Route(path: '/escape-rooms/{id}/reviews', name: 'website_escaperoom_review', methods: ['POST'], requirements: ['id' => '\d+'])] #[IsGranted('IS_AUTHENTICATED_FULLY')] public function review( EscapeRoom $room, Request $request, EntityManagerInterface $em, EscapeRoomReviewRepository $reviews, ): Response { $this->guardVisible($room); $review = new EscapeRoomReview(); $form = $this->createForm(EscapeRoomReviewType::class, $review); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { /** @var User $user */ $user = $this->getUser(); $review->setEscapeRoom($room)->setAuthor($user); $em->persist($review); $em->flush(); $this->addFlash('success', 'Thanks for your review!'); return $this->redirectToRoute('website_escaperoom_show', [ 'id' => $room->getId(), 'slug' => $room->getSlug(), ]); } return $this->renderRoom($room, $reviews, $form); } private function guardVisible(EscapeRoom $room): void { if ($room->isDeleted() || !$room->getStatus()->isPubliclyVisible()) { throw $this->createNotFoundException(); } } private function renderRoom(EscapeRoom $room, EscapeRoomReviewRepository $reviews, FormInterface $reviewForm): Response { return $this->render('website/escape_room/show.html.twig', [ 'room' => $room, 'reviews' => $reviews->findVisibleForRoom($room), 'rating' => $reviews->ratingSummary($room), 'reviewForm' => $reviewForm, ]); } }