src/Controller/API/V4Controller.php line 48

Open in your IDE?
  1. <?php
  2. namespace App\Controller\API;
  3. use App\Common\API\V4Common;
  4. use App\Common\VideoStream;
  5. use App\Entity\ArtObjectMedia;
  6. use App\Entity\SurveyQuestion;
  7. use App\Entity\SurveyQuestionResponse;
  8. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  9. use Symfony\Component\HttpFoundation\Request;
  10. use Symfony\Component\HttpFoundation\Response;
  11. use Symfony\Component\HttpFoundation\JsonResponse;
  12. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  13. use Symfony\Component\HttpFoundation\StreamedResponse;
  14. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  15. use Symfony\Component\Routing\Annotation\Route;
  16. /**
  17.  * Class V4Controller
  18.  *
  19.  * @package App\Controller
  20.  */
  21. #[Route(path'/api/v4'name'v4.')]
  22. class V4Controller extends CommonController
  23. {
  24.     /**
  25.      * Get list of update dates
  26.      *
  27.      * @return string
  28.      * @throws Exception
  29.      */
  30.     #[Route(path'/'name'index')]
  31.     public function index(): JsonResponse
  32.     {
  33.         //Return JSON
  34.         return new JsonResponse(['status'=> 'OK']);
  35.     }
  36.     /**
  37.      * Get list of update dates
  38.      *
  39.      * @return string
  40.      * @throws Exception
  41.      */
  42.     #[Route(path'/check'name'check')]
  43.     public function checkForUpdate(): JsonResponse
  44.     {
  45.         //Return JSON
  46.         return new JsonResponse(V4Common::getLastEntityTouchDateTime($this->em));
  47.     }
  48.     /**
  49.      * Get application data
  50.      *
  51.      * @param $timestamp
  52.      *             oldest data set to retrieve; null fetches all
  53.      *
  54.      * @return Response
  55.      */
  56.     #[Route(path'/data/{timestamp}'name'data'defaults: ['$timestamp' => 'null'])]
  57.     public function fetchData($timestamp null): Response
  58.     {
  59.         $projectDir $this->container->get('parameter_bag')->get('kernel.project_dir');
  60.         $cache = new V4Common($projectDir);
  61.         $filename $cache->getFileName();
  62.         return new Response(file_get_contents($filename));
  63.     }
  64.     /**
  65.      * Get application data
  66.      *
  67.      * @return string
  68.      */
  69.     #[Route(path'/webtour'name'webtour')]
  70.     public function fetchWebTourAction()
  71.     {
  72.         $data = [];
  73.         /** @var QueryBuilder $qb */
  74.         $qb =
  75.             $this->em->createQueryBuilder()
  76.                 ->select('WebTour')
  77.                 ->from('App:WebTour''WebTour');
  78.         $results =
  79.             $qb->getQuery()
  80.                 ->getResult();
  81.         /** @var WebTour $item */
  82.         foreach ($results as $item) {
  83.             $webTour = array(
  84.                 "id" => $item->getId(),
  85.                 "tourID" => $item->getTourID(),
  86.                 "title" => $item->getTitle(),
  87.                 "description" => $item->getDescription(),
  88.                 "displayDescription" => $item->getDisplayDescription(),
  89.                 "priority" => $item->getPriority(),
  90.                 "objects" => [],
  91.                 "media" => [],
  92.             );
  93.             /** @var WebTourLink $link */
  94.             foreach ($item->getArtObjects() as $link) {
  95.                 /** @var ArtObject $artObject */
  96.                 $artObject $link->getArtObject();
  97.                 $object = array(
  98.                     "id" => $artObject->getObjectID(),
  99.                     "priority" => $link->getPriority(),
  100.                     "defaultDescription" => $artObject->getDescription(),
  101.                     "collectionDescription" => null,
  102.                     "collectionDescriptionFormatted" => null,
  103.                 );
  104.                 /** @var ArtObjectDescription $desc */
  105.                 foreach ($artObject->getDescriptions() as $desc) {
  106.                     if ($desc->getCollectionId() == $item->getTourID()) {
  107.                         $object['collectionDescription'] = $desc->getDescription();
  108.                         $object['collectionDescriptionFormatted'] = $desc->getDisplayDescription();
  109.                         break;
  110.                     }
  111.                 }
  112.                 $webTour['objects'][] = $object;
  113.             }
  114.             /** @var WebTourMedia $media */
  115.             foreach ($item->getMedia() as $media) {
  116.                 $media = [
  117.                     "id" => $media->getId(),
  118.                     "objectID" => $media->getObjectID(),
  119.                     "linkID" => $media->getLinkID(),
  120.                     "name" => $media->getName(),
  121.                     "ext" => $media->getExt(),
  122.                     "typeDesc" => $media->getTypeDesc(),
  123.                     "description" => $media->getDescription(),
  124.                 ];
  125.                 $webTour['media'][] = $media;
  126.             }
  127.             $data[] = $webTour;
  128.         }
  129.         $this->em->clear();
  130.         unset($results);
  131.         return new JsonResponse($data);
  132.     }
  133.     /**
  134.      * Get multimedia asset.
  135.      *
  136.      * @param $objectID
  137.      * @param $linkID
  138.      * @param $name
  139.      * @param $ext
  140.      * @return Response
  141.      */
  142.     #[Route(path'/asset/{objectID}/{linkID}/{name}.{ext}'name'media'requirements: [
  143.         'objectID' => '\d+',
  144.         'linkID' => '.+',
  145.         'name' => '.+',
  146.         'ext' => '.+',
  147.     ])]
  148.     public function objectAsset($objectID$linkID$name$ext)
  149.     {
  150.         /** @var ArtObjectMedia $media */
  151.         $media $this->getMediaAsset($objectID$linkID$name$ext);
  152.         if (!$media) {
  153.             // Asset not found. Kill process.
  154.             throw new NotFoundHttpException('Object not found.');
  155.         }
  156.         $remoteAsset $this->getRemoteAssetPath($media);
  157.         if (!file_exists($remoteAsset) || filesize($remoteAsset) <= 0) {
  158.             // Asset not found. Kill process.
  159.             throw new NotFoundHttpException('Asset not found.');
  160.         }
  161.         // Get last modified time.
  162.         $lastModified filemtime($remoteAsset);
  163.         // Getting headers sent by the client.
  164.         $headers apache_request_headers();
  165.         // Checking if the client is validating its cache and if it is current.
  166.         if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $lastModified)) {
  167.             // Client's cache IS current, so we just respond '304 Not Modified'.
  168.             header("Last-Modified: ".gmdate('D, d M Y H:i:s'$lastModified)." GMT"true304);
  169.             exit;
  170.         }
  171.         $response = new BinaryFileResponse($remoteAsset);
  172.         $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
  173.         $response->headers->add(array("Last-Modified" => gmdate('D, d M Y H:i:s'$lastModified)." GMT"));
  174.         return $response;
  175.     }
  176.     /**
  177.      * Stream MP4 asset.
  178.      *
  179.      * @param         $objectID
  180.      * @param         $linkID
  181.      * @param         $name
  182.      * @param         $ext
  183.      *
  184.      * @param Request $request
  185.      *
  186.      * @return Response
  187.      */
  188.     #[Route(path'/asset/stream/{objectID}/{linkID}/{name}.{ext}'name'stream'requirements: [
  189.         'objectID' => '\d+',
  190.         'linkID' => '.+',
  191.         'name' => '.+',
  192.         'ext' => '.+',
  193.     ])]
  194.     public function streamVideo($objectID$linkID$name$extRequest $request): Response|StreamedResponse
  195.     {
  196.         /** @var \App\Entity\ArtObjectMedia $media */
  197.         $media $this->getMediaAsset($objectID$linkID$name$ext);
  198.         if (!$media) {
  199.             // Asset not found. Kill process.
  200.             throw new NotFoundHttpException('Object not found.');
  201.         }
  202.         $remoteAsset $this->getRemoteAssetPath($media);
  203.         if (!file_exists($remoteAsset) || filesize($remoteAsset) <= || $media->getExt() != "mp4") {
  204.             // Asset not found. Kill process.
  205.             throw new NotFoundHttpException('Asset not found.');
  206.         }
  207.         // Run stream protocol.
  208.         return (new VideoStream($remoteAsset))->streamAction($request);
  209.     }
  210.     /**
  211.      * Save POST survey data. Example POST JSON: {"response":[{"qid":1,"data":"true"}]}
  212.      *
  213.      * @param Request $request
  214.      *
  215.      * @return string
  216.      */
  217.     #[Route(path'/survey'name'survey_data')]
  218.     public function submitSurvey(Request $request): Response
  219.     {
  220.         // Configure batch saving
  221.         $batchSize 20;
  222.         $i 0;
  223.         // Retrieve submission from Request
  224.         $submission json_decode($request->getContent(), true);
  225.         if (isset($submission['response'])) {
  226.             $submission $submission['response'];
  227.         } else {
  228.             // bad data, return failure
  229.             return new JsonResponse(array("failure" => true));
  230.         }
  231.         // Loop through data items in submission
  232.         foreach ($submission as $data) {
  233.             if (!isset($data['qid']) || !isset($data['data'])) {
  234.                 // invalid data
  235.                 continue;
  236.             }
  237.             $id $data['qid'];
  238.             /** @var SurveyQuestion $question */
  239.             $question $this->em->getRepository('App:SurveyQuestion')->findOneBy(
  240.                 array("id" => $id"enabled" => true)
  241.             );
  242.             if (!$question) {
  243.                 // Survey question not found
  244.                 continue;
  245.             }
  246.             $response = new SurveyQuestionResponse();
  247.             if ($question->getType() == "boolean") {
  248.                 // boolean requires additional check
  249.                 if ($data['data'] === "true" || $data['data'] === "false") {
  250.                     $response->setResponse($data['data']);
  251.                 } else {
  252.                     // weed out trash responses
  253.                     continue;
  254.                 }
  255.             } else {
  256.                 $response->setResponse($data['data']);
  257.             }
  258.             $response->setQuestion($question);
  259.             // Save response to database
  260.             $this->em->persist($response);
  261.             // Increment batch index
  262.             $i++;
  263.             // Save batch, clear in memory objects
  264.             if (($i $batchSize) === 0) {
  265.                 $this->em->flush();
  266.                 $this->em->clear();
  267.             }
  268.         }
  269.         // Save unsaved objects
  270.         $this->em->flush();
  271.         $this->em->clear();
  272.         return new JsonResponse(array("success" => true));
  273.     }
  274. }