3 namespace Rapsys\AirBundle\Controller
;
5 use Symfony\Component\HttpFoundation\Request
;
6 use Symfony\Component\Routing\RequestContext
;
7 use Symfony\Component\Routing\Exception\MethodNotAllowedException
;
8 use Symfony\Component\Routing\Exception\ResourceNotFoundException
;
9 use Rapsys\AirBundle\Entity\Application
;
10 use Rapsys\AirBundle\Entity\User
;
11 use Rapsys\AirBundle\Entity\Slot
;
12 use Rapsys\AirBundle\Entity\Session
;
13 use Rapsys\AirBundle\Entity\Location
;
15 class SessionController
extends DefaultController
{
19 * @desc Persist session 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 edit(Request
$request, $id) {
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');
37 $doctrine = $this->getDoctrine();
40 $session = $doctrine->getRepository(Session
::class)->fetchOneById($id, $request->getLocale());
45 !$this->isGranted('ROLE_ADMIN') &&
47 $this->getUser()->getId() != $session['au_id'] &&
48 //or application without attributed user
49 $session['au_id'] !== null && !in_array($this->getUser()->getId(), explode("\n", $session['sau_id']))
51 //Prevent non admin and non attributed user access
52 throw $this->createAccessDeniedException();
56 $now = new \
DateTime('now');
58 //Create SessionEditType form
59 $form = $this->createForm('Rapsys\AirBundle\Form\SessionEditType', null, [
61 'action' => $this->generateUrl('rapsys_air_session_edit', [ 'id' => $id ]),
62 //Set the form attribute
65 'admin' => $this->isGranted('ROLE_ADMIN'),
66 //Set default user to current
67 'user' => $this->getUser()->getId(),
69 'begin' => $session['begin'],
71 'length' => $session['length'],
73 'raincancel' => ($this->isGranted('ROLE_ADMIN') || $this->getUser()->getId() == $session['au_id']) && $session['rainfall'] >= 2,
75 'cancel' => $this->isGranted('ROLE_ADMIN') || in_array($this->getUser()->getId(), explode("\n", $session['sau_id'])),
77 'modify' => $this->isGranted('ROLE_ADMIN') || $this->getUser()->getId() == $session['au_id'] && $session['stop'] >= $now && $this->isGranted('ROLE_REGULAR'),
79 'move' => $this->isGranted('ROLE_ADMIN') || $this->getUser()->getId() == $session['au_id'] && $session['stop'] >= $now && $this->isGranted('ROLE_SENIOR'),
81 'attribute' => $this->isGranted('ROLE_ADMIN') && $session['locked'] === null,
83 'session' => $session['id']
86 //Refill the fields in case of invalid form
87 $form->handleRequest($request);
90 #if (true) { $form->isValid();
91 //TODO: mettre une contrainte sur un des boutons submit, je sais pas encore comment
92 if (!$form->isValid()) {
94 $section = $this->translator
->trans('Session %id%', ['%id%' => $id]);
97 $title = $section.' - '.$this->translator
->trans($this->config
['site']['title']);
99 //Add session in context
100 $context['session'] = [
102 'title' => $this->translator
->trans('Session %id%', ['%id%' => $id]),
104 'id' => $session['l_id'],
105 'at' => $this->translator
->trans('at '.$session['l_title'])
109 return $this->render('@RapsysAir/session/edit.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView()]+
$context+
$this->context
);
113 $manager = $doctrine->getManager();
116 $data = $form->getData();
119 $session = $doctrine->getRepository(Session
::class)->findOneById($id);
122 $user = $this->getUser();
124 //Replace with requested user for admin
125 if ($this->isGranted('ROLE_ADMIN') && !empty($data['user'])) {
126 $user = $doctrine->getRepository(User
::class)->findOneById($data['user']);
130 $datetime = new \
DateTime('now');
132 //Set canceled time at start minus one day
133 $canceled = (clone $session->getStart())->sub(new \
DateInterval('P1D'));
137 'raincancel' => $form->has('raincancel') && $form->get('raincancel')->isClicked(),
138 'modify' => $form->has('modify') && $form->get('modify')->isClicked(),
139 'move' => $form->has('move') && $form->get('move')->isClicked(),
140 'cancel' => $form->has('cancel') && $form->get('cancel')->isClicked(),
141 'forcecancel' => $form->has('forcecancel') && $form->get('forcecancel')->isClicked(),
142 'attribute' => $form->has('attribute') && $form->get('attribute')->isClicked(),
143 'autoattribute' => $form->has('autoattribute') && $form->get('autoattribute')->isClicked(),
144 'lock' => $form->has('lock') && $form->get('lock')->isClicked(),
147 //With raincancel and application and (rainfall or admin)
148 if ($action['raincancel'] && ($application = $session->getApplication()) && ($session->getRainfall() >= 2 || $this->isGranted('ROLE_ADMIN'))) {
149 //Cancel application at start minus one day
150 $application->setCanceled($canceled);
153 $application->setUpdated($datetime);
155 //Insufficient rainfall
157 if ($session->getRainfall() < 2) {
159 //XXX: magic cheat score 42
160 $application->setScore(42);
163 //Queue application save
164 $manager->persist($application);
166 //Add notice in flash message
167 $this->addFlash('notice', $this->translator
->trans('Application %id% updated', ['%id%' => $application->getId()]));
170 $session->setUpdated($datetime);
173 $manager->persist($session);
175 //Add notice in flash message
176 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
178 } elseif ($action['modify']) {
180 $session->setBegin($data['begin']);
183 $session->setLength($data['length']);
186 $session->setUpdated($datetime);
189 $manager->persist($session);
191 //Add notice in flash message
192 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
194 } elseif ($action['move']) {
196 $session->setLocation($doctrine->getRepository(Location
::class)->findOneById($data['location']));
199 $session->setUpdated($datetime);
202 $manager->persist($session);
204 //Add notice in flash message
205 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
206 //With cancel or forcecancel
207 } elseif ($action['cancel'] || $action['forcecancel']) {
209 $application = $doctrine->getRepository(Application
::class)->findOneBySessionUser($session, $user);
211 //Not already canceled
212 if ($application->getCanceled() === null) {
214 $application->setCanceled($datetime);
216 //Check if application is session application and (canceled 24h before start or forcecancel (as admin))
217 #if ($session->getApplication() == $application && ($datetime < $canceled || $action['forcecancel'])) {
218 if ($session->getApplication() == $application && $action['forcecancel']) {
220 //XXX: magic cheat score 42
221 $application->setScore(42);
223 //Unattribute session
224 $session->setApplication(null);
227 $session->setUpdated($datetime);
230 $manager->persist($session);
232 //Add notice in flash message
233 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
237 //Uncancel application
238 $application->setCanceled(null);
242 $application->setUpdated($datetime);
244 //Queue application save
245 $manager->persist($application);
247 //Add notice in flash message
248 $this->addFlash('notice', $this->translator
->trans('Application %id% updated', ['%id%' => $application->getId()]));
250 } elseif ($action['attribute']) {
252 $application = $doctrine->getRepository(Application
::class)->findOneBySessionUser($session, $user);
255 if ($application->getCanceled() !== null) {
256 //Uncancel application
257 $application->setCanceled(null);
261 //XXX: magic cheat score 42
262 $application->setScore(42);
265 $application->setUpdated($datetime);
267 //Queue application save
268 $manager->persist($application);
270 //Add notice in flash message
271 $this->addFlash('notice', $this->translator
->trans('Application %id% updated', ['%id%' => $application->getId()]));
273 //Unattribute session
274 $session->setApplication($application);
277 $session->setUpdated($datetime);
280 $manager->persist($session);
282 //Add notice in flash message
283 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
285 } elseif ($action['autoattribute']) {
286 //Get best application
287 //XXX: best application may not issue result while grace time or bad behaviour
288 if (!empty($application = $doctrine->getRepository(Session
::class)->findBestApplicationById($id))) {
290 $session->setApplication($application);
293 $session->setUpdated($datetime);
296 $manager->persist($session);
298 //Add notice in flash message
299 $this->addFlash('notice', $this->translator
->trans('Session %id% auto attributed', ['%id%' => $id]));
302 //Add warning in flash message
303 $this->addFlash('warning', $this->translator
->trans('Session %id% not auto attributed', ['%id%' => $id]));
306 } elseif ($action['lock']) {
308 if ($session->getLocked() !== null) {
313 $session->setLocked(null);
317 if ($application = $session->getApplication()) {
319 //XXX: magic cheat score 42
320 $application->setScore(42);
323 $application->setUpdated($datetime);
325 //Queue application save
326 $manager->persist($application);
328 //Add notice in flash message
329 $this->addFlash('notice', $this->translator
->trans('Application %id% updated', ['%id%' => $application->getId()]));
332 //Unattribute session
333 $session->setApplication(null);
336 $session->setLocked($datetime);
340 # $applications = $doctrine->getRepository(Application::class)->findBySession($session);
343 # if (!empty($applications)) {
344 # //Iterate on each applications
345 # foreach($applications as $application) {
346 # //Cancel application
347 # $application->setCanceled($canceled);
350 # $application->setUpdated($datetime);
352 # //Queue application save
353 # $manager->persist($application);
355 # //Add notice in flash message
356 # $this->addFlash('notice', $this->translator->trans('Application %id% updated', ['%id%' => $application->getId()]));
361 $session->setUpdated($datetime);
364 $manager->persist($session);
366 //Add notice in flash message
367 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
370 //Add warning in flash message
371 $this->addFlash('warning', $this->translator
->trans('Session %id% not updated', ['%id%' => $id]));
374 //Flush to get the ids
377 //Extract and process referer
378 if ($referer = $request->headers
->get('referer')) {
379 //Create referer request instance
380 $req = Request
::create($referer);
383 $path = $req->getPathInfo();
385 //Get referer query string
386 $query = $req->getQueryString();
389 $path = str_replace($request->getScriptName(), '', $path);
391 //Try with referer path
394 $oldContext = $this->router
->getContext();
396 //Force clean context
397 //XXX: prevent MethodNotAllowedException because current context method is POST in onevendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php+42
398 $this->router
->setContext(new RequestContext());
400 //Retrieve route matching path
401 $route = $this->router
->match($path);
404 $this->router
->setContext($oldContext);
410 $name = $route['_route'];
412 //Remove route and controller from route defaults
413 unset($route['_route'], $route['_controller']);
416 return $this->redirectToRoute($name, $route);
418 } catch(MethodNotAllowedException
|ResourceNotFoundException
$e) {
419 //Unset referer to fallback to default route
424 //Redirect to cleanup the form
425 return $this->redirectToRoute('rapsys_air_session_view', ['id' => $id]);
431 * @desc Display all sessions with an application or login form
433 * @param Request $request The request instance
435 * @return Response The rendered view
437 public function index(Request
$request) {
439 $doctrine = $this->getDoctrine();
442 $section = $this->translator
->trans('Sessions');
445 $title = $this->translator
->trans($this->config
['site']['title']).' - '.$section;
450 //Create application form for role_guest
451 if ($this->isGranted('ROLE_GUEST')) {
452 //Create ApplicationType form
453 $application = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [
455 'action' => $this->generateUrl('rapsys_air_application_add'),
456 //Set the form attribute
457 'attr' => [ 'class' => 'col' ],
459 'admin' => $this->isGranted('ROLE_ADMIN'),
460 //Set default user to current
461 'user' => $this->getUser()->getId(),
462 //Set default slot to evening
463 //XXX: default to Evening (3)
464 'slot' => $doctrine->getRepository(Slot
::class)->findOneById(3)
467 //Add form to context
468 $context['application'] = $application->createView();
469 //Create login form for anonymous
470 } elseif (!$this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
471 //Create ApplicationType form
472 $login = $this->createForm('Rapsys\UserBundle\Form\LoginType', null, [
474 'action' => $this->generateUrl('rapsys_user_login'),
475 //Set the form attribute
476 'attr' => [ 'class' => 'col' ]
479 //Add form to context
480 $context['login'] = $login->createView();
484 $period = new \
DatePeriod(
485 //Start from first monday of week
486 new \
DateTime('Monday this week'),
487 //Iterate on each day
488 new \
DateInterval('P1D'),
489 //End with next sunday and 4 weeks
490 new \
DateTime('Monday this week + 5 week')
494 //TODO: highlight with current session route parameter
495 $calendar = $doctrine->getRepository(Session
::class)->fetchCalendarByDatePeriod($this->translator
, $period, null, $request->get('session'), !$this->isGranted('IS_AUTHENTICATED_REMEMBERED'));
498 //XXX: we want to display all active locations anyway
499 $locations = $doctrine->getRepository(Location
::class)->fetchTranslatedLocationByDatePeriod($this->translator
, $period/*, !$this->isGranted('IS_AUTHENTICATED_REMEMBERED')*/);
502 return $this->render('@RapsysAir/session/index.html.twig', ['title' => $title, 'section' => $section, 'calendar' => $calendar, 'locations' => $locations]+
$context+
$this->context
);
508 * @desc Display session by id with an application or login form
510 * @param Request $request The request instance
511 * @param int $id The session id
513 * @return Response The rendered view
515 public function view(Request
$request, $id) {
517 $doctrine = $this->getDoctrine();
520 if (empty($session = $doctrine->getRepository(Session
::class)->fetchOneById($id, $request->getLocale()))) {
521 throw $this->createNotFoundException($this->translator
->trans('Unable to find session: %id%', ['%id%' => $id]));
525 $section = $this->translator
->trans($session['l_title']);
528 $title = $this->translator
->trans($this->config
['site']['title']).' - '.$section.' - '.$this->translator
->trans('Session %id%', ['%id%' => $id]);
533 //Create application form for role_guest
534 if ($this->isGranted('ROLE_GUEST')) {
535 //Create ApplicationType form
536 $application = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [
538 'action' => $this->generateUrl('rapsys_air_application_add'),
539 //Set the form attribute
540 'attr' => [ 'class' => 'col' ],
542 'admin' => $this->isGranted('ROLE_ADMIN'),
543 //Set default user to current
544 'user' => $this->getUser()->getId(),
545 //Set default slot to current
546 'slot' => $this->getDoctrine()->getRepository(Slot
::class)->findOneById($session['t_id']),
547 //Set default location to current
548 'location' => $this->getDoctrine()->getRepository(Location
::class)->findOneById($session['l_id']),
551 //Add form to context
552 $context['application'] = $application->createView();
555 $now = new \
DateTime('now');
557 //Create SessionEditType form
558 $session_edit = $this->createForm('Rapsys\AirBundle\Form\SessionEditType', null, [
560 'action' => $this->generateUrl('rapsys_air_session_edit', [ 'id' => $id ]),
561 //Set the form attribute
562 'attr' => [ 'class' => 'col' ],
564 'admin' => $this->isGranted('ROLE_ADMIN'),
565 //Set default user to current
566 'user' => $this->getUser()->getId(),
568 'begin' => $session['begin'],
570 'length' => $session['length'],
572 'raincancel' => ($this->isGranted('ROLE_ADMIN') || $this->getUser()->getId() == $session['au_id']) && $session['rainfall'] >= 2,
574 'cancel' => $this->isGranted('ROLE_ADMIN') || in_array($this->getUser()->getId(), explode("\n", $session['sau_id'])),
576 'modify' => $this->isGranted('ROLE_ADMIN') || $this->getUser()->getId() == $session['au_id'] && $session['stop'] >= $now && $this->isGranted('ROLE_REGULAR'),
578 'move' => $this->isGranted('ROLE_ADMIN') || $this->getUser()->getId() == $session['au_id'] && $session['stop'] >= $now && $this->isGranted('ROLE_SENIOR'),
580 'attribute' => $this->isGranted('ROLE_ADMIN') && $session['locked'] === null,
582 'session' => $session['id']
585 //Add form to context
586 $context['session_edit'] = $session_edit->createView();
587 //Create login form for anonymous
588 } elseif (!$this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
589 //Create ApplicationType form
590 $login = $this->createForm('Rapsys\UserBundle\Form\LoginType', null, [
592 'action' => $this->generateUrl('rapsys_user_login'),
593 //Set the form attribute
594 'attr' => [ 'class' => 'col' ]
597 //Add form to context
598 $context['login'] = $login->createView();
601 //Add session in context
602 $context['session'] = [
604 'date' => $session['date'],
605 'begin' => $session['begin'],
606 'start' => $session['start'],
607 'length' => $session['length'],
608 'stop' => $session['stop'],
609 'rainfall' => $session['rainfall'] !== null ? $session['rainfall'].' mm' : $session['rainfall'],
610 'rainrisk' => $session['rainrisk'] !== null ? ($session['rainrisk']*100).' %' : $session['rainrisk'],
611 'realfeel' => $session['realfeel'] !== null ? $session['realfeel'].' °C' : $session['realfeel'],
612 'realfeelmin' => $session['realfeelmin'] !== null ? $session['realfeelmin'].' °C' : $session['realfeelmin'],
613 'realfeelmax' => $session['realfeelmax'] !== null ? $session['realfeelmax'].' °C' : $session['realfeelmax'],
614 'temperature' => $session['temperature'] !== null ? $session['temperature'].' °C' : $session['temperature'],
615 'temperaturemin' => $session['temperaturemin'] !== null ? $session['temperaturemin'].' °C' : $session['temperaturemin'],
616 'temperaturemax' => $session['temperaturemax'] !== null ? $session['temperaturemax'].' °C' : $session['temperaturemax'],
617 'locked' => $session['locked'],
618 'created' => $session['created'],
619 'updated' => $session['updated'],
620 'title' => $this->translator
->trans('Session %id%', ['%id%' => $id]),
621 'application' => null,
623 'id' => $session['l_id'],
624 'at' => $this->translator
->trans('at '.$session['l_title']),
625 'short' => $this->translator
->trans($session['l_short']),
626 'title' => $this->translator
->trans($session['l_title']),
627 'address' => $session['l_address'],
628 'zipcode' => $session['l_zipcode'],
629 'city' => $session['l_city'],
630 'latitude' => $session['l_latitude'],
631 'longitude' => $session['l_longitude']
634 'id' => $session['t_id'],
635 'title' => $this->translator
->trans($session['t_title'])
638 'id' => $session['p_id'],
639 'description' => $session['p_description']
641 'applications' => null
645 if (!empty($session['a_id'])) {
646 $context['session']['application'] = [
648 'id' => $session['au_id'],
649 'title' => $session['au_pseudonym'],
650 'donation' => $session['au_donation'],
651 'site' => $session['au_site']
653 'id' => $session['a_id'],
654 'title' => $this->translator
->trans('Application %id%', [ '%id%' => $session['a_id'] ]),
659 if (!empty($session['sa_id'])) {
660 //Extract applications id
661 $session['sa_id'] = explode("\n", $session['sa_id']);
662 //Extract applications score
663 //XXX: score may be null before grant or for bad behaviour, replace NULL with 'NULL' to avoid silent drop in mysql
664 $session['sa_score'] = array_map(function($v){return $v
==='NULL'?null:$v
;}, explode("\n", $session['sa_score']));
665 //Extract applications created
666 $session['sa_created'] = array_map(function($v){return new \
DateTime($v
);}, explode("\n", $session['sa_created']));
667 //Extract applications updated
668 $session['sa_updated'] = array_map(function($v){return new \
DateTime($v
);}, explode("\n", $session['sa_updated']));
669 //Extract applications canceled
670 //XXX: canceled is null before cancelation, replace NULL with 'NULL' to avoid silent drop in mysql
671 $session['sa_canceled'] = array_map(function($v){return $v
==='NULL'?null:new \
DateTime($v
);}, explode("\n", $session['sa_canceled']));
673 //Extract applications user id
674 $session['sau_id'] = explode("\n", $session['sau_id']);
675 //Extract applications user pseudonym
676 $session['sau_pseudonym'] = explode("\n", $session['sau_pseudonym']);
679 $context['session']['applications'] = [];
680 foreach($session['sa_id'] as $i => $sa_id) {
681 $context['session']['applications'][$sa_id] = [
683 'score' => $session['sa_score'][$i],
684 'created' => $session['sa_created'][$i],
685 'updated' => $session['sa_updated'][$i],
686 'canceled' => $session['sa_canceled'][$i]
688 if (!empty($session['sau_id'][$i])) {
689 $context['session']['applications'][$sa_id]['user'] = [
690 'id' => $session['sau_id'][$i],
691 'title' => $session['sau_pseudonym'][$i]
698 $period = new \
DatePeriod(
699 //Start from first monday of week
700 new \
DateTime('Monday this week'),
701 //Iterate on each day
702 new \
DateInterval('P1D'),
703 //End with next sunday and 4 weeks
704 new \
DateTime('Monday this week + 5 week')
708 //XXX: we want to display all active locations anyway
709 $locations = $doctrine->getRepository(Location
::class)->findTranslatedSortedByPeriod($this->translator
, $period, $session['au_id']);
712 return $this->render('@RapsysAir/session/view.html.twig', ['title' => $title, 'section' => $section, 'locations' => $locations]+
$context+
$this->context
);