3 namespace Rapsys\AirBundle\Controller
; 
   5 use Symfony\Component\HttpFoundation\Request
; 
   6 use Symfony\Component\Routing\RequestContext
; 
   7 use Symfony\Component\Form\FormError
; 
   8 use Symfony\Component\Routing\Exception\MethodNotAllowedException
; 
   9 use Symfony\Component\Routing\Exception\ResourceNotFoundException
; 
  10 use Rapsys\AirBundle\Entity\Slot
; 
  11 use Rapsys\AirBundle\Entity\User
; 
  12 use Rapsys\AirBundle\Entity\Session
; 
  13 use Rapsys\AirBundle\Entity\Application
; 
  15 class ApplicationController 
extends DefaultController 
{ 
  19          * @desc Persist application and all required dependencies in database 
  21          * @param Request $request The request instance 
  23          * @return Response The rendered view or redirection 
  25          * @throws \RuntimeException When user has not at least guest role 
  27         public function add(Request 
$request) { 
  28                 //Prevent non-guest to access here 
  29                 $this->denyAccessUnlessGranted('ROLE_GUEST', null, $this->translator
->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator
->trans('Guest')])); 
  31                 //Reject non post requests 
  32                 if (!$request->isMethod('POST')) { 
  33                         throw new \
RuntimeException('Request method MUST be POST'); 
  36                 //Create ApplicationType form 
  37                 $form = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [ 
  39                         'action' => $this->generateUrl('rapsys_air_application_add'), 
  40                         //Set the form attribute 
  41                         #'attr' => [ 'class' => 'col' ], 
  43                         'admin' => $this->isGranted('ROLE_ADMIN'), 
  44                         //Set default user to current 
  45                         'user' => $this->getUser()->getId(), 
  46                         //Set default slot to evening 
  47                         //XXX: default to Evening (3) 
  48                         'slot' => $this->getDoctrine()->getRepository(Slot
::class)->findOneById(3) 
  51                 //Refill the fields in case of invalid form 
  52                 $form->handleRequest($request); 
  55                 if (!$form->isValid()) { 
  57                         $section = $this->translator
->trans('Application add'); 
  60                         $title = $section.' - '.$this->translator
->trans($this->config
['site']['title']); 
  63                         return $this->render('@RapsysAir/application/add.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView()]+
$this->context
); 
  67                 $doctrine = $this->getDoctrine(); 
  70                 $manager = $doctrine->getManager(); 
  73                 $data = $form->getData(); 
  75                 //Count session at location in last month for guest 
  76                 if (!$this->isGranted('ROLE_REGULAR') && !empty($session = $doctrine->getRepository(Session
::class)->findOneWithinLastMonthByLocationUser($data['location']->getId(), $this->getUser()->getId()))) { 
  77                         //Add warning in flash message 
  78                         $this->addFlash('warning', $this->translator
->trans('Monthly application %location% already exists', ['%location%' => $this->translator
->trans('at '.$data['location'])])); 
  80                         //Redirect to cleanup the form 
  81                         return $this->redirectToRoute('rapsys_air_session_view', ['id' => $session['id']]); 
  84                 //Protect session fetching 
  87                         $session = $doctrine->getRepository(Session
::class)->findOneByLocationSlotDate($data['location'], $data['slot'], $data['date']); 
  88                 //Catch no session case 
  89                 } catch (\Doctrine\ORM\NoResultException 
$e) { 
  91                         $session = new Session(); 
  92                         $session->setLocation($data['location']); 
  93                         $session->setDate($data['date']); 
  94                         $session->setSlot($data['slot']); 
  95                         $session->setCreated(new \
DateTime('now')); 
  96                         $session->setUpdated(new \
DateTime('now')); 
  99                         $short = $data['location']->getShort(); 
 102                         $slot = $data['slot']->getTitle(); 
 105                         $session->setPremium($premium = false); 
 107                         //Check if slot is afternoon 
 108                         //XXX: premium is stored only for Afternoon and Evening 
 109                         if ($slot == 'Afternoon') { 
 111                                 //XXX: a session is considered premium a day off 
 112                                 $session->setPremium($premium = $this->isPremium($data['date'])); 
 113                         //Check if slot is evening 
 114                         //XXX: premium is stored only for Afternoon and Evening 
 115                         } elseif ($slot == 'Evening') { 
 117                                 //XXX: a session is considered premium the eve of a day off 
 118                                 $session->setPremium($premium = $this->isPremium((clone $data['date'])->add(new \
DateInterval('P1D')))); 
 119                         //Check if slot is after 
 120                         } elseif ($slot == 'After') { 
 122                                 //XXX: a session is considered premium the eve of a day off 
 123                                 $premium = $this->isPremium((clone $data['date'])->add(new \
DateInterval('P1D'))); 
 126                         //Set default length at 6h 
 127                         //XXX: date part will be truncated on save 
 128                         $session->setLength(new \
DateTime('06:00:00')); 
 131                         if ($this->isGranted('ROLE_ADMIN')) { 
 133                                 if ($slot == 'Morning') { 
 135                                         $session->setBegin(new \
DateTime('09:00:00')); 
 138                                         $session->setLength(new \
DateTime('05:00:00')); 
 140                                 } elseif ($slot == 'Afternoon') { 
 142                                         $session->setBegin(new \
DateTime('14:00:00')); 
 145                                         $session->setLength(new \
DateTime('05:00:00')); 
 147                                 } elseif ($slot == 'Evening') { 
 149                                         $session->setBegin(new \
DateTime('19:00:00')); 
 151                                         //Check if next day is premium 
 154                                                 $session->setLength(new \
DateTime('07:00:00')); 
 159                                         $session->setBegin(new \
DateTime('01:00:00')); 
 162                                         $session->setLength(new \
DateTime('04:00:00')); 
 164                                         //Check if next day is premium 
 167                                                 $session->setBegin(new \
DateTime('02:00:00')); 
 170                                                 $session->setLength(new \
DateTime('03:00:00')); 
 173                         //Docks => 14h -> 19h | 19h -> 01/02h 
 174                         //XXX: remove Garnier from here to switch back to 21h 
 175                         } elseif (in_array($short, ['Docks', 'Garnier']) && in_array($slot, ['Afternoon', 'Evening', 'After'])) { 
 177                                 if ($slot == 'Afternoon') { 
 179                                         $session->setBegin(new \
DateTime('14:00:00')); 
 182                                         $session->setLength(new \
DateTime('05:00:00')); 
 184                                 } elseif ($slot == 'Evening') { 
 186                                         $session->setBegin(new \
DateTime('19:00:00')); 
 188                                         //Check if next day is premium 
 191                                                 $session->setLength(new \
DateTime('07:00: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                         //Garnier => 21h -> 01/02h 
 211                         } elseif ($short == 'Garnier' && in_array($slot, ['Evening', 'After'])) { 
 213                                 if ($slot == 'Evening') { 
 215                                         $session->setBegin(new \
DateTime('21:00:00')); 
 218                                         $session->setLength(new \
DateTime('05:00:00')); 
 220                                         //Check if next day is premium 
 223                                                 $session->setLength(new \
DateTime('06:00:00')); 
 228                                         $session->setBegin(new \
DateTime('01:00:00')); 
 231                                         $session->setLength(new \
DateTime('04:00:00')); 
 233                                         //Check if next day is premium 
 236                                                 $session->setBegin(new \
DateTime('02:00:00')); 
 239                                                 $session->setLength(new \
DateTime('03:00:00')); 
 242                         //Trocadero|Tokyo|Swan|Honore|Orsay => 19h -> 01/02h 
 243                         } elseif (in_array($short, ['Trocadero', 'Tokyo', 'Swan', 'Honore', 'Orsay']) && in_array($slot, ['Evening', 'After'])) { 
 245                                 if ($slot == 'Evening') { 
 247                                         $session->setBegin(new \
DateTime('19:00:00')); 
 249                                         //Check if next day is premium 
 252                                                 $session->setLength(new \
DateTime('07:00:00')); 
 257                                         $session->setBegin(new \
DateTime('01:00:00')); 
 260                                         $session->setLength(new \
DateTime('04:00:00')); 
 262                                         //Check if next day is premium 
 265                                                 $session->setBegin(new \
DateTime('02:00:00')); 
 268                                                 $session->setLength(new \
DateTime('03:00:00')); 
 271                         //La Villette => 14h -> 19h 
 272                         } elseif ($short == 'Villette' && $slot == 'Afternoon') { 
 274                                 $session->setBegin(new \
DateTime('14:00:00')); 
 277                                 $session->setLength(new \
DateTime('05:00:00')); 
 278                         //Place Colette => 14h -> 21h 
 279                         //TODO: add check here that it's a millegaux account ? 
 280                         } elseif ($short == 'Colette' && $slot == 'Afternoon') { 
 282                                 $session->setBegin(new \
DateTime('14:00:00')); 
 285                                 $session->setLength(new \
DateTime('07:00:00')); 
 286                         //Galerie d'OrlƩans => 14h -> 18h 
 287                         } elseif ($short == 'Orleans' && $slot == 'Afternoon') { 
 289                                 $session->setBegin(new \
DateTime('14:00:00')); 
 292                                 $session->setLength(new \
DateTime('04:00:00')); 
 293                         //Combination not supported 
 295                                 //Add error in flash message 
 296                                 $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($data['slot'])), '%date%' => $data['date']->format('Y-m-d')])); 
 299                                 $section = $this->translator
->trans('Application add'); 
 302                                 $title = $section.' - '.$this->translator
->trans($this->config
['site']['title']); 
 305                                 return $this->render('@RapsysAir/application/add.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView()]+
$this->context
); 
 309                         if (!$this->isGranted('ROLE_ADMIN') && $session->getStart() < new \
DateTime('00:00:00')) { 
 310                                 //Add error in flash message 
 311                                 $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($data['slot'])), '%date%' => $data['date']->format('Y-m-d')])); 
 314                                 $section = $this->translator
->trans('Application add'); 
 317                                 $title = $section.' - '.$this->translator
->trans($this->config
['site']['title']); 
 320                                 return $this->render('@RapsysAir/application/add.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView()]+
$this->context
); 
 324                         $manager->persist($session); 
 326                         //Flush to get the ids 
 329                         $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($data['slot'])), '%date%' => $data['date']->format('Y-m-d')])); 
 333                 $user = $this->getUser(); 
 335                 //Replace with requested user for admin 
 336                 if ($this->isGranted('ROLE_ADMIN') && !empty($data['user'])) { 
 337                         $user = $this->getDoctrine()->getRepository(User
::class)->findOneById($data['user']); 
 340                 //Protect application fetching 
 342                         //Retrieve application 
 343                         $application = $doctrine->getRepository(Application
::class)->findOneBySessionUser($session, $user); 
 345                         //Add warning in flash message 
 346                         $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($data['slot'])), '%date%' => $data['date']->format('Y-m-d')])); 
 347                 //Catch no application and session without identifier (not persisted&flushed) cases 
 348                 } catch (\Doctrine\ORM\NoResultException
|\Doctrine\ORM\ORMInvalidArgumentException 
$e) { 
 349                         //Create the application 
 350                         $application = new Application(); 
 351                         $application->setSession($session); 
 352                         $application->setUser($user); 
 353                         $application->setCreated(new \
DateTime('now')); 
 354                         $application->setUpdated(new \
DateTime('now')); 
 356                         //Refresh session updated field 
 357                         $session->setUpdated(new \
DateTime('now')); 
 360                         $manager->persist($session); 
 362                         //Queue application save 
 363                         $manager->persist($application); 
 365                         //Flush to get the ids 
 368                         //Add notice in flash message 
 369                         $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($data['slot'])), '%date%' => $data['date']->format('Y-m-d')])); 
 372                 //Extract and process referer 
 373                 if ($referer = $request->headers
->get('referer')) { 
 374                         //Create referer request instance 
 375                         $req = Request
::create($referer); 
 378                         $path = $req->getPathInfo(); 
 380                         //Get referer query string 
 381                         $query = $req->getQueryString(); 
 384                         $path = str_replace($request->getScriptName(), '', $path); 
 386                         //Try with referer path 
 389                                 $oldContext = $this->router
->getContext(); 
 391                                 //Force clean context 
 392                                 //XXX: prevent MethodNotAllowedException because current context method is POST in onevendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php+42 
 393                                 $this->router
->setContext(new RequestContext()); 
 395                                 //Retrieve route matching path 
 396                                 $route = $this->router
->match($path); 
 399                                 $this->router
->setContext($oldContext); 
 405                                 $name = $route['_route']; 
 407                                 //Remove route and controller from route defaults 
 408                                 unset($route['_route'], $route['_controller']); 
 411                                 return $this->redirectToRoute($name, ['session' => $session->getId()]+
$route); 
 413                         } catch(MethodNotAllowedException
|ResourceNotFoundException 
$e) { 
 414                                 //Unset referer to fallback to default route 
 419                 //Redirect to cleanup the form 
 420                 return $this->redirectToRoute('rapsys_air', ['session' => $session->getId()]); 
 424          * Compute eastern for selected year 
 426          * @param int $year The eastern year 
 428          * @return DateTime The eastern date 
 430         function getEastern($year) { 
 433                 //Check if already computed 
 434                 if (isset($data[$year])) { 
 435                         //Return computed eastern 
 437                 //Check if data is null 
 438                 } elseif (is_null($data)) { 
 442                 $d = (19 * ($year % 
19) + 
24) % 
30; 
 443                 $e = (2 * ($year % 
4) + 
4 * ($year % 
7) + 
6 * $d + 
5) % 
7; 
 451                 } elseif ($d == 29 && $e == 6) { 
 454                 } elseif ($d == 28 && $e == 6) { 
 459                 //Store eastern in data 
 460                 return ($data[$year] = new \
DateTime(sprintf('%04d-%02d-%02d', $year, $month, $day))); 
 464          * Check if date is a premium day 
 466          * @desc Consider as premium a day off 
 468          * @param DateTime $date The date to check 
 469          * @return bool Whether the date is off or not 
 471         function isPremium($date) { 
 473                 $w = $date->format('w'); 
 475                 //Check if weekend day 
 476                 if ($w == 0 || $w == 6) { 
 477                         //Date is weekend day 
 482                 $d = $date->format('d'); 
 485                 $m = $date->format('m'); 
 487                 //Check if fixed holiday 
 489                         //Check if 1st january 
 490                         ($d == 1 && $m == 1) || 
 492                         ($d == 1 && $m == 5) || 
 494                         ($d == 8 && $m == 5) || 
 496                         ($d == 14 && $m == 7) || 
 497                         //Check if 15st august 
 498                         ($d == 15 && $m == 8) || 
 499                         //Check if 1st november 
 500                         ($d == 1 && $m == 11) || 
 501                         //Check if 11st november 
 502                         ($d == 11 && $m == 11) || 
 503                         //Check if 25st december 
 504                         ($d == 25 && $m == 12) 
 506                         //Date is a fixed holiday 
 511                 $eastern = $this->getEastern($date->format('Y')); 
 513                 //Check dynamic holidays 
 515                         (clone $eastern)->add(new \
DateInterval('P1D')) == $date || 
 516                         (clone $eastern)->add(new \
DateInterval('P39D')) == $date || 
 517                         (clone $eastern)->add(new \
DateInterval('P50D')) == $date 
 519                         //Date is a dynamic holiday 
 523                 //Date is not a holiday and week day