<?php
namespace App\Controller;
use App\Entity\Category;
use App\Entity\Tour;
use App\Entity\POI;
use App\Form\TourType;
use App\Repository\TourRepository;
use JMS\Serializer\Context;
use JMS\Serializer\Expression\ExpressionEvaluator;
use JMS\Serializer\Handler\HandlerRegistry;
use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use JMS\Serializer\Ordering\IdenticalPropertyOrderingStrategy;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerBuilder;
use JMS\Serializer\SerializerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use App\Serializer\IdOnlyRelationNormalizer;
#[Route('/tour')]
class TourController extends AbstractController
{
/*
* @var SerializerInterface
*/
private SerializerInterface $serializer;
/**
* @param SerializerInterface $serializer
*/
public function __construct(SerializerInterface $serializer)
{
$this->serializer = SerializerBuilder::create()
->setPropertyNamingStrategy(
new SerializedNameAnnotationStrategy(
new IdenticalPropertyNamingStrategy()
)
)->addDefaultHandlers()
->setExpressionEvaluator(new ExpressionEvaluator(new ExpressionLanguage()))
->build();
}
#[Route('/', name: 'app_tour_index', methods: ['GET'])]
public function index(TourRepository $tourRepository): Response
{
return $this->render('tour/index.html.twig', [
'tours' => $tourRepository->findAll(),
]);
}
#[Route('/new', name: 'app_tour_new', methods: ['GET', 'POST'])]
public function new(Request $request, TourRepository $tourRepository): Response
{
$tour = new Tour();
$form = $this->createForm(TourType::class, $tour);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$tourRepository->save($tour, true);
return $this->redirectToRoute('app_tour_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('tour/new.html.twig', [
'tour' => $tour,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_tour_show', methods: ['GET'])]
public function show(Tour $tour): Response
{
return $this->render('tour/show.html.twig', [
'tour' => $tour,
]);
}
#[Route('/{id}/edit', name: 'app_tour_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Tour $tour, TourRepository $tourRepository): Response
{
$form = $this->createForm(TourType::class, $tour);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$tourRepository->save($tour, true);
return $this->redirectToRoute('app_tour_index', [], Response::HTTP_SEE_OTHER);
}
return $this->renderForm('tour/edit.html.twig', [
'tour' => $tour,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_tour_delete', methods: ['POST'])]
public function delete(Request $request, Tour $tour, TourRepository $tourRepository): Response
{
if ($this->isCsrfTokenValid('delete' . $tour->getId(), $request->request->get('_token'))) {
$tourRepository->remove($tour, true);
}
return $this->redirectToRoute('app_tour_index', [], Response::HTTP_SEE_OTHER);
}
#[Route('/api/all')]
public function getAll(EntityManagerInterface $entityManager): Response
{
$tours = $entityManager->getRepository(Tour::class)->findAll();
$categories = $entityManager->getRepository(Category::class)->findAll();
$pois = $entityManager->getRepository(POI::class)->findAll();
$merged_entity_data = $this->serializeEntityData($pois, $tours, $categories);
$response = JsonResponse::fromJsonString($merged_entity_data);
return $response;
}
#[Route('/api/live')]
public function getLive(EntityManagerInterface $entityManager): Response
{
$tours = $entityManager->getRepository(Tour::class)->findBy(array('live' => true));
$categories = $entityManager->getRepository(Category::class)->findBy(array('live' => true));
$pois = $entityManager->getRepository(POI::class)->findBy(array('live' => true));
$merged_entity_data = $this->serializeEntityData($pois, $tours, $categories);
$response = new JsonResponse($merged_entity_data, 200, [], false);
return $response;
}
#[Route('/api/beta')]
public function getBeta(EntityManagerInterface $entityManager): Response
{
$tours = $entityManager->getRepository(Tour::class)->findBy(array('live' => false));
$categories = $entityManager->getRepository(Category::class)->findBy(array('live' => false));
$pois = $entityManager->getRepository(POI::class)->findBy(array('live' => false));
$merged_entity_data = $this->serializeEntityData($pois, $tours, $categories);
$response = new JsonResponse($merged_entity_data, 200, [], false);
return $response;
}
public function serializeEntityData($pois, $tours, $categories)
{
$contextTours = SerializationContext::create()->enableMaxDepthChecks()->setGroups("tour");
$contextPois = SerializationContext::create()->enableMaxDepthChecks()->setGroups("poi");
$contextCategories = SerializationContext::create()->enableMaxDepthChecks()->setGroups("category");
$data = [ ['categories' => $this->serializer->toArray($categories, $contextCategories)],
['tours' => $this->serializer->toArray($tours, $contextTours)],
['pois' => $this->serializer->toArray($pois, $contextPois)],
];
return $data;
}
private function normalizeEntities($serializer, $entities, $relations)
{
$data = array_map(function ($entity) use ($serializer, $relations) {
$normalizedEntity = json_decode($serializer->serialize($entity, 'json'), true);
foreach ($relations as $relation) {
if (isset($normalizedEntity[$relation])) {
$normalizedEntity[$relation] = array_map(function ($relatedEntity) {
return $relatedEntity['id'];
}, $normalizedEntity[$relation]);
}
}
return $normalizedEntity;
}, $entities);
return $data;
}
#[Route('/api/{id}')]
public function getTour(EntityManagerInterface $entityManager, $id): Response
{
$tours = $entityManager->getRepository(Tour::class)->find($id);
return $this->json($tours);
}
}