<?php
declare(strict_types=1);
namespace App\Controller\V1;
use App\Entity\Local\CinemaAreaCategory;
use App\Entity\Local\Response\CinemasWithMoviesItem;
use App\Entity\Vista\Cinema;
use App\Entity\Vista\Session;
use App\Helper\SessionHelper;
use App\Helper\UserHelper;
use App\Repository\CinemaAreaCategoryRepository;
use App\Repository\CinemaRepository;
use App\Repository\LocationRepository;
use App\Repository\MovieRepositoryInterface as MovieRepository;
use App\Repository\RestrictionsRepository;
use App\Repository\SeatPlanRepository;
use App\Repository\TicketRepository;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\View;
use Nelmio\ApiDocBundle\Annotation\Model;
use Swagger\Annotations as SWG;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Repository\SessionRepositoryInterface as SessionRepository;
use App\Repository\SeatPlanLocalRepository;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* @Route("/cinemas")
* @SWG\Tag(name="Cinema_v1")
*/
class CinemaController extends BaseCinemaController
{
/** @var TicketRepository */
protected $ticketRepository;
/** @var UserHelper */
protected $userHelper;
/** @var CinemaAreaCategoryRepository */
protected $areaCategoryRepository;
/** @var SeatPlanRepository */
protected $seatPlanRepository;
/** @var RestrictionsRepository */
protected $restrictionsRepository;
/** @var SessionRepository */
private $sessionRepository;
/** @var SeatPlanLocalRepository */
protected $seatPlanLocalRepository;
public function __construct(
SessionRepository $sessionRepository,
CinemaRepository $cinemaRepository,
MovieRepository $movieRepository,
SessionHelper $sessionHelper,
LocationRepository $locationRepository,
CinemaAreaCategoryRepository $areaCategoryRepository,
SeatPlanRepository $seatPlanRepository,
UserHelper $userHelper,
RestrictionsRepository $restrictionsRepository,
SeatPlanLocalRepository $seatPlanLocalRepository,
TicketRepository $ticketRepository
) {
parent::__construct($locationRepository, $cinemaRepository, $movieRepository, $sessionHelper);
$this->sessionRepository = $sessionRepository;
$this->userHelper = $userHelper;
$this->areaCategoryRepository = $areaCategoryRepository;
$this->seatPlanRepository = $seatPlanRepository;
$this->restrictionsRepository = $restrictionsRepository;
$this->seatPlanLocalRepository = $seatPlanLocalRepository;
$this->ticketRepository = $ticketRepository;
}
/**
* @Route("", methods="GET")
* @Rest\QueryParam(name="filter", allowBlank=true)
* @Rest\QueryParam(name="order", allowBlank=true)
* @Rest\QueryParam(name="limit", default="0", requirements="\d+", allowBlank=true)
* @Rest\QueryParam(name="offset", default="0", requirements="\d+", allowBlank=true)
* @Rest\QueryParam(name="location", requirements="\d+", allowBlank=true)
* @View(serializerGroups={"Default", "cinema_list"})
*
* @SWG\Parameter(name="filter", type="string", in="query")
* @SWG\Parameter(name="order", type="string", in="query")
*
* @SWG\Response(
* response="200",
* description="Returns a list of cinemas",
* @SWG\Schema(type="array", items=@SWG\Items(ref=@Model(type=\App\Entity\Vista\Cinema::class))))
*
* @param array $filter
* @param array $order
* @param int $limit
* @param int $offset
* @param int $location
*
* @return Cinema[]
*/
public function indexAction($filter = [], $order = [], $limit = null, $offset = null, $location = null)
{
$filter or $filter = [];
if (is_numeric($location)) {
$filter['id'] = $this->locationRepository->findById($location)->getItems();
} else {
$filter['id'] = $this->locationRepository->findLocationIds();
}
$cinemas = $this->cinemaRepository->findBy($filter, $order ?: [], $limit ?: null, $offset ?: null);
$response = [];
foreach ($cinemas as $cinema) {
$response[] = $this->prepareCinema($cinema);
}
return $response;
}
/**
* @Route("/with-movies", methods={"GET"})
* @Rest\QueryParam(name="locationId", allowBlank=true, nullable=true)
* @Rest\QueryParam(name="date", allowBlank=true)
* @Rest\QueryParam(name="order", allowBlank=true)
* @View(serializerGroups={"Default", "cinema_list"})
*
* @SWG\Response(
* response="200",
* description="Returns a list of cinemas",
* @SWG\Schema(type="array", items=@SWG\Items(ref=@Model(type=\App\Entity\Local\Response\CinemasWithMoviesItem::class))))
*
* @param int|null $locationId
* @param \DateTime|null $date
* @return array
* @throws \Exception
*/
public function cinemasWithMoviesAction($locationId = null, ?\DateTime $date = null)
{
if (!is_numeric($locationId)) {
$locationId = null;
} else {
$locationId = (int) $locationId;
}
$filter = [];
if (null !== $locationId) {
$filter['id'] = $this->locationRepository->findById($locationId)->getItems();
} else {
$filter['id'] = $this->locationRepository->findLocationIds();
}
$defaultDate = $this->sessionHelper->getDefaultDate(null, $locationId);
if (!$date) {
$date = $defaultDate;
} elseif ($date < $defaultDate) {
$date = $defaultDate;
}
return $this->prepareResponse($this->getCinemasWithMovies('CELL', $filter, $date));
}
/**
* @Route("/{id}", methods={"GET"})
* @View(serializerGroups={"Default", "cinema_details"})
*
* @SWG\Response(
* response="200",
* description="Get cinema by id",
* @Model(type=\App\Entity\Vista\Cinema::class))
* @SWG\Response(
* response="404",
* description="Cinema not found")
*
* @param $id
* @return array
*/
public function showAction($id): array
{
return $this->prepareCinema($this->getCinema($id));
}
/**
* @Route("/{id}/price-list", methods={"GET"})
* @View()
*
* @SWG\Response(
* response="200",
* description="Get cinema price list by id",
* @Model(type=\App\Entity\Vista\Cinema::class))
* @SWG\Response(
* response="404",
* description="Cinema not found")
*
* @param string $id
*
* @return Response
*/
public function priceListAction(string $id): Response
{
/** @var Cinema $cinema */
if (!$cinema = $this->cinemaRepository->find($id)) {
throw new NotFoundHttpException();
}
$response = new Response($cinema->getInfo() ?? '');
$response->headers->set('Content-type', 'text/html');
return $response;
}
/**
* @Route("/{id}/movies", methods={"GET"})
* @Rest\QueryParam(name="date", allowBlank=true)
* @View(serializerGroups={"Default", "movie_details"})
*
* @SWG\Response(
* response="200",
* description="Get upcoming movies list by cinema id",
* @SWG\Schema(type="array", items=@SWG\Items(ref=@Model(type=\App\Entity\Vista\ScheduledFilm::class))))
* @SWG\Response(
* response="404",
* description="Cinema not found")
*
* @param $id
* @param \DateTime|null $date
* @return array
* @throws \Exception
*/
public function moviesAction($id, ?\DateTime $date = null)
{
$cinema = $this->getCinema($id);
$defaultDate = $this->sessionHelper->getDefaultDate([$cinema->getId()]);
if (!$date || ($date < $defaultDate)) {
$date = $defaultDate;
}
$response = $this->prepareMoviesResponse(
$this->movieRepository->findByCinemaIdAndDate($cinema->getId(), $date)
);
return $this->filterSessionByType($response, 'CELL');
}
/**
* @Route("/{id}/sessions", methods={"GET"})
* @Rest\QueryParam(name="filter", allowBlank=true)
* @Rest\QueryParam(name="order", allowBlank=true)
* @Rest\QueryParam(name="limit", requirements="\d+", allowBlank=true, strict=true, nullable=true)
* @Rest\QueryParam(name="offset", requirements="\d+", allowBlank=true, strict=true, nullable=true)
* @Rest\QueryParam(name="location", requirements="\d+", allowBlank=true, strict=true, nullable=true)
* @Rest\QueryParam(name="date", allowBlank=true)
* @Rest\View(serializerGroups={"Default", "session_details"})
*
* @SWG\Parameter(name="filter", type="string", in="query")
* @SWG\Parameter(name="order", type="string", in="query")
*
* @SWG\Response(
* response="200",
* description="Get list of sessions by movie id",
* @SWG\Schema(type="array", items=@SWG\Items(ref=@Model(type=\App\Entity\Vista\Session::class))))
* @SWG\Response(
* response="404",
* description="Cinema not found")
*
* @param int|string $id
* @param array $filter
* @param array $order
* @param int|null $limit
* @param int|null $offset
* @param \DateTime|null $date
*
* @return Session[]|array
* @throws \Exception
*/
public function sessionsAction(
$id,
$filter = [],
$order = [],
?int $limit = null,
?int $offset = null,
?\DateTime $date = null
) {
$filter or $filter = [];
$cinema = $this->getCinema($id);
$filter['cinemaId'] = $cinema->getId();
if ($date) {
$filter['>=showtime'] = $date->setTime(0, 0, 0);
$filter['<=showtime'] = (clone $date)->add(new \DateInterval('P1D'));
}
return $this->prepareSessionsResponse($this->sessionHelper->findBy(
$filter ?: [],
$order ?: null,
$limit,
$offset
));
}
/**
* @Route("/{cinemaId}/sessions/{sessionId}/tickets", methods={"GET"})
* @View()
*
* @SWG\Response(
* response="200",
* description="Get available tickets by cinema id and session id",
* @SWG\Schema(type="array", items=@SWG\Items(ref=@Model(type=\App\Entity\Vista\SessionTicketType::class))))
*
* @param $cinemaId
* @param $sessionId
* @return \App\Entity\Vista\SessionTicketType[]
*/
public function sessionsTicketsAction($cinemaId, $sessionId)
{
return $this->ticketRepository->findByCinemaIdSessionId($cinemaId, $sessionId);
}
/**
* @Route("/{cinemaId}/sessions/{sessionId}/area-categories", methods={"GET"})
* @View()
*
* @SWG\Response(
* response="200",
* description="Success",
* @SWG\Schema(type="array", items=@SWG\Items(ref=@Model(type=\App\Entity\Local\CinemaAreaCategory::class))))
*
* @param string $cinemaId
* @param string $sessionId
* @return CinemaAreaCategory[]
*/
public function areaCategoriesAction(string $cinemaId, string $sessionId)
{
$categories = array_values($this->areaCategoryRepository->find($cinemaId) ?: []);
[, $seatPlanRows] = $this->seatPlanRepository->getSeatPlan($cinemaId, $sessionId, $categories);
return $this->areaCategoryRepository->filterBySeatPlan($categories, $seatPlanRows);
}
/**
* @Route("/list/short", methods="GET")
* @View(serializerGroups={"Default", "cinema_list_short"})
*
* @SWG\Response(response="200",
* description="Success")
* @SWG\Response(
* response="404",
* description="Cinema not found")
*
* @return Response
*/
public function allCinemaList() {
$filter = ['id' => $this->locationRepository->findLocationIds()];
$cinemas = $this->cinemaRepository->findBy($filter, ['name' => 'ASC']);
$json = '';
foreach ($cinemas as $cinema) {
if ($json) { $json .= ','; }
$json .= "{\"id\":\"{$cinema->getId()}\",\"name\":\"{$cinema->getName()}\"}";
}
$response = new Response("[$json]");
$response->headers->set('Content-Type', 'application/json; charset=UTF-8');
return $response;
}
/**
* @Route("/halls/{cinemaId}", methods="GET")
* @View()
*
* @SWG\Response(response=200,
* description="Success")
* @SWG\Response(
* response="404",
* description="Cinema not found")
*
* @param string $cinemaId
* @return Response
*/
public function getSavedCinemaHalls(string $cinemaId) {
$sessions = $this->sessionRepository->findScreens($cinemaId);
//error_log(sprintf("%s %s(%s) ", date('Y-m-d H:i:s'), __METHOD__, __LINE__) . ' sessions ' . var_export($sessions, true));
$json = '';
if ($sessions) {
$seatPlanCinemaHalls = $this->seatPlanLocalRepository->findBy(['cinemaId' => $cinemaId], ['screenNumber' => 'ASC']);
$halls = [];
foreach($seatPlanCinemaHalls as $hall) {
$halls[$hall->getScreenNumber()] = null;
}
foreach ($sessions as $session) { // $session->getShowtime()
if ($json) { $json .= ','; }
$seatPlanSaved = array_key_exists($session['screenNumber'], $halls) ? 1 : 0;
$json .= "{\"cinemaId\":\"{$session['cinemaId']}\",\"screenNumber\":\"{$session['screenNumber']}\",\"screenName\":\"{$session['screenName']}\",\"seatPlanSaved\":\"$seatPlanSaved\"}";
}
}
$response = new Response("[$json]");
$response->headers->set('Content-Type', 'application/json; charset=UTF-8');
return $response;
}
}