wip: implement admin crud
This commit is contained in:
1 parent
306cd6bec4
commit
e902a5e298
78 files changed
+2555
-101
No files matched your search
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Groups\Accommodation;
|
||||
use App\Form\Admin\Groups\AccommodationType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use App\Repository\Groups\AccommodationRepository;
|
||||
use App\Service\CmsDataProvider;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class AccommodationController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AccommodationRepository $accommodationRepository,
|
||||
private readonly CmsDataProvider $cmsDataProvider,
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/accommodation', name: 'app_admin_accommodation')]
|
||||
public function index(): Response
|
||||
{
|
||||
$accommodations = $this->accommodationRepository->findAll();
|
||||
|
||||
return $this->render('admin/accommodation/index.html.twig', [
|
||||
'accommodations' => $accommodations,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/accommodation/create', name: 'app_admin_accommodation_create')]
|
||||
public function create(Request $request): Response
|
||||
{
|
||||
$accommodation = new Accommodation();
|
||||
|
||||
$form = $this->createForm(AccommodationType::class, $accommodation);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->persist($accommodation);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Das Gruppenhaus wurde angelegt');
|
||||
|
||||
$this->logger->info('Created accommodation', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_accommodation');
|
||||
}
|
||||
|
||||
return $this->render('admin/accommodation/create.html.twig', [
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/accommodation/{id}/edit', name: 'app_admin_accommodation_edit')]
|
||||
public function edit(Accommodation $accommodation, Request $request): Response
|
||||
{
|
||||
// fetch additional data from cms if available
|
||||
$cmsData = [];
|
||||
|
||||
if (null !== $accommodation->getCode()) {
|
||||
$cmsData = $this->cmsDataProvider->getHotelDetails($accommodation->getCode());
|
||||
}
|
||||
|
||||
$form = $this->createForm(AccommodationType::class, $accommodation);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->persist($accommodation);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Das Gruppenhaus wurde aktualisiert');
|
||||
|
||||
$this->logger->info('Updated accommodation', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_accommodation_edit', ['id' => $accommodation->getId()]);
|
||||
}
|
||||
|
||||
return $this->render('admin/accommodation/edit.html.twig', [
|
||||
'accommodation' => $accommodation,
|
||||
'form' => $form,
|
||||
'cmsData' => $cmsData,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/accommodation/{id}/delete', name: 'app_admin_accommodation_delete')]
|
||||
public function delete(Accommodation $accommodation, Request $request): Response
|
||||
{
|
||||
if (true === $request->isMethod(Request::METHOD_POST)) {
|
||||
$this->entityManager->remove($accommodation);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Das Gruppenhaus wurde gelöscht');
|
||||
|
||||
$this->logger->info('Deleted accommodation', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
]);
|
||||
|
||||
return new HxRedirectResponse($this->generateUrl('app_admin_accommodation'));
|
||||
}
|
||||
|
||||
return $this->render('admin/accommodation/modal_delete.html.twig', [
|
||||
'accommodation' => $accommodation,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Groups\Accommodation;
|
||||
use App\Entity\Groups\AccommodationPrice;
|
||||
use App\Form\Admin\Groups\AccommodationPriceType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class AccommodationPriceController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/accommodation-price/{id}/create', name: 'app_admin_accommodationprice_create')]
|
||||
public function create(Accommodation $accommodation, Request $request): Response
|
||||
{
|
||||
$accommodationPrice = new AccommodationPrice();
|
||||
|
||||
$form = $this->getForm($accommodationPrice, null);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$accommodation->addAccommodationPrice($accommodationPrice);
|
||||
|
||||
$this->entityManager->persist($accommodationPrice);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der Preis wurde angelegt');
|
||||
|
||||
$this->logger->info('Created accommodation price', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'date_range' => [
|
||||
'from' => $accommodationPrice->getDateFrom()->format('Y-m-d'),
|
||||
'to' => $accommodationPrice->getDateTo()->format('Y-m-d'),
|
||||
]
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('admin/accommodation_price/create.html.twig', [
|
||||
'accommodation' => $accommodation,
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/accommodation-price/{id}/edit', name: 'app_admin_accommodationprice_edit', defaults: ['duplicate' => false])]
|
||||
#[Route('/admin/accommodation-price/{id}/duplicate', name: 'app_admin_accommodationprice_duplicate', defaults: ['duplicate' => true])]
|
||||
public function edit(AccommodationPrice $accommodationPrice, bool $duplicate, Request $request): Response
|
||||
{
|
||||
$accommodation = $accommodationPrice->getAccommodation();
|
||||
|
||||
if (true === $duplicate) {
|
||||
$accommodationPrice = clone $accommodationPrice;
|
||||
}
|
||||
|
||||
$form = $this->getForm($accommodationPrice, $accommodation);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
if (true === $duplicate) {
|
||||
$accommodation->addAccommodationPrice($accommodationPrice);
|
||||
}
|
||||
|
||||
$this->entityManager->persist($accommodationPrice);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der Preis wurde aktualisiert');
|
||||
|
||||
$this->logger->info('Edited accommodation price', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'date_range' => [
|
||||
'from' => $accommodationPrice->getDateFrom()->format('Y-m-d'),
|
||||
'to' => $accommodationPrice->getDateTo()->format('Y-m-d'),
|
||||
]
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('admin/accommodation_price/edit.html.twig', [
|
||||
'accommodation' => $accommodation,
|
||||
'accommodationPrice' => $accommodationPrice,
|
||||
'form' => $form,
|
||||
'duplicate' => $duplicate,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/accommodation-price/{id}/delete', name: 'app_admin_accommodationprice_delete')]
|
||||
public function delete(AccommodationPrice $accommodationPrice, Request $request): Response
|
||||
{
|
||||
$accommodation = $accommodationPrice->getAccommodation();
|
||||
|
||||
if (true === $request->isMethod(Request::METHOD_POST)) {
|
||||
$this->entityManager->remove($accommodationPrice);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der Preis wurde gelöscht');
|
||||
|
||||
$this->logger->info('Deleted accommodation price', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'date_range' => [
|
||||
'from' => $accommodationPrice->getDateFrom()->format('Y-m-d'),
|
||||
'to' => $accommodationPrice->getDateTo()->format('Y-m-d'),
|
||||
]
|
||||
]);
|
||||
|
||||
$returnUrl = $this->generateUrl('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
|
||||
return new HxRedirectResponse($returnUrl);
|
||||
}
|
||||
|
||||
return $this->render('admin/accommodation_price/modal_delete.html.twig', [
|
||||
'accommodationPrice' => $accommodationPrice,
|
||||
'accommodation' => $accommodation,
|
||||
]);
|
||||
}
|
||||
|
||||
private function getForm(AccommodationPrice $accommodationPrice, ?Accommodation $accommodation): FormInterface
|
||||
{
|
||||
return $this->createForm(AccommodationPriceType::class, $accommodationPrice, ['currency' => $accommodation->getCurrency()]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Groups\Accommodation;
|
||||
use App\Entity\Groups\AdditionalService;
|
||||
use App\Form\Admin\Groups\AdditionalServiceType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class AdditionalServiceController extends AbstractController
|
||||
{
|
||||
use SortingControllerTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/additional-service/{id}/create', name: 'app_admin_additionalservice_create')]
|
||||
public function create(Accommodation $accommodation, Request $request): Response
|
||||
{
|
||||
$additionalService = new AdditionalService();
|
||||
|
||||
$form = $this->getForm($additionalService, $accommodation);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$accommodation->addAdditionalService($additionalService);
|
||||
|
||||
$this->entityManager->persist($additionalService);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Zusatzleistung wurde angelegt');
|
||||
|
||||
$this->logger->info('Created additional service', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'label' => $additionalService->getLabel(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('admin/additional_service/create.html.twig', [
|
||||
'accommodation' => $accommodation,
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/additional-service/{id}/edit', name: 'app_admin_additionalservice_edit', defaults: ['duplicate' => false])]
|
||||
#[Route('/admin/additional-service/{id}/duplicate', name: 'app_admin_additionalservice_duplicate', defaults: ['duplicate' => true])]
|
||||
public function edit(AdditionalService $additionalService, bool $duplicate, Request $request): Response
|
||||
{
|
||||
$accommodation = $additionalService->getAccommodation();
|
||||
|
||||
if (true === $duplicate) {
|
||||
$additionalService = clone $additionalService;
|
||||
}
|
||||
|
||||
$form = $this->getForm($additionalService, $accommodation);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
if (true === $duplicate) {
|
||||
$accommodation->addAdditionalService($additionalService);
|
||||
}
|
||||
|
||||
$this->entityManager->persist($additionalService);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Zusatzleistung wurde aktualisiert');
|
||||
|
||||
$this->logger->info('Edited additional service', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'label' => $additionalService->getLabel(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('admin/additional_service/edit.html.twig', [
|
||||
'accommodation' => $accommodation,
|
||||
'additionalService' => $additionalService,
|
||||
'form' => $form,
|
||||
'duplicate' => $duplicate,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/additional-service/{id}/delete', name: 'app_admin_additionalservice_delete')]
|
||||
public function delete(AdditionalService $additionalService, Request $request): Response
|
||||
{
|
||||
$accommodation = $additionalService->getAccommodation();
|
||||
|
||||
if (true === $request->isMethod(Request::METHOD_POST)) {
|
||||
$this->entityManager->remove($additionalService);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Zusatzleistung wurde gelöscht');
|
||||
|
||||
$this->logger->info('Deleted additional service', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'label' => $additionalService->getLabel(),
|
||||
]);
|
||||
|
||||
$returnUrl = $this->generateUrl('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
|
||||
return new HxRedirectResponse($returnUrl);
|
||||
}
|
||||
|
||||
return $this->render('admin/additional_service/modal_delete.html.twig', [
|
||||
'additionalService' => $additionalService,
|
||||
'accommodation' => $accommodation,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/additional-service/sort/{id}', name: 'app_admin_additionalservice_sort', methods: ['POST'])]
|
||||
public function sort(Accommodation $accommodation, Request $request): Response
|
||||
{
|
||||
$this->applySorting($accommodation->getAdditionalServices(), $request->request->all('sorting'));
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new Response('', Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
private function getForm(AdditionalService $additionalService, ?Accommodation $accommodation): FormInterface
|
||||
{
|
||||
return $this->createForm(AdditionalServiceType::class, $additionalService, ['currency' => $accommodation->getCurrency()]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Groups\Accommodation;
|
||||
use App\Entity\Groups\BoardService;
|
||||
use App\Form\Admin\Groups\BoardServiceType;
|
||||
use App\Htmx\HxRedirectResponse;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class BoardServiceController extends AbstractController
|
||||
{
|
||||
use SortingControllerTrait;
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger,
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/board-service/{id}/create', name: 'app_admin_boardservice_create')]
|
||||
public function create(Accommodation $accommodation, Request $request): Response
|
||||
{
|
||||
$boardService = new BoardService();
|
||||
|
||||
$form = $this->getForm($boardService, $accommodation);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$accommodation->addBoardService($boardService);
|
||||
|
||||
$this->entityManager->persist($boardService);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Verpflegungsleistung wurde angelegt');
|
||||
|
||||
$this->logger->info('Created board service', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'label' => $boardService->getLabel(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('admin/board_service/create.html.twig', [
|
||||
'accommodation' => $accommodation,
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/board-service/{id}/edit', name: 'app_admin_boardservice_edit', defaults: ['duplicate' => false])]
|
||||
#[Route('/admin/board-service/{id}/duplicate', name: 'app_admin_boardservice_duplicate', defaults: ['duplicate' => true])]
|
||||
public function edit(BoardService $boardService, bool $duplicate, Request $request): Response
|
||||
{
|
||||
$accommodation = $boardService->getAccommodation();
|
||||
|
||||
if (true === $duplicate) {
|
||||
$boardService = clone $boardService;
|
||||
}
|
||||
|
||||
$form = $this->getForm($boardService, $accommodation);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
if (true === $duplicate) {
|
||||
$accommodation->addBoardService($boardService);
|
||||
}
|
||||
|
||||
$this->entityManager->persist($boardService);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Verpflegungsleistung wurde aktualisiert');
|
||||
|
||||
$this->logger->info('Edited board service', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'label' => $boardService->getLabel(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render('admin/board_service/edit.html.twig', [
|
||||
'accommodation' => $accommodation,
|
||||
'boardService' => $boardService,
|
||||
'form' => $form,
|
||||
'duplicate' => $duplicate,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/board-service/{id}/delete', name: 'app_admin_boardservice_delete')]
|
||||
public function delete(BoardService $boardService, Request $request): Response
|
||||
{
|
||||
$accommodation = $boardService->getAccommodation();
|
||||
|
||||
if (true === $request->isMethod(Request::METHOD_POST)) {
|
||||
$this->entityManager->remove($boardService);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Verpflegungsleistung wurde gelöscht');
|
||||
|
||||
$this->logger->info('Deleted board service', [
|
||||
'name' => $accommodation->getName(),
|
||||
'code' => $accommodation->getCode(),
|
||||
'label' => $boardService->getLabel(),
|
||||
]);
|
||||
|
||||
$returnUrl = $this->generateUrl('app_admin_accommodation_edit', [
|
||||
'id' => $accommodation->getId(),
|
||||
]);
|
||||
|
||||
return new HxRedirectResponse($returnUrl);
|
||||
}
|
||||
|
||||
return $this->render('admin/board_service/modal_delete.html.twig', [
|
||||
'boardService' => $boardService,
|
||||
'accommodation' => $accommodation,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/board-service/sort/{id}', name: 'app_admin_boardservice_sort', methods: ['POST'])]
|
||||
public function sort(Accommodation $accommodation, Request $request): Response
|
||||
{
|
||||
$this->applySorting($accommodation->getBoardServices(), $request->request->all('sorting'));
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new Response('', Response::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
private function getForm(BoardService $boardService, ?Accommodation $accommodation): FormInterface
|
||||
{
|
||||
return $this->createForm(BoardServiceType::class, $boardService, ['currency' => $accommodation->getCurrency()]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Groups\SortableEntityInterface;
|
||||
|
||||
trait SortingControllerTrait
|
||||
{
|
||||
private function applySorting(iterable $collection, array $sortingMap): void
|
||||
{
|
||||
foreach ($collection as $entity) {
|
||||
/** @var SortableEntityInterface $entity */
|
||||
if (isset($sortingMap[$entity->getId()])) {
|
||||
$entity->setSorting((int) $sortingMap[$entity->getId()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use App\Repository\Groups\AccommodationRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
#[ORM\Entity(repositoryClass: AccommodationRepository::class)]
|
||||
class Accommodation implements BlameableEntityInterface, TimestampableEntityInterface
|
||||
@@ -23,36 +24,45 @@ class Accommodation implements BlameableEntityInterface, TimestampableEntityInte
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
#[Assert\NotBlank(message: 'required')]
|
||||
private ?string $name = null;
|
||||
|
||||
#[ORM\Column(length: 16, unique: true)]
|
||||
#[Assert\NotBlank(message: 'required')]
|
||||
private ?string $code = null;
|
||||
|
||||
#[ORM\Column]
|
||||
#[Assert\NotNull(message: 'required')]
|
||||
private ?int $minPaxSummer = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, AccommodationPrice>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: AccommodationPrice::class, mappedBy: 'accommodation')]
|
||||
#[ORM\OneToMany(targetEntity: AccommodationPrice::class, mappedBy: 'accommodation', cascade: ['all'])]
|
||||
#[ORM\OrderBy(['dateFrom' => 'ASC'])]
|
||||
private Collection $accommodationPrices;
|
||||
|
||||
/**
|
||||
* @var Collection<int, BoardService>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: BoardService::class, mappedBy: 'accommodation')]
|
||||
#[ORM\OneToMany(targetEntity: BoardService::class, mappedBy: 'accommodation', cascade: ['all'])]
|
||||
#[ORM\OrderBy(['sorting' => 'ASC'])]
|
||||
private Collection $boardServices;
|
||||
|
||||
/**
|
||||
* @var Collection<int, AdditionalService>
|
||||
*/
|
||||
#[ORM\OneToMany(targetEntity: AdditionalService::class, mappedBy: 'accommodation')]
|
||||
#[ORM\OneToMany(targetEntity: AdditionalService::class, mappedBy: 'accommodation', cascade: ['all'])]
|
||||
#[ORM\OrderBy(['sorting' => 'ASC'])]
|
||||
private Collection $additionalServices;
|
||||
|
||||
#[ORM\Column]
|
||||
#[Assert\NotNull(message: 'required')]
|
||||
private ?int $maxAdolescentAge = null;
|
||||
|
||||
#[ORM\Column(length: 3)]
|
||||
#[Assert\NotBlank(message: 'required')]
|
||||
#[Assert\Choice(choices: ['EUR', 'CHF'], message: 'invalid')]
|
||||
private ?string $currency = 'EUR';
|
||||
|
||||
public function __construct()
|
||||
|
||||
@@ -9,6 +9,8 @@ use App\Entity\TimestampableEntityInterface;
|
||||
use App\Repository\Groups\AccommodationPriceRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
#[ORM\Entity(repositoryClass: AccommodationPriceRepository::class)]
|
||||
class AccommodationPrice implements BlameableEntityInterface, TimestampableEntityInterface
|
||||
@@ -26,23 +28,44 @@ class AccommodationPrice implements BlameableEntityInterface, TimestampableEntit
|
||||
private ?Accommodation $accommodation = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
||||
#[Assert\NotNull(message: 'required')]
|
||||
private ?\DateTimeImmutable $dateFrom = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
||||
#[Assert\NotNull(message: 'required')]
|
||||
#[Assert\GreaterThan(propertyPath: 'dateFrom', message: 'Das Bis-Datum muss nach dem Von-Datum liegen')]
|
||||
private ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
#[ORM\Column]
|
||||
#[Assert\NotNull(message: 'required')]
|
||||
private ?int $includedPax = null;
|
||||
|
||||
#[ORM\Column]
|
||||
#[Assert\NotNull(message: 'required')]
|
||||
private ?int $pricePerNight = null;
|
||||
|
||||
#[ORM\Column]
|
||||
#[Assert\NotNull(message: 'required')]
|
||||
private ?int $priceAdditionalPerson = null;
|
||||
|
||||
#[ORM\Column]
|
||||
#[Assert\NotNull(message: 'required')]
|
||||
private ?int $minNights = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?int $pricePerNightOverride = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?int $priceAdditionalPersonOverride = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private bool $acceptUndersubscription = false;
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->id = null;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@@ -131,4 +154,71 @@ class AccommodationPrice implements BlameableEntityInterface, TimestampableEntit
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPricePerNightOverride(): ?int
|
||||
{
|
||||
return $this->pricePerNightOverride;
|
||||
}
|
||||
|
||||
public function setPricePerNightOverride(?int $pricePerNightOverride): self
|
||||
{
|
||||
$this->pricePerNightOverride = $pricePerNightOverride;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEffectivePricePerNight(): int
|
||||
{
|
||||
return $this->pricePerNightOverride ?? $this->pricePerNight;
|
||||
}
|
||||
|
||||
public function getPriceAdditionalPersonOverride(): ?int
|
||||
{
|
||||
return $this->priceAdditionalPersonOverride;
|
||||
}
|
||||
|
||||
public function setPriceAdditionalPersonOverride(?int $priceAdditionalPersonOverride): self
|
||||
{
|
||||
$this->priceAdditionalPersonOverride = $priceAdditionalPersonOverride;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEffectivePriceAdditionalPerson(): int
|
||||
{
|
||||
return $this->priceAdditionalPersonOverride ?? $this->priceAdditionalPerson;
|
||||
}
|
||||
|
||||
public function isAcceptUndersubscription(): bool
|
||||
{
|
||||
return $this->acceptUndersubscription;
|
||||
}
|
||||
|
||||
public function setAcceptUndersubscription(bool $acceptUndersubscription): self
|
||||
{
|
||||
$this->acceptUndersubscription = $acceptUndersubscription;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
#[Assert\Callback]
|
||||
public function assertDatesValid(ExecutionContextInterface $context): void
|
||||
{
|
||||
// we only check new entities
|
||||
if (null !== $this->getId()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// come on, we need something to work with
|
||||
if (null === $this->getDateFrom() || null === $this->getDateTo()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->getDateFrom() < new \DateTimeImmutable()) {
|
||||
$context
|
||||
->buildViolation('Das Von-Datum darf nicht in der Vergangenheit liegen')
|
||||
->atPath('dateFrom')
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: AdditionalServiceRepository::class)]
|
||||
class AdditionalService implements BlameableEntityInterface, TimestampableEntityInterface
|
||||
class AdditionalService implements BlameableEntityInterface, TimestampableEntityInterface, SortableEntityInterface
|
||||
{
|
||||
use BlameableEntity;
|
||||
use TimestampableEntity;
|
||||
@@ -41,12 +41,17 @@ class AdditionalService implements BlameableEntityInterface, TimestampableEntity
|
||||
#[ORM\Column(type: Types::DATE_IMMUTABLE)]
|
||||
private ?\DateTimeImmutable $dateTo = null;
|
||||
|
||||
#[ORM\Column(length: 128)]
|
||||
private ?string $grouping = null;
|
||||
#[ORM\Column(length: 128, nullable: true)]
|
||||
private ?string $selectionGroup = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?int $sorting = 0;
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->id = null;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@@ -124,14 +129,14 @@ class AdditionalService implements BlameableEntityInterface, TimestampableEntity
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGrouping(): ?string
|
||||
public function getSelectionGroup(): ?string
|
||||
{
|
||||
return $this->grouping;
|
||||
return $this->selectionGroup;
|
||||
}
|
||||
|
||||
public function setGrouping(?string $grouping): self
|
||||
public function setSelectionGroup(?string $selectionGroup): self
|
||||
{
|
||||
$this->grouping = $grouping;
|
||||
$this->selectionGroup = $selectionGroup;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: BoardServiceRepository::class)]
|
||||
class BoardService implements BlameableEntityInterface, TimestampableEntityInterface
|
||||
class BoardService implements BlameableEntityInterface, TimestampableEntityInterface, SortableEntityInterface
|
||||
{
|
||||
use BlameableEntity;
|
||||
use TimestampableEntity;
|
||||
@@ -40,6 +40,11 @@ class BoardService implements BlameableEntityInterface, TimestampableEntityInter
|
||||
#[ORM\Column]
|
||||
private ?int $sorting = 0;
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->id = null;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity\Groups;
|
||||
|
||||
interface SortableEntityInterface
|
||||
{
|
||||
public function getId(): ?int;
|
||||
|
||||
public function setSorting(?int $sorting): self;
|
||||
}
|
||||
@@ -8,4 +8,9 @@ enum AdditionalServiceType: string
|
||||
case PerPerson = 'per_person';
|
||||
case PerNight = 'per_night';
|
||||
case PerPersonPerNight = 'per_person_per_night';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return 'enum.additional_service.'.$this->value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form\Admin\Groups;
|
||||
|
||||
use App\Entity\Groups\AccommodationPrice;
|
||||
use App\Form\DatepickerType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class AccommodationPriceType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('dateFrom', DatepickerType::class, [
|
||||
'label' => 'Datum von',
|
||||
'html5' => true,
|
||||
'widget' => 'single_text',
|
||||
])
|
||||
->add('dateTo', DatepickerType::class, [
|
||||
'label' => 'Datum bis',
|
||||
'html5' => true,
|
||||
'widget' => 'single_text',
|
||||
])
|
||||
->add('includedPax', IntegerType::class, [
|
||||
'label' => 'Inklusiv-Personen',
|
||||
])
|
||||
->add('minNights', IntegerType::class, [
|
||||
'label' => 'Mindestbelegung (Nächte)',
|
||||
])
|
||||
->add('pricePerNight', MoneyType::class, [
|
||||
'label' => 'Preis pro Nacht',
|
||||
'currency' => $options['currency'],
|
||||
'divisor' => 100,
|
||||
])
|
||||
->add('pricePerNightOverride', MoneyType::class, [
|
||||
'label' => 'Streich-Preis pro Nacht',
|
||||
'required' => false,
|
||||
'currency' => $options['currency'],
|
||||
'divisor' => 100,
|
||||
])
|
||||
->add('priceAdditionalPerson', MoneyType::class, [
|
||||
'label' => 'Preis weitere Person',
|
||||
'currency' => $options['currency'],
|
||||
'divisor' => 100,
|
||||
])
|
||||
->add('priceAdditionalPersonOverride', MoneyType::class, [
|
||||
'label' => 'Streich-Preis weitere Person',
|
||||
'required' => false,
|
||||
'currency' => $options['currency'],
|
||||
'divisor' => 100,
|
||||
])
|
||||
->add('acceptUndersubscription', CheckboxType::class, [
|
||||
'label' => 'Unterbelegung akzeptieren',
|
||||
'required' => false,
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => AccommodationPrice::class,
|
||||
'currency' => 'EUR',
|
||||
]);
|
||||
$resolver->setAllowedValues('currency', ['EUR', 'CHF']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form\Admin\Groups;
|
||||
|
||||
use App\Entity\Groups\Accommodation;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class AccommodationType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('name', TextType::class, [
|
||||
'label' => 'Name',
|
||||
])
|
||||
->add('code', TextType::class, [
|
||||
'label' => 'Code',
|
||||
])
|
||||
->add('minPaxSummer', IntegerType::class, [
|
||||
'label' => 'Mindestbelegung Sommer',
|
||||
])
|
||||
->add('maxAdolescentAge', IntegerType::class, [
|
||||
'label' => 'Altersgrenze Jugendliche (6-X Jahre)',
|
||||
])
|
||||
->add('currency', ChoiceType::class, [
|
||||
'label' => 'Währung',
|
||||
'choices' => [
|
||||
'EUR' => 'EUR',
|
||||
'CHF' => 'CHF',
|
||||
],
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Accommodation::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form\Admin\Groups;
|
||||
|
||||
use App\Entity\Groups\AdditionalService;
|
||||
use App\Enum\Groups\AdditionalServiceType as AdditionalServiceTypeEnum;
|
||||
use App\Form\DatepickerType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EnumType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class AdditionalServiceType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('label', TextType::class, [
|
||||
'label' => 'Bezeichnung',
|
||||
])
|
||||
->add('type', EnumType::class, [
|
||||
'label' => 'Preistyp',
|
||||
'class' => AdditionalServiceTypeEnum::class,
|
||||
'choice_label' => fn($item) => $item->label(),
|
||||
])
|
||||
->add('price', MoneyType::class, [
|
||||
'label' => 'Preis',
|
||||
'currency' => $options['currency'],
|
||||
'divisor' => 100,
|
||||
])
|
||||
->add('selectionGroup', TextType::class, [
|
||||
'label' => 'Auswahlgruppe',
|
||||
'required' => false,
|
||||
])
|
||||
->add('dateFrom', DatepickerType::class, [
|
||||
'label' => 'Datum von',
|
||||
'html5' => true,
|
||||
'widget' => 'single_text',
|
||||
])
|
||||
->add('dateTo', DatepickerType::class, [
|
||||
'label' => 'Datum bis',
|
||||
'html5' => true,
|
||||
'widget' => 'single_text',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => AdditionalService::class,
|
||||
'currency' => 'EUR',
|
||||
]);
|
||||
$resolver->setAllowedValues('currency', ['EUR', 'CHF']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Form\Admin\Groups;
|
||||
|
||||
use App\Entity\Groups\BoardService;
|
||||
use App\Form\DatepickerType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class BoardServiceType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('label', TextType::class, [
|
||||
'label' => 'Bezeichnung',
|
||||
])
|
||||
->add('price', MoneyType::class, [
|
||||
'label' => 'Preis pro Person/Nacht',
|
||||
'currency' => $options['currency'],
|
||||
'divisor' => 100,
|
||||
])
|
||||
->add('dateFrom', DatepickerType::class, [
|
||||
'label' => 'Datum von',
|
||||
'html5' => true,
|
||||
'widget' => 'single_text',
|
||||
])
|
||||
->add('dateTo', DatepickerType::class, [
|
||||
'label' => 'Datum bis',
|
||||
'html5' => true,
|
||||
'widget' => 'single_text',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => BoardService::class,
|
||||
'currency' => 'EUR',
|
||||
]);
|
||||
$resolver->setAllowedValues('currency', ['EUR', 'CHF']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\DateType;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class DatepickerType extends AbstractType
|
||||
{
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'html5' => false,
|
||||
'widget' => 'single_text',
|
||||
'input' => 'datetime_immutable',
|
||||
'min_date' => null,
|
||||
'max_date' => null,
|
||||
'disable_weekends' => false,
|
||||
]);
|
||||
$resolver->setAllowedTypes('min_date', ['null', \DateTimeImmutable::class]);
|
||||
$resolver->setAllowedTypes('max_date', ['null', \DateTimeImmutable::class]);
|
||||
$resolver->setAllowedTypes('disable_weekends', 'bool');
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
$view->vars['min_date'] = $options['min_date'];
|
||||
$view->vars['max_date'] = $options['max_date'];
|
||||
$view->vars['disable_weekends'] = $options['disable_weekends'];
|
||||
}
|
||||
|
||||
public function getParent(): string
|
||||
{
|
||||
return DateType::class;
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
],
|
||||
'extras' => [
|
||||
'icon' => 'edit',
|
||||
'routes' => [['pattern' => '/^app_admin_bookingeditdraft/']],
|
||||
],
|
||||
]);
|
||||
$menu->addChild('Benutzer', [
|
||||
@@ -40,6 +41,16 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
'icon' => 'users',
|
||||
],
|
||||
]);
|
||||
$menu->addChild('Gruppenhäuser', [
|
||||
'route' => 'app_admin_accommodation',
|
||||
'linkAttributes' => [
|
||||
'title' => 'Gruppenhäuser',
|
||||
],
|
||||
'extras' => [
|
||||
'icon' => 'house',
|
||||
'routes' => [['pattern' => '/^app_admin_accommodation/']],
|
||||
],
|
||||
]);
|
||||
$menu->addChild('Logs', [
|
||||
'route' => 'app_admin_log',
|
||||
'linkAttributes' => [
|
||||
@@ -47,6 +58,7 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
],
|
||||
'extras' => [
|
||||
'icon' => 'list',
|
||||
'routes' => [['pattern' => '/^app_admin_log/']],
|
||||
],
|
||||
]);
|
||||
|
||||
|
||||
@@ -2,13 +2,18 @@
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class CmsDataProvider
|
||||
{
|
||||
public function __construct(private readonly HttpClientInterface $httpClient, private readonly string $apiKey)
|
||||
{
|
||||
public function __construct(
|
||||
private readonly HttpClientInterface $httpClient,
|
||||
private readonly CacheInterface $cache,
|
||||
private readonly string $apiKey,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,33 +32,98 @@ class CmsDataProvider
|
||||
return $result['hotel']['images'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function getHotelImages(string $hotelCode): ?array
|
||||
{
|
||||
$result = $this->getHotelDetails($hotelCode);
|
||||
|
||||
if (true === isset($result['success']) && false === $result['success']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $result['images'] ?? null;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function getHotelDetails(string $hotelCode): array
|
||||
{
|
||||
return $this->cache->get(
|
||||
sprintf('cms_hotel_%s', $hotelCode),
|
||||
function (ItemInterface $item) use ($hotelCode): array {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
try {
|
||||
$request = $this->httpClient->request('GET', 'api/hotel', [
|
||||
'query' => [
|
||||
'hotel' => $hotelCode,
|
||||
'key' => $this->apiKey,
|
||||
],
|
||||
]);
|
||||
} catch (ExceptionInterface $e) {
|
||||
$item->expiresAfter(0);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
$data = $request->toArray();
|
||||
} catch (ExceptionInterface $e) {
|
||||
$item->expiresAfter(0);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function getProductDetails(string $productCode, ?string $hotelCode = null): array
|
||||
{
|
||||
try {
|
||||
$request = $this->httpClient->request('GET', 'api/product', [
|
||||
'query' => [
|
||||
'product' => $productCode,
|
||||
'hotel' => $hotelCode,
|
||||
'key' => $this->apiKey,
|
||||
],
|
||||
]);
|
||||
} catch (ExceptionInterface $e) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
return $this->cache->get(
|
||||
sprintf('cms_product_%s_%s', $productCode, $hotelCode ?? ''),
|
||||
function (ItemInterface $item) use ($productCode, $hotelCode): array {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
try {
|
||||
$data = $request->toArray();
|
||||
} catch (ExceptionInterface $e) {
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
try {
|
||||
$request = $this->httpClient->request('GET', 'api/product', [
|
||||
'query' => [
|
||||
'product' => $productCode,
|
||||
'hotel' => $hotelCode,
|
||||
'key' => $this->apiKey,
|
||||
],
|
||||
]);
|
||||
} catch (ExceptionInterface $e) {
|
||||
$item->expiresAfter(0);
|
||||
|
||||
return $data;
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
try {
|
||||
$data = $request->toArray();
|
||||
} catch (ExceptionInterface $e) {
|
||||
$item->expiresAfter(0);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user