]> Raphaël G. Git Repositories - airbundle/blob - Controller/ApplicationController.php
Upgrade date and time to type cosntraint
[airbundle] / Controller / ApplicationController.php
1 <?php declare(strict_types=1);
2
3 /*
4 * This file is part of the Rapsys AirBundle package.
5 *
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Rapsys\AirBundle\Controller;
13
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;
22
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;
29
30 /**
31 * {@inheritdoc}
32 */
33 class ApplicationController extends AbstractController {
34 /**
35 * Add application
36 *
37 * @desc Persist application and all required dependencies in database
38 *
39 * @param Request $request The request instance
40 * @param Registry $manager The doctrine registry
41 * @param EntityManagerInterface $manager The doctrine entity manager
42 *
43 * @return Response The rendered view or redirection
44 *
45 * @throws \RuntimeException When user has not at least guest role
46 */
47 public function add(Request $request) {
48 //Prevent non-guest to access here
49 $this->denyAccessUnlessGranted('ROLE_GUEST', null, $this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Guest')]));
50
51 //Get favorites dances
52 $danceFavorites = $this->doctrine->getRepository(Dance::class)->findByUserId($this->getUser()->getId());
53
54 //Set dance default
55 $danceDefault = !empty($danceFavorites)?current($danceFavorites):null;
56
57
58 //Get favorites locations
59 $locationFavorites = $this->doctrine->getRepository(Location::class)->findByUserId($this->getUser()->getId());
60
61 //Set location default
62 $locationDefault = !empty($locationFavorites)?current($locationFavorites):null;
63
64 //With admin
65 if ($this->isGranted('ROLE_ADMIN')) {
66 //Get dances
67 $dances = $this->doctrine->getRepository(Dance::class)->findAll();
68
69 //Get locations
70 $locations = $this->doctrine->getRepository(Location::class)->findAll();
71 //Without admin
72 } else {
73 //Restrict to favorite dances
74 $dances = $danceFavorites;
75
76 //Reset favorites
77 $danceFavorites = [];
78
79 //Restrict to favorite locations
80 $locations = $locationFavorites;
81
82 //Reset favorites
83 $locationFavorites = [];
84 }
85
86 //Create ApplicationType form
87 $form = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [
88 //Set the action
89 'action' => $this->generateUrl('rapsys_air_application_add'),
90 //Set the form attribute
91 #'attr' => [ 'class' => 'col' ],
92 //Set dance choices
93 'dance_choices' => $dances,
94 //Set dance default
95 'dance_default' => $danceDefault,
96 //Set dance favorites
97 'dance_favorites' => $danceFavorites,
98 //Set location choices
99 'location_choices' => $locations,
100 //Set location default
101 'location_default' => $locationDefault,
102 //Set location favorites
103 'location_favorites' => $locationFavorites,
104 //With user
105 'user' => $this->isGranted('ROLE_ADMIN'),
106 //Set user choices
107 'user_choices' => $this->doctrine->getRepository(User::class)->findIndexByGroupPseudonym(),
108 //Set default user to current
109 'user_default' => $this->getUser()->getId(),
110 //Set default slot to evening
111 //XXX: default to Evening (3)
112 'slot_default' => $this->doctrine->getRepository(Slot::class)->findOneByTitle('Evening')
113 ]);
114
115 //Refill the fields in case of invalid form
116 $form->handleRequest($request);
117
118 //Handle invalid form
119 if (!$form->isSubmitted() || !$form->isValid()) {
120 //Set title
121 $title = $this->translator->trans('Application add');
122
123 //Render the view
124 return $this->render('@RapsysAir/application/add.html.twig', ['title' => $title, 'form' => $form->createView()]+$this->context);
125 }
126
127 //Get data
128 $data = $form->getData();
129
130 //Protect session fetching
131 try {
132 //Fetch session
133 $session = $this->doctrine->getRepository(Session::class)->findOneByLocationSlotDate($data['location'], $data['slot'], $data['date']);
134 //Catch no session case
135 } catch (NoResultException $e) {
136 //Create the session
137 $session = new Session();
138 $session->setLocation($data['location']);
139 $session->setDate($data['date']);
140 $session->setSlot($data['slot']);
141
142 //Get location
143 $location = $data['location']->getTitle();
144
145 //Get slot
146 $slot = $data['slot']->getTitle();
147
148 //Get premium
149 //XXX: premium is stored only for Afternoon and Evening
150 $premium = $session->isPremium();
151
152 //Set default length at 6h
153 //XXX: date part will be truncated on save
154 $session->setLength(new \DateTime('06:00:00'));
155
156 //Check if admin
157 if ($this->isGranted('ROLE_ADMIN')) {
158 //Check if morning
159 if ($slot == 'Morning') {
160 //Set begin at 9h
161 $session->setBegin(new \DateTime('09:00:00'));
162
163 //Set length at 5h
164 $session->setLength(new \DateTime('05:00:00'));
165 //Check if afternoon
166 } elseif ($slot == 'Afternoon') {
167 //Set begin at 18h
168 $session->setBegin(new \DateTime('14:00:00'));
169
170 //Set length at 5h
171 $session->setLength(new \DateTime('05:00:00'));
172 //Check if evening
173 } elseif ($slot == 'Evening') {
174 //Set begin at 19h00
175 $session->setBegin(new \DateTime('19:00:00'));
176
177 //Set length at 5h
178 $session->setLength(new \DateTime('06:00:00'));
179
180 //Check if next day is premium
181 if ($premium) {
182 //Set length at 7h
183 $session->setLength(new \DateTime('07:00:00'));
184 }
185 //Check if after
186 } else {
187 //Set begin at 1h
188 $session->setBegin(new \DateTime('01:00:00'));
189
190 //Set length at 4h
191 $session->setLength(new \DateTime('04:00:00'));
192
193 //Check if next day is premium
194 if ($premium) {
195 //Set begin at 2h
196 $session->setBegin(new \DateTime('02:00:00'));
197
198 //Set length at 3h
199 $session->setLength(new \DateTime('03:00:00'));
200 }
201 }
202 //Tino-Rossi garden => 14h -> 19h | 19h -> 01/02h
203 } elseif (in_array($location, ['Tino-Rossi garden']) && in_array($slot, ['Afternoon', 'Evening', 'After'])) {
204 //Check if afternoon
205 if ($slot == 'Afternoon') {
206 //Set begin at 14h
207 $session->setBegin(new \DateTime('14:00:00'));
208
209 //Set length at 5h
210 $session->setLength(new \DateTime('05:00:00'));
211 //Check if evening
212 } elseif ($slot == 'Evening') {
213 //Set begin at 19h
214 $session->setBegin(new \DateTime('19:00:00'));
215
216 //Check if next day is premium
217 if ($premium) {
218 //Set length at 7h
219 $session->setLength(new \DateTime('07:00:00'));
220 }
221 //Check if after
222 } else {
223 //Set begin at 1h
224 $session->setBegin(new \DateTime('01:00:00'));
225
226 //Set length at 4h
227 $session->setLength(new \DateTime('04:00:00'));
228
229 //Check if next day is premium
230 if ($premium) {
231 //Set begin at 2h
232 $session->setBegin(new \DateTime('02:00:00'));
233
234 //Set length at 3h
235 $session->setLength(new \DateTime('03:00:00'));
236 }
237 }
238 //Garnier opera => 21h -> 01/02h
239 } elseif ($location == 'Garnier opera' && in_array($slot, ['Evening', 'After'])) {
240 //Check if evening
241 if ($slot == 'Evening') {
242 //Set begin at 21h
243 $session->setBegin(new \DateTime('21:00:00'));
244
245 //Set length at 5h
246 $session->setLength(new \DateTime('05:00:00'));
247
248 //Check if next day is premium
249 if ($premium) {
250 //Set length at 6h
251 $session->setLength(new \DateTime('06:00:00'));
252 }
253 //Check if after
254 } else {
255 //Set begin at 1h
256 $session->setBegin(new \DateTime('01:00:00'));
257
258 //Set length at 4h
259 $session->setLength(new \DateTime('04:00:00'));
260
261 //Check if next day is premium
262 if ($premium) {
263 //Set begin at 2h
264 $session->setBegin(new \DateTime('02:00:00'));
265
266 //Set length at 3h
267 $session->setLength(new \DateTime('03:00:00'));
268 }
269 }
270 //Trocadero esplanade|Tokyo palace|Swan island|Saint-Honore market|Orsay museum => 19h -> 01/02h
271 } elseif (in_array($location, ['Trocadero esplanade', 'Tokyo palace', 'Swan island', 'Saint-Honore market', 'Orsay museum']) && in_array($slot, ['Evening', 'After'])) {
272 //Check if evening
273 if ($slot == 'Evening') {
274 //Set begin at 19h
275 $session->setBegin(new \DateTime('19:00:00'));
276
277 //Check if next day is premium
278 if ($premium) {
279 //Set length at 7h
280 $session->setLength(new \DateTime('07:00:00'));
281 }
282 //Check if after
283 } else {
284 //Set begin at 1h
285 $session->setBegin(new \DateTime('01:00:00'));
286
287 //Set length at 4h
288 $session->setLength(new \DateTime('04:00:00'));
289
290 //Check if next day is premium
291 if ($premium) {
292 //Set begin at 2h
293 $session->setBegin(new \DateTime('02:00:00'));
294
295 //Set length at 3h
296 $session->setLength(new \DateTime('03:00:00'));
297 }
298 }
299 //Drawings' garden (Villette) => 14h -> 19h
300 } elseif ($location == 'Drawings\' garden' && $slot == 'Afternoon') {
301 //Set begin at 14h
302 $session->setBegin(new \DateTime('14:00:00'));
303
304 //Set length at 5h
305 $session->setLength(new \DateTime('05:00:00'));
306 //Colette place => 14h -> 21h
307 //TODO: add check here that it's a millegaux account ?
308 } elseif ($location == 'Colette place' && $slot == 'Afternoon') {
309 //Set begin at 14h
310 $session->setBegin(new \DateTime('14:00:00'));
311
312 //Set length at 7h
313 $session->setLength(new \DateTime('07:00:00'));
314 //Orleans gallery => 14h -> 18h
315 } elseif ($location == 'Orleans gallery' && $slot == 'Afternoon') {
316 //Set begin at 14h
317 $session->setBegin(new \DateTime('14:00:00'));
318
319 //Set length at 4h
320 $session->setLength(new \DateTime('04:00:00'));
321 //Monde garden => 14h -> 19h
322 //TODO: add check here that it's a raphael account ?
323 } elseif ($location == 'Monde garden' && $slot == 'Afternoon') {
324 //Set begin at 14h
325 $session->setBegin(new \DateTime('14:00:00'));
326
327 //Set length at 4h
328 $session->setLength(new \DateTime('05:00:00'));
329 //Combination not supported
330 //TODO: add Madeleine place|Bastille place|Vendome place ?
331 } else {
332 //Add error in flash message
333 $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')]));
334
335 //Set title
336 $title = $this->translator->trans('Application add');
337
338 //Render the view
339 return $this->render('@RapsysAir/application/add.html.twig', ['title' => $title, 'form' => $form->createView()]+$this->context);
340 }
341
342 //Check if admin
343 if (!$this->isGranted('ROLE_ADMIN') && $session->getStart() < new \DateTime('00:00:00')) {
344 //Add error in flash message
345 $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')]));
346
347 //Set title
348 $title = $this->translator->trans('Application add');
349
350 //Render the view
351 return $this->render('@RapsysAir/application/add.html.twig', ['title' => $title, 'form' => $form->createView()]+$this->context);
352 }
353
354 //Queue session save
355 $this->manager->persist($session);
356
357 //Flush to get the ids
358 #$this->manager->flush();
359
360 $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')]));
361 }
362
363 //Set user
364 $user = $this->getUser();
365
366 //Replace with requested user for admin
367 if ($this->isGranted('ROLE_ADMIN') && !empty($data['user'])) {
368 $user = $this->getDoctrine()->getRepository(User::class)->findOneById($data['user']);
369 }
370
371 //Protect application fetching
372 try {
373 //Retrieve application
374 $application = $this->doctrine->getRepository(Application::class)->findOneBySessionUser($session, $user);
375
376 //Add warning in flash message
377 $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')]));
378 //Catch no application and session without identifier (not persisted&flushed) cases
379 } catch (NoResultException|ORMInvalidArgumentException $e) {
380 //Create the application
381 $application = new Application();
382 $application->setDance($data['dance']);
383 $application->setSession($session);
384 $application->setUser($user);
385
386 //Refresh session updated field
387 $session->setUpdated(new \DateTime('now'));
388
389 //Queue session save
390 $this->manager->persist($session);
391
392 //Queue application save
393 $this->manager->persist($application);
394
395 //Flush to get the ids
396 $this->manager->flush();
397
398 //Add notice in flash message
399 $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')]));
400 }
401
402 //Extract and process referer
403 if ($referer = $request->headers->get('referer')) {
404 //Create referer request instance
405 $req = Request::create($referer);
406
407 //Get referer path
408 $path = $req->getPathInfo();
409
410 //Get referer query string
411 $query = $req->getQueryString();
412
413 //Remove script name
414 $path = str_replace($request->getScriptName(), '', $path);
415
416 //Try with referer path
417 try {
418 //Save old context
419 $oldContext = $this->router->getContext();
420
421 //Force clean context
422 //XXX: prevent MethodNotAllowedException because current context method is POST in onevendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php+42
423 $this->router->setContext(new RequestContext());
424
425 //Retrieve route matching path
426 $route = $this->router->match($path);
427
428 //Reset context
429 $this->router->setContext($oldContext);
430
431 //Clear old context
432 unset($oldContext);
433
434 //Extract name
435 $name = $route['_route'];
436
437 //Remove route and controller from route defaults
438 unset($route['_route'], $route['_controller']);
439
440 //Check if session view route
441 if ($name == 'rapsys_air_session_view' && !empty($route['id'])) {
442 //Replace id
443 $route['id'] = $session->getId();
444 //Other routes
445 } else {
446 //Set session
447 $route['session'] = $session->getId();
448 }
449
450 //Generate url
451 return $this->redirectToRoute($name, $route);
452 //No route matched
453 } catch (MethodNotAllowedException|ResourceNotFoundException $e) {
454 //Unset referer to fallback to default route
455 unset($referer);
456 }
457 }
458
459 //Redirect to cleanup the form
460 return $this->redirectToRoute('rapsys_air', ['session' => $session->getId()]);
461 }
462 }