1 <?php 
declare(strict_types
=1); 
   4  * This file is part of the Rapsys AirBundle package. 
   6  * (c) Raphaël Gertz <symfony@rapsys.eu> 
   8  * For the full copyright and license information, please view the LICENSE 
   9  * file that was distributed with this source code. 
  12 namespace Rapsys\AirBundle\Controller
; 
  14 use Doctrine\ORM\NoResultException
; 
  15 use Doctrine\ORM\ORMInvalidArgumentException
; 
  16 use Symfony\Component\Form\FormError
; 
  17 use Symfony\Component\HttpFoundation\Request
; 
  18 use Symfony\Component\HttpFoundation\Response
; 
  19 use Symfony\Component\Routing\Exception\MethodNotAllowedException
; 
  20 use Symfony\Component\Routing\Exception\ResourceNotFoundException
; 
  21 use Symfony\Component\Routing\RequestContext
; 
  23 use Rapsys\AirBundle\Entity\Application
; 
  24 use Rapsys\AirBundle\Entity\Dance
; 
  25 use Rapsys\AirBundle\Entity\Location
; 
  26 use Rapsys\AirBundle\Entity\Session
; 
  27 use Rapsys\AirBundle\Entity\Slot
; 
  28 use Rapsys\AirBundle\Entity\User
; 
  33 class ApplicationController 
extends AbstractController 
{ 
  37          * @desc Persist application and all required dependencies in database 
  39          * @param Request $request The request instance 
  40          * @param Registry $manager The doctrine registry 
  41          * @param EntityManagerInterface $manager The doctrine entity manager 
  43          * @return Response The rendered view or redirection 
  45          * @throws \RuntimeException When user has not at least guest role 
  47         public function add(Request 
$request) { 
  49                 if (!$this->checker
->isGranted('ROLE_GUEST')) { 
  51                         throw $this->createAccessDeniedException($this->translator
->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator
->trans('Guest')])); 
  54                 //Get favorites dances 
  55                 $danceFavorites = $this->doctrine
->getRepository(Dance
::class)->findByUserId($this->security
->getUser()->getId()); 
  58                 $danceDefault = !empty($danceFavorites)?current($danceFavorites):null; 
  60                 //Get favorites locations 
  61                 $locationFavorites = $this->doctrine
->getRepository(Location
::class)->findByUserId($this->security
->getUser()->getId()); 
  63                 //Set location default 
  64                 $locationDefault = !empty($locationFavorites)?current($locationFavorites):null; 
  67                 if ($this->checker
->isGranted('ROLE_ADMIN')) { 
  69                         $dances = $this->doctrine
->getRepository(Dance
::class)->findAll(); 
  72                         $locations = $this->doctrine
->getRepository(Location
::class)->findAll(); 
  75                         //Restrict to favorite dances 
  76                         $dances = $danceFavorites; 
  81                         //Restrict to favorite locations 
  82                         $locations = $locationFavorites; 
  85                         $locationFavorites = []; 
  88                 //Create ApplicationType form 
  89                 $form = $this->factory
->create('Rapsys\AirBundle\Form\ApplicationType', null, [ 
  91                         'action' => $this->generateUrl('rapsys_air_application_add'), 
  92                         //Set the form attribute 
  93                         #'attr' => [ 'class' => 'col' ], 
  95                         'dance_choices' => $dances, 
  97                         'dance_default' => $danceDefault, 
  99                         'dance_favorites' => $danceFavorites, 
 100                         //Set location choices 
 101                         'location_choices' => $locations, 
 102                         //Set location default 
 103                         'location_default' => $locationDefault, 
 104                         //Set location favorites 
 105                         'location_favorites' => $locationFavorites, 
 107                         'user' => $this->checker
->isGranted('ROLE_ADMIN'), 
 109                         'user_choices' => $this->doctrine
->getRepository(User
::class)->findChoicesAsArray(), 
 110                         //Set default user to current 
 111                         'user_default' => $this->security
->getUser()->getId(), 
 112                         //Set default slot to evening 
 113                         //XXX: default to Evening (3) 
 114                         'slot_default' => $this->doctrine
->getRepository(Slot
::class)->findOneByTitle('Evening') 
 118                 $this->context
['title']['page'] = $this->translator
->trans('Application add'); 
 121                 $this->context
['title']['section'] = $this->translator
->trans('Application'); 
 124                 $this->context
['description'] = $this->translator
->trans('Add an application and session'); 
 126                 //Refill the fields in case of invalid form 
 127                 $form->handleRequest($request); 
 129                 //Handle invalid form 
 130                 if (!$form->isSubmitted() || !$form->isValid()) { 
 132                         return $this->render('@RapsysAir/application/add.html.twig', ['form' => $form->createView()]+
$this->context
); 
 136                 $data = $form->getData(); 
 138                 //Protect session fetching 
 141                         $session = $this->doctrine
->getRepository(Session
::class)->findOneByLocationSlotDate($data['location'], $data['slot'], $data['date']); 
 142                 //Catch no session case 
 143                 } catch (NoResultException 
$e) { 
 145                         $session = new Session(); 
 146                         $session->setLocation($data['location']); 
 147                         $session->setDate($data['date']); 
 148                         $session->setSlot($data['slot']); 
 151                         $location = $data['location']->getTitle(); 
 154                         $slot = $data['slot']->getTitle(); 
 157                         //XXX: premium is stored only for Afternoon and Evening 
 158                         $premium = $session->isPremium(); 
 160                         //Set default length at 6h 
 161                         //XXX: date part will be truncated on save 
 162                         $session->setLength(new \
DateTime('06:00:00')); 
 165                         if ($this->checker
->isGranted('ROLE_ADMIN')) { 
 167                                 if ($slot == 'Morning') { 
 169                                         $session->setBegin(new \
DateTime('09:00:00')); 
 172                                         $session->setLength(new \
DateTime('05:00:00')); 
 174                                 } elseif ($slot == 'Afternoon') { 
 176                                         $session->setBegin(new \
DateTime('15:30:00')); 
 179                                         $session->setLength(new \
DateTime('05:30:00')); 
 181                                 } elseif ($slot == 'Evening') { 
 183                                         $session->setBegin(new \
DateTime('19:30:00')); 
 186                                         $session->setLength(new \
DateTime('05:30:00')); 
 188                                         //Check if next day is premium 
 191                                                 $session->setLength(new \
DateTime('06:30:00')); 
 196                                         $session->setBegin(new \
DateTime('01:00:00')); 
 199                                         $session->setLength(new \
DateTime('04:00:00')); 
 201                                         //Check if next day is premium 
 204                                                 $session->setBegin(new \
DateTime('02:00:00')); 
 207                                                 $session->setLength(new \
DateTime('03:00:00')); 
 210                         //Tino-Rossi garden => 14h -> 19h | 19h -> 01/02h 
 211                         } elseif (in_array($location, ['Tino-Rossi garden']) && in_array($slot, ['Afternoon', 'Evening', 'After'])) { 
 213                                 if ($slot == 'Afternoon') { 
 215                                         $session->setBegin(new \
DateTime('14:00:00')); 
 218                                         $session->setLength(new \
DateTime('05:00:00')); 
 220                                 } elseif ($slot == 'Evening') { 
 222                                         $session->setBegin(new \
DateTime('19:00:00')); 
 224                                         //Check if next day is premium 
 227                                                 $session->setLength(new \
DateTime('07:00:00')); 
 232                                         $session->setBegin(new \
DateTime('01:00:00')); 
 235                                         $session->setLength(new \
DateTime('04:00:00')); 
 237                                         //Check if next day is premium 
 240                                                 $session->setBegin(new \
DateTime('02:00:00')); 
 243                                                 $session->setLength(new \
DateTime('03:00:00')); 
 246                         //Garnier opera => 21h -> 01/02h 
 247                         } elseif ($location == 'Garnier opera' && in_array($slot, ['Evening', 'After'])) { 
 249                                 if ($slot == 'Evening') { 
 251                                         $session->setBegin(new \
DateTime('21:00:00')); 
 254                                         $session->setLength(new \
DateTime('05:00:00')); 
 256                                         //Check if next day is premium 
 259                                                 $session->setLength(new \
DateTime('06:00:00')); 
 264                                         $session->setBegin(new \
DateTime('01:00:00')); 
 267                                         $session->setLength(new \
DateTime('04:00:00')); 
 269                                         //Check if next day is premium 
 272                                                 $session->setBegin(new \
DateTime('02:00:00')); 
 275                                                 $session->setLength(new \
DateTime('03:00:00')); 
 278                         //Trocadero esplanade|Tokyo palace|Swan island|Saint-Honore market|Orsay museum => 19h -> 01/02h 
 279                         } elseif (in_array($location, ['Trocadero esplanade', 'Tokyo palace', 'Swan island', 'Saint-Honore market', 'Orsay museum']) && in_array($slot, ['Evening', 'After'])) { 
 281                                 if ($slot == 'Evening') { 
 283                                         $session->setBegin(new \
DateTime('19:00:00')); 
 285                                         //Check if next day is premium 
 288                                                 $session->setLength(new \
DateTime('07:00:00')); 
 293                                         $session->setBegin(new \
DateTime('01:00:00')); 
 296                                         $session->setLength(new \
DateTime('04:00:00')); 
 298                                         //Check if next day is premium 
 301                                                 $session->setBegin(new \
DateTime('02:00:00')); 
 304                                                 $session->setLength(new \
DateTime('03:00:00')); 
 307                         //Drawings' garden (Villette) => 14h -> 19h 
 308                         } elseif ($location == 'Drawings\' garden' && $slot == 'Afternoon') { 
 310                                 $session->setBegin(new \
DateTime('14:00:00')); 
 313                                 $session->setLength(new \
DateTime('05:00:00')); 
 314                         //Colette place => 14h -> 21h 
 315                         //TODO: add check here that it's a millegaux account ? 
 316                         } elseif ($location == 'Colette place' && $slot == 'Afternoon') { 
 318                                 $session->setBegin(new \
DateTime('14:00:00')); 
 321                                 $session->setLength(new \
DateTime('07:00:00')); 
 322                         //Orleans gallery => 14h -> 18h 
 323                         } elseif ($location == 'Orleans gallery' && $slot == 'Afternoon') { 
 325                                 $session->setBegin(new \
DateTime('14:00:00')); 
 328                                 $session->setLength(new \
DateTime('04:00:00')); 
 329                         //Monde garden => 14h -> 19h 
 330                         //TODO: add check here that it's a raphael account ? 
 331                         } elseif ($location == 'Monde garden' && $slot == 'Afternoon') { 
 333                                 $session->setBegin(new \
DateTime('14:00:00')); 
 336                                 $session->setLength(new \
DateTime('05:00:00')); 
 337                         //Combination not supported 
 338                         //TODO: add Madeleine place|Bastille place|Vendome place ? 
 340                                 //Add error in flash message 
 341                                 $this->addFlash('error', $this->translator
->trans('Session on %date% %location% %slot% not yet supported', ['%location%' => $this->translator
->trans('at '.$data['location']), '%slot%' => $this->translator
->trans('the '.strtolower(strval($data['slot']))), '%date%' => $data['date']->format('Y-m-d')])); 
 344                                 return $this->render('@RapsysAir/application/add.html.twig', ['form' => $form->createView()]+
$this->context
); 
 348                         if (!$this->checker
->isGranted('ROLE_ADMIN') && $session->getStart() < new \
DateTime('00:00:00')) { 
 349                                 //Add error in flash message 
 350                                 $this->addFlash('error', $this->translator
->trans('Session in the past on %date% %location% %slot% not yet supported', ['%location%' => $this->translator
->trans('at '.$data['location']), '%slot%' => $this->translator
->trans('the '.strtolower(strval($data['slot']))), '%date%' => $data['date']->format('Y-m-d')])); 
 353                                 return $this->render('@RapsysAir/application/add.html.twig', ['form' => $form->createView()]+
$this->context
); 
 357                         $this->manager
->persist($session); 
 359                         //Flush to get the ids 
 360                         #$this->manager->flush(); 
 362                         $this->addFlash('notice', $this->translator
->trans('Session on %date% %location% %slot% created', ['%location%' => $this->translator
->trans('at '.$data['location']), '%slot%' => $this->translator
->trans('the '.strtolower(strval($data['slot']))), '%date%' => $data['date']->format('Y-m-d')])); 
 366                 $user = $this->security
->getUser(); 
 368                 //Replace with requested user for admin 
 369                 if ($this->checker
->isGranted('ROLE_ADMIN') && !empty($data['user'])) { 
 370                         $user = $this->doctrine
->getRepository(User
::class)->findOneById($data['user']); 
 373                 //Protect application fetching 
 375                         //Retrieve application 
 376                         $application = $this->doctrine
->getRepository(Application
::class)->findOneBySessionUser($session, $user); 
 378                         //Add warning in flash message 
 379                         $this->addFlash('warning', $this->translator
->trans('Application on %date% %location% %slot% already exists', ['%location%' => $this->translator
->trans('at '.$data['location']), '%slot%' => $this->translator
->trans('the '.strtolower(strval($data['slot']))), '%date%' => $data['date']->format('Y-m-d')])); 
 380                 //Catch no application and session without identifier (not persisted&flushed) cases 
 381                 } catch (NoResultException
|ORMInvalidArgumentException 
$e) { 
 382                         //Create the application 
 383                         $application = new Application(); 
 384                         $application->setDance($data['dance']); 
 385                         $application->setSession($session); 
 386                         $application->setUser($user); 
 388                         //Refresh session updated field 
 389                         $session->setUpdated(new \
DateTime('now')); 
 392                         $this->manager
->persist($session); 
 394                         //Queue application save 
 395                         $this->manager
->persist($application); 
 397                         //Flush to get the ids 
 398                         $this->manager
->flush(); 
 400                         //Add notice in flash message 
 401                         $this->addFlash('notice', $this->translator
->trans('Application on %date% %location% %slot% created', ['%location%' => $this->translator
->trans('at '.$data['location']), '%slot%' => $this->translator
->trans('the '.strtolower(strval($data['slot']))), '%date%' => $data['date']->format('Y-m-d')])); 
 404                 //Extract and process referer 
 405                 if ($referer = $request->headers
->get('referer')) { 
 406                         //Create referer request instance 
 407                         $req = Request
::create($referer); 
 410                         $path = $req->getPathInfo(); 
 412                         //Get referer query string 
 413                         $query = $req->getQueryString(); 
 416                         $path = str_replace($request->getScriptName(), '', $path); 
 418                         //Try with referer path 
 421                                 $oldContext = $this->router
->getContext(); 
 423                                 //Force clean context 
 424                                 //XXX: prevent MethodNotAllowedException because current context method is POST in onevendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php+42 
 425                                 $this->router
->setContext(new RequestContext()); 
 427                                 //Retrieve route matching path 
 428                                 $route = $this->router
->match($path); 
 431                                 $this->router
->setContext($oldContext); 
 437                                 $name = $route['_route']; 
 439                                 //Remove route and controller from route defaults 
 440                                 unset($route['_route'], $route['_controller']); 
 442                                 //Check if session view route 
 443                                 if ($name == 'rapsys_air_session_view' && !empty($route['id'])) { 
 445                                         $route['id'] = $session->getId(); 
 449                                         $route['session'] = $session->getId(); 
 453                                 return $this->redirectToRoute($name, $route); 
 455                         } catch (MethodNotAllowedException
|ResourceNotFoundException 
$e) { 
 456                                 //Unset referer to fallback to default route 
 461                 //Redirect to cleanup the form 
 462                 return $this->redirectToRoute('rapsys_air', ['session' => $session->getId()]);