src/Controller/RolloutController.php line 228

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\File;
  4. use App\Entity\FileGroup;
  5. use App\Entity\Rollout;
  6. use App\Entity\User;
  7. use App\Entity\Workspace;
  8. use App\Form\RolloutType;
  9. use App\Repository\FileGroupRepository;
  10. use App\Repository\RolloutRepository;
  11. use App\Repository\DeviceRepository;
  12. use App\Service\BlockChainService;
  13. use App\Service\IotBrokerService;
  14. use App\Service\IpfsService;
  15. use App\Utils\Datatable;
  16. use DateTime;
  17. use Exception;
  18. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  19. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  20. use Symfony\Component\HttpFoundation\JsonResponse;
  21. use Symfony\Component\HttpFoundation\Request;
  22. use Symfony\Component\HttpFoundation\Response;
  23. use Symfony\Component\Routing\Annotation\Route;
  24. use Symfony\Component\Serializer\Exception\ExceptionInterface;
  25. use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
  26. use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
  27. use Symfony\Component\Serializer\Serializer;
  28. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  29. use Symfony\Contracts\Translation\TranslatorInterface;
  30. use Symfony\Component\HttpFoundation\File\UploadedFile;
  31. /**
  32.  * @Route("/rollout")
  33.  */
  34. class RolloutController extends AbstractController
  35. {
  36.     /**
  37.      * @Route("/list", name="rollout_index", methods={"GET"})
  38.      * @IsGranted("ROLLOUT_VIEW")
  39.      * @Security("is_granted('ROLE_ADMIN',user) or is_granted('ROLLOUT_VIEW', user)")
  40.      * @param RolloutRepository $rolloutRepository
  41.      * @return Response
  42.      * @throws Exception
  43.      */
  44.     public function index(RolloutRepository $rolloutRepository): Response
  45.     {
  46.         /** @var User $user */
  47.         $user $this->getUser();
  48.         /** @var Workspace $workspace */
  49.         $workspace $user->getWorkspace();
  50.         return $this->render(
  51.             'rollout/index.html.twig',
  52.             [
  53.                 'planned_rollouts' => $rolloutRepository->getPlanned(
  54.                     $workspace,
  55.                     5
  56.                 ),
  57.                 'running_rollouts' => $rolloutRepository->getRunning(
  58.                     $workspace,
  59.                     5
  60.                 ),
  61.             ]
  62.         );
  63.     }
  64.     /**
  65.      * @Route("/fetch/planned/{nonce}", name="fetch_rollout_planned", methods={"GET"})
  66.      * @IsGranted("ROLLOUT_VIEW")
  67.      * @param Request $request
  68.      * @param Datatable $datatable
  69.      * @param RolloutRepository $rolloutRepository
  70.      * @param $nonce
  71.      * @return Response
  72.      * @throws Exception
  73.      */
  74.     public function fetchRolloutsPlanned(
  75.         Request $request,
  76.         Datatable $datatable,
  77.         RolloutRepository $rolloutRepository,
  78.         $nonce
  79.     ): Response
  80.     {
  81.         if (!$request->isXmlHttpRequest()) {
  82.             throw $this->createAccessDeniedException("Not an ajax request!");
  83.         }
  84.         /** @var User $user */
  85.         $user $this->getUser();
  86.         $datatables $datatable
  87.             ->withColumnType(
  88.                 [ // list column in order
  89.                     'id' => ['alias' => 'r'],
  90.                     'priority' => [
  91.                         'alias' => 'r',
  92.                         'twig' => 'components/datatable.rollout.priority.twig',
  93.                     ],
  94.                     'disabled' => [
  95.                         'alias' => 'r',
  96.                         'twig' => 'components/datatable.rollout.disabled.twig',
  97.                     ],
  98.                     'name' => [
  99.                         'alias' => 'r',
  100.                         'twig' => 'rollout/datatable.link.twig',
  101.                     ],
  102.                     'startDate' => [
  103.                         'alias' => 'r',
  104.                         'twig' => 'components/datatable.datetime.twig',
  105.                     ],
  106.                     'fileName' => [
  107.                         'alias' => 'f',
  108.                     ],
  109.                     'deviceGroups' => [
  110.                         'alias' => 'dg',
  111.                     ],
  112.                     'devicesInGroups' => [
  113.                         'alias' => 'dg',
  114.                     ],
  115.                     'updatedDevices' => [
  116.                         'alias' => 'dg',
  117.                     ],
  118.                 ]
  119.             )
  120.             ->withOptions(['nonce' => $nonce])
  121.             ->renderActionView('rollout/datatable.action.planned.twig'// provide custom twig to render action column
  122.             ->isRollout(true)
  123.             ->withQueryBuilder($rolloutRepository->queryPlanned($user->getWorkspace()))
  124.             ->withRequestParams($request->query->all());
  125.         return new JsonResponse($datatables->getResponse());
  126.     }
  127.     /**
  128.      * @Route("/fetch/running/{nonce}", name="fetch_rollout_running", methods={"GET"})
  129.      * @IsGranted("ROLLOUT_VIEW")
  130.      * @param Request $request
  131.      * @param Datatable $datatable
  132.      * @param RolloutRepository $rolloutRepository
  133.      * @param $nonce
  134.      * @return Response
  135.      * @throws Exception
  136.      */
  137.     public function fetchRolloutsRunning(
  138.         Request $request,
  139.         Datatable $datatable,
  140.         RolloutRepository $rolloutRepository,
  141.         $nonce
  142.     ): Response
  143.     {
  144.         if (!$request->isXmlHttpRequest()) {
  145.             throw $this->createAccessDeniedException("Not an ajax request!");
  146.         }
  147.         /** @var User $user */
  148.         $user $this->getUser();
  149.         $datatables $datatable
  150.             ->withColumnType(
  151.                 [ // list column in order
  152.                     'id' => ['alias' => 'r'],
  153.                     'priority' => [
  154.                         'alias' => 'r',
  155.                         'twig' => 'components/datatable.rollout.priority.twig',
  156.                     ],
  157.                     'disabled' => [
  158.                         'alias' => 'r',
  159.                         'twig' => 'components/datatable.rollout.disabled.twig',
  160.                     ],
  161.                     'name' => [
  162.                         'alias' => 'r',
  163.                         'twig' => 'rollout/datatable.link.twig',
  164.                     ],
  165.                     'startDate' => [
  166.                         'alias' => 'r',
  167.                         'twig' => 'components/datatable.datetime.twig',
  168.                     ],
  169.                     // 'realStartDate' => [
  170.                     //     'alias' => 'r',
  171.                     //     'twig' => 'components/datatable.datetime.twig',
  172.                     // ],
  173.                     'fileName' => [
  174.                         'alias' => 'f',
  175.                     ],
  176.                     'deviceGroups' => [
  177.                         'alias' => 'dg',
  178.                     ],
  179.                     'devicesInGroups' => [
  180.                         'alias' => 'dg',
  181.                     ],
  182.                     'updatedDevices' => [
  183.                         'alias' => 'dg',
  184.                     ],
  185.                     'leftDevices' => [
  186.                         'alias' => 'dg',
  187.                     ],
  188.                 ]
  189.             )
  190.             ->withOptions(['nonce' => $nonce])
  191.             ->renderActionView('rollout/datatable.action.running.twig'// provide custom twig to render action column
  192.             ->isRollout(true)
  193.             ->withQueryBuilder($rolloutRepository->queryRunning($user->getWorkspace()))
  194.             ->withRequestParams($request->query->all());
  195.         return new JsonResponse($datatables->getResponse());
  196.     }
  197.     /**
  198.      * @Route("/list/running", name="rollout_list_running", methods={"GET"})
  199.      * @IsGranted("ROLLOUT_VIEW")
  200.      * @return Response
  201.      * @throws Exception
  202.      */
  203.     public function runningList(): Response
  204.     {
  205.         return $this->render(
  206.             'rollout/running.html.twig'
  207.         );
  208.     }
  209.     /**
  210.      * @Route("/list/planned", name="rollout_list_planned", methods={"GET"})
  211.      * @IsGranted("ROLLOUT_VIEW")
  212.      * @return Response
  213.      * @throws Exception
  214.      */
  215.     public function plannedList(): Response
  216.     {
  217.         return $this->render(
  218.             'rollout/planned.html.twig'
  219.         );
  220.     }
  221.     /**
  222.      * @Route("/new/{nonce}/{type}", name="rollout_new", methods={"GET","POST"})
  223.      * @IsGranted("ROLLOUT_CREATE")
  224.      * @param Request $request
  225.      * @param TranslatorInterface $translator
  226.      * @param FileGroupRepository $fileGroupRepository
  227.      * @param IpfsService $ipfsService
  228.      * @param IotBrokerService $iotBrokerService
  229.      * @param BlockChainService $blockChainService
  230.      * @param $nonce
  231.      * @param string $type
  232.      * @return Response
  233.      * @throws Exception
  234.      */
  235.     public function new(Request $requestTranslatorInterface $translatorFileGroupRepository $fileGroupRepositoryIpfsService $ipfsServiceIotBrokerService $iotBrokerServiceBlockChainService $blockChainService$noncestring $type "index"): Response
  236.     {
  237.         if ($request->isMethod('GET') && !$request->isXmlHttpRequest()) {
  238.             throw $this->createAccessDeniedException("Not an ajax request!");
  239.         }
  240.         $rollout = new Rollout();
  241.         /** @var User $user */
  242.         $user $this->getUser();
  243.         /** @var Workspace $workspace */
  244.         $workspace $user->getWorkspace();
  245.         $rollout->setWorkspace($workspace);
  246.         if (!$this->isGranted('VIEW_PLAN_SCHEDULED_ROLLOUTS'$this->getUser())) {
  247.             $rollout->setStartDate(new DateTime());
  248.         }
  249.         $form $this->createForm(
  250.             RolloutType::class,
  251.             $rollout,
  252.             [
  253.                 'action' => $this->generateUrl(
  254.                     'rollout_new',
  255.                     [
  256.                         'type' => $type,
  257.                         'nonce' => $nonce
  258.                     ]
  259.                 ),
  260.                 'method' => 'POST',
  261.                 'dt_trans_format' => $translator->trans('datetime_formtype')
  262.             ]
  263.         );
  264.         $form->handleRequest($request);
  265.         if ($form->isSubmitted() && $form->isValid()) {
  266.             $entityManager $this->getDoctrine()->getManager();
  267.             $configType $form->get("configType")->getData();
  268.             if ($configType == 1) {
  269.                 $fileGroup $form->get("fileGroup")->getData();
  270.                 $fileGroupId $fileGroup->getId();
  271.                 $configText $form->get("configurationText")->getData();
  272.                 $fileName time()."_".$fileGroupId;
  273.                 $requestFile fopen($fileName"w") or die("Unable to open file!");
  274.                 fwrite($requestFile$configText);
  275.                 fclose($requestFile);
  276.                 $uploadedFile =  new UploadedFile($fileName$fileNamenullnullfalse);
  277.                 $cid $ipfsService->upload($uploadedFile);
  278.                 /** @var File $file */
  279.                 $file = new File();
  280.                 $file->addFileGroup($fileGroup);
  281.                 $file->setWorkspace($workspace);
  282.                 $file->setName($fileName);
  283.                 $file->setClientFileName($fileName);
  284.                 $file->setUrl($cid);
  285.                 $file->setVersion(1);
  286.                 $file->addRollout($rollout);
  287.                 $entityManager->persist($file);
  288.                 $entityManager->persist($rollout);
  289.                 $entityManager->flush();
  290.                 $blockChainService->registerFirmware($file);
  291.             }
  292.             $disabled $rollout->getDisabled();
  293.             if ($rollout->getPriority() === 1) {
  294.                 $this->disableRollouts($rollout);
  295.             }
  296.             $rollout->setDisabled($disabled);
  297.             $entityManager->persist($rollout);
  298.             $entityManager->flush();
  299.             //Lora check start
  300.             if (intval($_ENV['ALLOW_LORA_A']) === 1) {
  301.                 $loraDeviceGroups = [];
  302.                 foreach ($rollout->getDeviceGroups() as $deviceGroup) {
  303.                     if ($deviceGroup->isLoraTypeA()) {
  304.                         $loraDeviceGroups[] = $deviceGroup;
  305.                     }
  306.                 }
  307.                 if (count($loraDeviceGroups) > 0) {
  308.                     if ($iotBrokerService->send($loraDeviceGroups$rollout"CLASS_A") === true) {
  309.                         $this->addFlash("success""IOT Broker - request successfully");
  310.                     }
  311.                 }
  312.             }
  313.             if (intval($_ENV['ALLOW_LORA_C']) === 1) {
  314.                 $loraDeviceGroups = [];
  315.                 foreach ($rollout->getDeviceGroups() as $deviceGroup) {
  316.                     if ($deviceGroup->isLoraTypeC()) {
  317.                         $loraDeviceGroups[] = $deviceGroup;
  318.                     }
  319.                 }
  320.                 if (count($loraDeviceGroups) > 0) {
  321.                     if ($iotBrokerService->send($loraDeviceGroups$rollout"CLASS_C") === true) {
  322.                         $this->addFlash("success""IOT Broker - request successfully");
  323.                     }
  324.                 }
  325.             }
  326.             //lora check end
  327.             if ($type === "running" || $type === "planned") {
  328.                 if ($rollout->getStartDate() >= new DateTime('-5 second')) {
  329.                     return $this->redirectToRoute('rollout_list_planned');
  330.                 }
  331.                 return $this->redirectToRoute('rollout_list_running');
  332.             }
  333.             return $this->redirectToRoute('rollout_index');
  334.         }
  335.         return $this->render(
  336.             'rollout/new.html.twig',
  337.             [
  338.                 'nonce' => urldecode(str_replace('?2F?''%2F'$nonce)),
  339.                 'rollout' => $rollout,
  340.                 'form' => $form->createView(),
  341.             ]
  342.         );
  343.     }
  344.     /**
  345.      * @param Rollout $rollout
  346.      */
  347.     private function disableRollouts(Rollout $rollout)
  348.     {
  349.         $entityManager $this->getDoctrine()->getManager();
  350.         foreach ($rollout->getDeviceGroups() as $deviceGroup) {
  351.             foreach ($deviceGroup->getRollouts() as $rollout) {
  352.                 $rollout->setDisabled(true);
  353.                 $entityManager->persist($rollout);
  354.             }
  355.         }
  356.         $entityManager->flush();
  357.     }
  358.     /**
  359.      * @Route("/show_popup/{id}", name="rollout_show_popup", methods={"GET"})
  360.      * @IsGranted("ROLLOUT_SHOW", subject="rollout")
  361.      * @param Request $request
  362.      * @param Rollout $rollout
  363.      * @return Response
  364.      */
  365.     public function showPopup(Request $requestRollout $rollout): Response
  366.     {
  367.         if (!$request->isXmlHttpRequest()) {
  368.             throw $this->createAccessDeniedException("Not an ajax request!");
  369.         }
  370.         return $this->render(
  371.             'rollout/show.html.popup.twig',
  372.             [
  373.                 'rollout' => $rollout,
  374.             ]
  375.         );
  376.     }
  377.     /**
  378.      * @Route("/show/{id}", name="rollout_show", methods={"GET"})
  379.      * @IsGranted("ROLLOUT_SHOW", subject="rollout")
  380.      * @param Request $request
  381.      * @param Rollout $rollout
  382.      * @return Response
  383.      */
  384.     public function show(Request $requestRollout $rolloutRolloutRepository $rolloutRepository): Response
  385.     {
  386.         // if (!$request->isXmlHttpRequest()) {
  387.         //     throw $this->createAccessDeniedException("Not an ajax request!");
  388.         // }
  389.         return $this->render(
  390.             'rollout/show.html.twig',
  391.             [
  392.                 'rollout' => $rollout,
  393.             ]
  394.         );
  395.     }
  396.      /**
  397.      * @Route("fetch/show/{id}/{nonce}", name="fetch_devices_for_rollout", methods={"POST"})
  398.      * @IsGranted("DEVICE_GROUP_VIEW")
  399.      * @param Request $request
  400.      * @param Rollout $rollout
  401.      * @param Datatable $datatable
  402.      * @param DeviceGroupRepository $deviceGroupRepository
  403.      * @param $nonce
  404.      * @return Response
  405.      */
  406.     public function fetchDevicesForRollout(Request $requestRollout $rolloutDatatable $datatableDeviceRepository $deviceRepository$nonce): Response
  407.     {
  408.         if (!$request->isXmlHttpRequest()) {
  409.             throw $this->createAccessDeniedException("Not an ajax request!");
  410.         }
  411.         $columns = [ // list column in order
  412.             'id' => ['alias' => 'd'],
  413.             'name' => ['alias' => 'd''twig' => 'rollout/datatable_device.link.twig'], // type link, badge or circular status twig
  414.             'macAddress' => ['alias' => 'd'],
  415.             // 'serialNumber' => ['alias' => 'd'],
  416.             'class' => ['alias' => 'd'],
  417.             'firmwareVersion' => ['alias' => 'd'],
  418.             'created' => ['alias' => 'd''twig' => 'components/datatable.datetime.twig'],
  419.             'isUsed' => ['alias' => 'd',  'twig' => 'rollout/datatable_is_used.twig'],
  420.             // zenner
  421.             // 'device_status' => ['alias' => 'd'],
  422.             // 'tenant' => ['alias' => 'd'],
  423.             // 'downlinkType' => ['alias' => 'd'],
  424.         ];
  425.       
  426.         $datatables $datatable
  427.             ->withColumnType($columns)
  428.             ->withOptions(['rollout' => $rollout'nonce' => $nonce])
  429.             ->renderActionView('rollout/datatable_device.action.twig')  // provide custom twig to render action column
  430.             ->withQueryBuilder($deviceRepository->getByRollout($rollout))
  431.             ->isDevice(true)
  432.             ->withRequestParams($request->request->all());
  433.         return new JsonResponse($datatables->getResponse());
  434.     }
  435.     /**
  436.      * @Route("/start/form/{id}", name="rollout_start_form", methods={"GET"})
  437.      * @IsGranted("ROLLOUT_EDIT", subject="rollout")
  438.      * @param Request $request
  439.      * @param Rollout $rollout
  440.      * @return Response
  441.      */
  442.     public function startForm(Request $requestRollout $rollout): Response
  443.     {
  444.         if (!$request->isXmlHttpRequest()) {
  445.             throw $this->createAccessDeniedException("Not an ajax request!");
  446.         }
  447.         return $this->render(
  448.             'rollout/start.html.twig',
  449.             [
  450.                 'rollout' => $rollout,
  451.             ]
  452.         );
  453.     }
  454.     /**
  455.      * @Route("/start/{id}", name="rollout_start", methods={"POST"})
  456.      * @IsGranted("ROLLOUT_EDIT", subject="rollout")
  457.      * @param Request $request
  458.      * @param Rollout $rollout
  459.      * @return Response
  460.      * @throws Exception
  461.      */
  462.     public function start(Request $requestRollout $rollout): Response
  463.     {
  464.         if ($this->isCsrfTokenValid(
  465.             'start' $rollout->getId(),
  466.             $request->request->get('_token')
  467.         )) {
  468.             $entityManager $this->getDoctrine()->getManager();
  469.             $dt = new DateTime();
  470.             $rollout->setStartDate($dt->modify("-1 minutes"));
  471.             $entityManager->persist($rollout);
  472.             $entityManager->flush();
  473.         }
  474.         return $this->redirectToRoute('rollout_index');
  475.     }
  476.     /**
  477.      * @Route("/clone/{id}/{type}", name="rollout_clone", methods={"GET"})
  478.      * @IsGranted("ROLLOUT_CLONE", subject="rollout")
  479.      * @param Rollout $rollout
  480.      * @param string $type
  481.      * @return Response
  482.      */
  483.     public function clone(Rollout $rolloutstring $type "index"): Response
  484.     {
  485.         /** @var User $user */
  486.         $user $this->getUser();
  487.         $entityManager $this->getDoctrine()->getManager();
  488.         $newRollout = new Rollout();
  489.         $newRollout->setName($rollout->getName() . '-Clone');
  490.         $newRollout->setFile($rollout->getFile());
  491.         $newRollout->setMaintainer($rollout->getMaintainer());
  492.         $newRollout->setPriority($rollout->getPriority());
  493.         $newRollout->setStartDate($rollout->getStartDate());
  494.         if (count($rollout->getDeviceGroups()) > 0) {
  495.             foreach ($rollout->getDeviceGroups() as $deviceGroup) {
  496.                 $newRollout->addDeviceGroup($deviceGroup);
  497.             }
  498.         }
  499.         /** @var Workspace $workspace */
  500.         $workspace $user->getWorkspace();
  501.         $newRollout->setWorkspace($workspace);
  502.         $newRollout->setDisabled(true);
  503.         $entityManager->persist($newRollout);
  504.         $entityManager->flush();
  505.         if ($type === "running") {
  506.             return $this->redirectToRoute('rollout_list_running');
  507.         }
  508.         if ($type === "planned") {
  509.             return $this->redirectToRoute('rollout_list_planned');
  510.         }
  511.         return $this->redirectToRoute('rollout_index');
  512.     }
  513.     /**
  514.      * @Route("/edit/{id}/{nonce}/{type}", name="rollout_edit", methods={"GET","POST"})
  515.      * @IsGranted("ROLLOUT_EDIT", subject="rollout")
  516.      * @param Request $request
  517.      * @param Rollout $rollout
  518.      * @param TranslatorInterface $translator
  519.      * @param $nonce
  520.      * @param string $type
  521.      * @return Response
  522.      */
  523.     public function edit(Request $requestRollout $rolloutTranslatorInterface $translator$noncestring $type "index"): Response
  524.     {
  525.         if ($request->isMethod('GET') && !$request->isXmlHttpRequest()) {
  526.             throw $this->createAccessDeniedException("Not an ajax request!");
  527.         }
  528.         $form $this->createForm(
  529.             RolloutType::class,
  530.             $rollout,
  531.             [
  532.                 'action' => $this->generateUrl(
  533.                     'rollout_edit',
  534.                     [
  535.                         'id' => $rollout->getId(),
  536.                         'type' => $type,
  537.                         'nonce' => $nonce
  538.                     ]
  539.                 ),
  540.                 'method' => 'POST',
  541.                 'dt_trans_format' => $translator->trans('datetime_formtype')
  542.             ]
  543.         );
  544.         $form->handleRequest($request);
  545.         if ($form->isSubmitted() && $form->isValid()) {
  546.             $this->getDoctrine()->getManager()->flush();
  547.             if ($type === "running") {
  548.                 return $this->redirectToRoute('rollout_list_running');
  549.             }
  550.             if ($type === "planned") {
  551.                 return $this->redirectToRoute('rollout_list_planned');
  552.             }
  553.             return $this->redirectToRoute('rollout_index');
  554.         }
  555.         return $this->render(
  556.             'rollout/edit.html.twig',
  557.             [
  558.                 'nonce' => urldecode(str_replace('?2F?''%2F'$nonce)),
  559.                 'rollout' => $rollout,
  560.                 'form' => $form->createView(),
  561.             ]
  562.         );
  563.     }
  564.     /**
  565.      * @Route("/delete/{id}/{type}", name="rollout_delete", methods={"DELETE"})
  566.      * @IsGranted("ROLLOUT_DELETE", subject="rollout")
  567.      * @param Request $request
  568.      * @param Rollout $rollout
  569.      * @param TranslatorInterface $translator
  570.      * @param string $type
  571.      * @return Response
  572.      */
  573.     public function delete(Request $requestRollout $rolloutTranslatorInterface $translatorstring $type "index"): Response
  574.     {
  575.         if ($this->isCsrfTokenValid(
  576.             'delete' $rollout->getId(),
  577.             $request->request->get('_token')
  578.         )) {
  579.             if (count($rollout->getRolloutDevices()) === 0) {
  580.                 $entityManager $this->getDoctrine()->getManager();
  581.                 $entityManager->remove($rollout);
  582.                 $entityManager->flush();
  583.             } else {
  584.                 $this->addFlash("success"$translator->trans("msg.record_used_not_deletable"));
  585.             }
  586.         }
  587.         if ($type === "running") {
  588.             return $this->redirectToRoute('rollout_list_running');
  589.         }
  590.         if ($type === "planned") {
  591.             return $this->redirectToRoute('rollout_list_planned');
  592.         }
  593.         return $this->redirectToRoute('rollout_index');
  594.     }
  595.     /**
  596.      * @Route("delete/form/{id}/{type}", name="rollout_delete_form", methods={"GET"})
  597.      * @IsGranted("ROLLOUT_DELETE", subject="rollout")
  598.      * @param Request $request
  599.      * @param Rollout $rollout
  600.      * @param string $type
  601.      * @return Response
  602.      */
  603.     public function deleteForm(Request $requestRollout $rolloutstring $type "index"): Response
  604.     {
  605.         if (!$request->isXmlHttpRequest()) {
  606.             throw $this->createAccessDeniedException("Not an ajax request!");
  607.         }
  608.         $form $this->createFormBuilder()
  609.             ->setAction(
  610.                 $this->generateUrl(
  611.                     'rollout_delete',
  612.                     array(
  613.                         'id' => $rollout->getId(),
  614.                         'type' => $type,
  615.                     )
  616.                 )
  617.             )
  618.             ->setMethod('DELETE')
  619.             ->getForm();
  620.         return $this->render(
  621.             'rollout/delete.html.twig',
  622.             [
  623.                 'rollout' => $rollout,
  624.                 'form' => $form->createView(),
  625.             ]
  626.         );
  627.     }
  628.     /**
  629.      * @Route("/get/files/{id}", name="rollout_get_files_in_file_group", methods={"POST"})
  630.      * @param FileGroup $fileGroup
  631.      * @return JsonResponse
  632.      * @throws ExceptionInterface
  633.      */
  634.     public function fileList(FileGroup $fileGroup): JsonResponse
  635.     {
  636.         /** @var File $file */
  637.         foreach ($fileGroup->getFiles() as $file) {
  638.             if ($file->getTransactionId() === null) {
  639.                 $fileGroup->removeFile($file);
  640.             }
  641.         }
  642.         $serializer = new Serializer([new ObjectNormalizer()]);
  643.         $data $serializer->normalize(
  644.             $fileGroup,
  645.             'json',
  646.             [
  647.                 AbstractNormalizer::ATTRIBUTES => [
  648.                     'files' => [
  649.                         'id',
  650.                         'name',
  651.                     ],
  652.                 ],
  653.             ]
  654.         );
  655.         return new JsonResponse(
  656.             $data,
  657.             200
  658.         );
  659.     }
  660.     /**
  661.      * @Route("/delete/rollouts", name="delete_rollouts", methods={"POST"})
  662.      * @IsGranted("ROLLOUT_MULTI_DELETE")
  663.      * @param Request $request
  664.      * @param RolloutRepository $rolloutRepository
  665.      * @return Response
  666.      */
  667.     public function deleteRollouts(Request $requestRolloutRepository $rolloutRepository): Response
  668.     {
  669.         /** @var User $user */
  670.         $user $this->getUser();
  671.         $data explode(
  672.             ',',
  673.             $request->request->get('data_ids')
  674.         );
  675.         $em $this->getDoctrine()->getManager();
  676.         foreach ($data as $id) {
  677.             $rollout $rolloutRepository->findOneBy(["id" => $id"workspace" => $user->getWorkspace()->getId()]);
  678.             if (is_object($rollout)) {
  679.                 $em->remove($rollout);
  680.             }
  681.         }
  682.         $em->flush();
  683.         return new Response('success');
  684.     }
  685. }