src/Repository/SeatPlanRepository.php line 81

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Repository;
  4. use App\Entity\Local\CinemaAreaCategories;
  5. use App\Entity\Local\CinemaAreaCategory;
  6. use App\Entity\Vista\Area;
  7. use App\Entity\Vista\GetSessionSeatPlanResponse;
  8. use App\Entity\Vista\Row;
  9. use App\Entity\Vista\Theatre;
  10. use App\Exceptions\SeatPlanException;
  11. use App\Utils\SeatPlanIconsMatcher;
  12. use GuzzleHttp\Client;
  13. use Symfony\Component\Serializer\SerializerInterface;
  14. use App\Repository\Vista\SessionVistaRepository as SessionRepository;
  15. use App\Repository\SeatPlanLocalRepository;
  16. use Psr\Log\LoggerInterface;
  17. class SeatPlanRepository
  18. {
  19.     /**
  20.      * @var Client $vistaClient
  21.      */
  22.     protected $vistaClient;
  23.     /**
  24.      * @var SerializerInterface $serializer
  25.      */
  26.     protected $serializer;
  27.     /**
  28.      * @var SeatPlanIconsMatcher
  29.      */
  30.     public $matcher;
  31.     /** @var SessionRepository */
  32.     private $sessionRepository;
  33.     /** @var SeatPlanLocalRepository */
  34.     protected $seatPlanLocalRepository;
  35.     /** @var LoggerInterface */
  36.     private $logger;
  37.     public function __construct(Client $vistaClientSerializerInterface $serializer,
  38.         SeatPlanIconsMatcher $matcherSessionRepository $sessionRepository,
  39.         SeatPlanLocalRepository $seatPlanLocalRepositoryLoggerInterface $logger)
  40.     {
  41.         $this->vistaClient $vistaClient;
  42.         $this->serializer $serializer;
  43.         $this->matcher $matcher;
  44.         $this->sessionRepository $sessionRepository;
  45.         $this->seatPlanLocalRepository $seatPlanLocalRepository;
  46.         $this->logger $logger;
  47.     }
  48.     /**
  49.      * @param string                      $cinemaId
  50.      * @param string                      $sessionId
  51.      *
  52.      * @return string
  53.      */
  54.     public function getSeatPlanRaw(string $cinemaIdstring $sessionId)
  55.     {
  56.         $start microtime(true);
  57.         $response $this->vistaClient->get(sprintf('/WSVistaWebClient/RESTData.svc/cinemas/%s/sessions/%s/seat-plan'$cinemaId$sessionId));
  58.         $this->logger->info(sprintf("profiling vista call :: /WSVistaWebClient/RESTData.svc/cinemas/%s/sessions/%s/seat-plan execution time: %f",
  59.             $cinemaId$sessionIdmicrotime(true) - $start));
  60.         return $response->getBody()->getContents();        
  61.     }
  62.     /**
  63.      * @param string                      $cinemaId
  64.      * @param string                      $sessionId
  65.      * @param CinemaAreaCategories[]      $categories
  66.      *
  67.      * @return array
  68.      */
  69.     public function getSeatPlan(string $cinemaIdstring $sessionId, array $categories)
  70.     {
  71.         $seatPlanVista $this->getSeatPlanRaw($cinemaId$sessionId);
  72.         if ($session $this->sessionRepository->findOneBy(['sessionId' => $sessionId'cinemaId' => $cinemaId])) {
  73.             $screenNumber $session->getScreenNumber();
  74.             if ($seatPlanJson $this->seatPlanLocalRepository->findOneBy(['cinemaId' => $cinemaId'screenNumber' => $screenNumber])) {
  75.                 $seatPlanInput $seatPlanJson->getSeatPlanJson();
  76.             }
  77.         }
  78.         return $this->getSeatPlanResponse($seatPlanVista$categories);
  79.     }
  80.     public function getSeatPlanResponse(string $responseJson, array $categories)
  81.     {
  82.         /** @var GetSessionSeatPlanResponse $seatPlanResponse */
  83.         $seatPlanResponse $this->serializer->deserialize($responseJsonGetSessionSeatPlanResponse::class, 'json');
  84.         if ($seatPlanResponse->getErrorDescription() || !$seatPlanResponse->getValue() instanceof Theatre) {
  85.             throw new SeatPlanException($seatPlanResponse->getErrorDescription() ?? 'An unexpected error has occured. Please try again later');
  86.         }
  87.         return array_merge([$seatPlanResponse->getErrorDescription()], $this->convertSeatPlan($seatPlanResponse->getValue(), $categories));
  88.     }
  89.     /**
  90.      * Copy similar fields from area to row
  91.      *
  92.      * @param Row  $to
  93.      * @param Area $from
  94.      */
  95.     private function copyFieldsFromArea(Row $toArea $from)
  96.     {
  97.         $to->setAreaCategoryCode($from->getAreaCategoryCode())
  98.             ->setDescription($from->getDescription())
  99.             ->setRight($from->getRight())
  100.             ->setColumnCount($from->getColumnCount())
  101.             ->setNumber($from->getNumber());
  102.     }
  103.     /**
  104.      * Sort rows by bottom value (usort)
  105.      *
  106.      * @param Row $a
  107.      * @param Row $b
  108.      *
  109.      * @return int
  110.      */
  111.     public function sortByBottom(Row $aRow $b)
  112.     {
  113.         if ($a->getBottom() > $b->getBottom()) {
  114.             return -1;
  115.         } elseif ($a->getBottom() < $b->getBottom()) {
  116.             return 1;
  117.         }
  118.         return 0;
  119.     }
  120.     /**
  121.      * @param Theatre                     $seatPlan
  122.      * @param CinemaAreaCategories[]|null $categories
  123.      *
  124.      * @return array<int, array<Row>|int>
  125.      */
  126.     protected function convertSeatPlan(Theatre $seatPlan, array $categories)
  127.     {
  128.         /** @var Row[] $seatPlanRows */
  129.         $seatPlanRows = [];
  130.         $totalSeatsCount 0;
  131.         foreach ($seatPlan->getAreas() as $area) {
  132.             $totalSeatsCount += $area->getNumberOfSeats();
  133.             $areaRows = [];
  134.             $rowsList $area->getRows();
  135.             $rowsCount count($rowsList);
  136.             if (!($lastRow $rowsList array_values(array_reverse($rowsList))[0] : null)) {
  137.                 continue;
  138.             }
  139.             foreach ($rowsList as $rowIndex => $row) {
  140.                 $this->copyFieldsFromArea($row$area);
  141.                 $row->setHeight(round(floatval($area->getHeight()) / $area->getRowCount(), 3));
  142.                 $k $rowsCount $rowIndex 1;
  143.                 $row->setBottom(round(floatval($area->getBottom()) + $row->getHeight() * $k3));
  144.                 foreach ($row->getSeats() as $seat) {
  145.                     $seat->setAreaCategoryCode($row->getAreaCategoryCode());
  146.                     $seat->setRowRight($row->getRight());
  147.                     /** @var CinemaAreaCategory $category */
  148.                     if ($category $categories[intval($row->getAreaCategoryCode())] ?? []) {
  149.                         $categoryId $category $category->getAreaCategoryId() : -1;
  150.                         $seat->setSeatIconId($this->matcher->getIconId($seat$categoryId));
  151.                         $seat->setSeatImprovedIconId($this->matcher->getImprovedIconId($seat$categoryId));
  152.                     }
  153.                 }
  154.                 $areaRows[] = $row;
  155.             }
  156.             $areaRows $this->trimFirstEmptyRows($areaRows);
  157.             $areaRows array_reverse($areaRows);
  158.             $areaRows $this->trimFirstEmptyRows($areaRows);
  159.             $areaRows array_reverse($areaRows);
  160.             $seatPlanRows array_merge($seatPlanRows$areaRows);
  161.         }
  162.         usort($seatPlanRows, [$this'sortByBottom']);
  163.         $seatPlanRows $this->adjustNulls($seatPlanRows);
  164.         return [
  165.             $seatPlanRows,
  166.             $totalSeatsCount,
  167.         ];
  168.     }
  169.     /**
  170.      * @param Row[] $list
  171.      *
  172.      * @return Row[]
  173.      */
  174.     protected function trimFirstEmptyRows(array $list): array
  175.     {
  176.         $result = [];
  177.         $skip true;
  178.         foreach ($list as $item) {
  179.             if (false === $skip || !is_null($item->getPhysicalName())) {
  180.                 $skip true;
  181.                 $result[] = $item;
  182.             }
  183.         }
  184.         return $result;
  185.     }
  186.     /**
  187.      * @param Row[] $list
  188.      *
  189.      * @return Row[]
  190.      */
  191.     protected function adjustNulls(array $list): array
  192.     {
  193.         $previous null;
  194.         $result = [];
  195.         foreach ($list as $item) {
  196.             $current $item->getPhysicalName();
  197.             if (null !== $previous || null !== $current) {
  198.                 $result[] = $item;
  199.             }
  200.             $previous $item->getPhysicalName();
  201.         }
  202.         return $result;
  203.     }
  204.     /**
  205.      * @param Row[]                $seatPlanRows
  206.      * @param CinemaAreaCategory[] $categories
  207.      */
  208.     public function setIconIds(array $seatPlanRows, array $categories)
  209.     {
  210.         foreach ($seatPlanRows as $row) {
  211.             $seats $row->getSeats();
  212.             $seats or $seats = [];
  213.             $categoryId = -1;
  214.             $messages '';
  215.             if ($categories) {
  216.                 $categoryCode intval($row->getAreaCategoryCode());
  217.                 if (array_key_exists($categoryCode$categories)) {
  218.                     $category $categories[intval($row->getAreaCategoryCode())];
  219.                     $categoryId $category->getAreaCategoryId();
  220.                 } else {
  221.                     $messages .= ' catecories does not consists category with code $categoryCode';
  222.                 }
  223.             } else {
  224.                 $messages .= ' catecories is empty';
  225.             }
  226.             if ($messages) {
  227.                 error_log(sprintf("%s %s(%s) $messages"date('Y-m-d H:i:s'), __METHOD____LINE__));
  228.             }
  229.             foreach ($seats as $seat) {
  230.                 $seat->setSeatIconId($this->matcher->getIconId($seat$categoryId));
  231.                 $seat->setSeatImprovedIconId($this->matcher->getImprovedIconId($seat$categoryId));
  232.             }
  233.         }
  234.     }
  235. }