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