]> Raphaƫl G. Git Repositories - airbundle/blob - Controller/DefaultController.php
Add user edit forms
[airbundle] / Controller / DefaultController.php
1 <?php
2
3 namespace Rapsys\AirBundle\Controller;
4
5 use Rapsys\AirBundle\Entity\Application;
6 use Rapsys\AirBundle\Entity\Location;
7 use Rapsys\AirBundle\Entity\Session;
8 use Rapsys\AirBundle\Entity\Slot;
9 use Rapsys\AirBundle\Entity\User;
10 use Rapsys\AirBundle\Pdf\DisputePdf;
11 use Rapsys\UserBundle\Utils\Slugger;
12 use Symfony\Bridge\Twig\Mime\TemplatedEmail;
13 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
14 use Symfony\Component\DependencyInjection\ContainerInterface;
15 use Symfony\Component\Form\FormError;
16 use Symfony\Component\HttpFoundation\Request;
17 use Symfony\Component\HttpFoundation\RequestStack;
18 use Symfony\Component\HttpFoundation\Response;
19 use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
20 use Symfony\Component\Mailer\MailerInterface;
21 use Symfony\Component\Mime\Address;
22 use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
23 use Symfony\Component\Routing\RouterInterface;
24 use Symfony\Component\Translation\TranslatorInterface;
25 use Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait;
26 use Symfony\Component\DependencyInjection\ContainerAwareTrait;
27
28
29 class DefaultController {
30 use ControllerTrait {
31 //Rename render as _render
32 render as protected _render;
33 }
34
35 ///Config array
36 protected $config;
37
38 ///Context array
39 protected $context;
40
41 ///Router instance
42 protected $router;
43
44 ///Translator instance
45 protected $translator;
46
47 /**
48 * @var ContainerInterface
49 */
50 protected $container;
51
52 /**
53 * Inject container and translator interface
54 *
55 * @param ContainerInterface $container The container instance
56 * @param RouterInterface $router The router instance
57 * @param TranslatorInterface $translator The translator instance
58 */
59 public function __construct(ContainerInterface $container, RouterInterface $router, RequestStack $requestStack, TranslatorInterface $translator) {
60 //Retrieve config
61 $this->config = $container->getParameter($this->getAlias());
62
63 //Set the container
64 $this->container = $container;
65
66 //Set the router
67 $this->router = $router;
68
69 //Set the translator
70 $this->translator = $translator;
71
72 //Set the context
73 $this->context = [
74 'copy' => [
75 'by' => $translator->trans($this->config['copy']['by']),
76 'link' => $this->config['copy']['link'],
77 'long' => $translator->trans($this->config['copy']['long']),
78 'short' => $translator->trans($this->config['copy']['short']),
79 'title' => $this->config['copy']['title']
80 ],
81 'site' => [
82 'ico' => $this->config['site']['ico'],
83 'logo' => $this->config['site']['logo'],
84 'png' => $this->config['site']['png'],
85 'svg' => $this->config['site']['svg'],
86 'title' => $translator->trans($this->config['site']['title']),
87 'url' => $router->generate($this->config['site']['url']),
88 ],
89 'canonical' => null,
90 'alternates' => [],
91 'forms' => []
92 ];
93
94 //Get current locale
95 #$currentLocale = $router->getContext()->getParameters()['_locale'];
96 $currentLocale = $requestStack->getCurrentRequest()->getLocale();
97
98 //Set translator locale
99 //XXX: allow LocaleSubscriber on the fly locale change for first page
100 $this->translator->setLocale($currentLocale);
101
102 //Iterate on locales excluding current one
103 foreach($this->config['locales'] as $locale) {
104 //Set titles
105 $titles = [];
106
107 //Iterate on other locales
108 foreach(array_diff($this->config['locales'], [$locale]) as $other) {
109 $titles[$other] = $translator->trans($this->config['languages'][$locale], [], null, $other);
110 }
111
112 //Get context path
113 $path = $router->getContext()->getPathInfo();
114
115 //Retrieve route matching path
116 $route = $router->match($path);
117
118 //Get route name
119 $name = $route['_route'];
120
121 //Unset route name
122 unset($route['_route']);
123
124 //With current locale
125 if ($locale == $currentLocale) {
126 //Set locale locales context
127 $this->context['canonical'] = $router->generate($name, ['_locale' => $locale]+$route, UrlGeneratorInterface::ABSOLUTE_URL);
128 } else {
129 //Set locale locales context
130 $this->context['alternates'][] = [
131 'lang' => $locale,
132 'absolute' => $router->generate($name, ['_locale' => $locale]+$route, UrlGeneratorInterface::ABSOLUTE_URL),
133 'relative' => $router->generate($name, ['_locale' => $locale]+$route),
134 'title' => implode('/', $titles),
135 'translated' => $translator->trans($this->config['languages'][$locale], [], null, $locale)
136 ];
137 }
138 }
139 }
140
141 /**
142 * The contact page
143 *
144 * @desc Send a contact mail to configured contact
145 *
146 * @param Request $request The request instance
147 * @param MailerInterface $mailer The mailer instance
148 *
149 * @return Response The rendered view or redirection
150 */
151 public function contact(Request $request, MailerInterface $mailer): Response {
152 //Set section
153 $section = $this->translator->trans('Contact');
154
155 //Set description
156 $this->context['description'] = $this->translator->trans('Contact Libre Air');
157
158 //Set keywords
159 $this->context['keywords'] = [
160 $this->translator->trans('contact'),
161 $this->translator->trans('Libre Air'),
162 $this->translator->trans('outdoor'),
163 $this->translator->trans('Argentine Tango'),
164 $this->translator->trans('calendar')
165 ];
166
167 //Set title
168 $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
169
170 //Create the form according to the FormType created previously.
171 //And give the proper parameters
172 $form = $this->createForm('Rapsys\AirBundle\Form\ContactType', null, [
173 'action' => $this->generateUrl('rapsys_air_contact'),
174 'method' => 'POST'
175 ]);
176
177 if ($request->isMethod('POST')) {
178 // Refill the fields in case the form is not valid.
179 $form->handleRequest($request);
180
181 if ($form->isValid()) {
182 //Get data
183 $data = $form->getData();
184
185 //Create message
186 $message = (new TemplatedEmail())
187 //Set sender
188 ->from(new Address($data['mail'], $data['name']))
189 //Set recipient
190 //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
191 ->to(new Address($this->config['contact']['mail'], $this->config['contact']['name']))
192 //Set subject
193 ->subject($data['subject'])
194
195 //Set path to twig templates
196 ->htmlTemplate('@RapsysAir/mail/contact.html.twig')
197 ->textTemplate('@RapsysAir/mail/contact.text.twig')
198
199 //Set context
200 ->context(
201 [
202 'subject' => $data['subject'],
203 'message' => strip_tags($data['message']),
204 ]+$this->context
205 );
206
207 //Try sending message
208 //XXX: mail delivery may silently fail
209 try {
210 //Send message
211 $mailer->send($message);
212
213 //Redirect on the same route with sent=1 to cleanup form
214 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+$request->get('_route_params'));
215 //Catch obvious transport exception
216 } catch(TransportExceptionInterface $e) {
217 if ($message = $e->getMessage()) {
218 //Add error message mail unreachable
219 $form->get('mail')->addError(new FormError($this->translator->trans('Unable to contact: %mail%: %message%', ['%mail%' => $this->config['contact']['mail'], '%message%' => $this->translator->trans($message)])));
220 } else {
221 //Add error message mail unreachable
222 $form->get('mail')->addError(new FormError($this->translator->trans('Unable to contact: %mail%', ['%mail%' => $this->config['contact']['mail']])));
223 }
224 }
225 }
226 }
227
228 //Render template
229 return $this->render('@RapsysAir/form/contact.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->context);
230 }
231
232
233 /**
234 * The dispute page
235 *
236 * @desc Generate a dispute document
237 *
238 * @param Request $request The request instance
239 * @param MailerInterface $mailer The mailer instance
240 *
241 * @return Response The rendered view or redirection
242 */
243 public function dispute(Request $request, MailerInterface $mailer): Response {
244 //Prevent non-guest to access here
245 $this->denyAccessUnlessGranted('ROLE_USER', null, $this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('User')]));
246 //Set section
247 $section = $this->translator->trans('Dispute');
248
249 //Set description
250 $this->context['description'] = $this->translator->trans('Libre Air dispute');
251
252 //Set keywords
253 $this->context['keywords'] = [
254 $this->translator->trans('dispute'),
255 $this->translator->trans('Libre Air'),
256 $this->translator->trans('outdoor'),
257 $this->translator->trans('Argentine Tango'),
258 $this->translator->trans('calendar')
259 ];
260
261 //Set title
262 $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
263
264 //Create the form according to the FormType created previously.
265 //And give the proper parameters
266 $form = $this->createForm('Rapsys\AirBundle\Form\DisputeType', ['court' => 'Paris', 'abstract' => 'Pour constater cette prĆ©tendue infraction, les agents verbalisateurs ont pĆ©nĆ©trĆ© dans un jardin privatif, sans visibilitĆ© depuis la voie publique, situĆ© derriĆØre un batiment privĆ©, pour ce faire ils ont franchi au moins un grillage de chantier ou des potteaux mĆ©talliques sĆ©parant le terrain privĆ© de la voie publique de l\'autre cĆ“tĆ© du batiment.'], [
267 'action' => $this->generateUrl('rapsys_air_dispute'),
268 'method' => 'POST'
269 ]);
270
271 if ($request->isMethod('POST')) {
272 // Refill the fields in case the form is not valid.
273 $form->handleRequest($request);
274
275 if ($form->isValid()) {
276 //Get data
277 $data = $form->getData();
278
279 //Gathering offense
280 if (!empty($data['offense']) && $data['offense'] == 'gathering') {
281 //Add gathering
282 $output = DisputePdf::genGathering($data['court'], $data['notice'], $data['agent'], $data['service'], $data['abstract'], $this->translator->trans($this->getUser()->getCivility()->getTitle()), $this->getUser()->getForename(), $this->getUser()->getSurname());
283 //Traffic offense
284 } elseif (!empty($data['offense'] && $data['offense'] == 'traffic')) {
285 //Add traffic
286 $output = DisputePdf::genTraffic($data['court'], $data['notice'], $data['agent'], $data['service'], $data['abstract'], $this->translator->trans($this->getUser()->getCivility()->getTitle()), $this->getUser()->getForename(), $this->getUser()->getSurname());
287 //Unsupported offense
288 } else {
289 header('Content-Type: text/plain');
290 die('TODO');
291 exit;
292 }
293
294 //Send common headers
295 header('Content-Type: application/pdf');
296
297 //Send remaining headers
298 header('Cache-Control: private, max-age=0, must-revalidate');
299 header('Pragma: public');
300
301 //Send content-length
302 header('Content-Length: '.strlen($output));
303
304 //Display the pdf
305 echo $output;
306
307 //Die for now
308 exit;
309
310 # //Create message
311 # $message = (new TemplatedEmail())
312 # //Set sender
313 # ->from(new Address($data['mail'], $data['name']))
314 # //Set recipient
315 # //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
316 # ->to(new Address($this->config['contact']['mail'], $this->config['contact']['name']))
317 # //Set subject
318 # ->subject($data['subject'])
319 #
320 # //Set path to twig templates
321 # ->htmlTemplate('@RapsysAir/mail/contact.html.twig')
322 # ->textTemplate('@RapsysAir/mail/contact.text.twig')
323 #
324 # //Set context
325 # ->context(
326 # [
327 # 'subject' => $data['subject'],
328 # 'message' => strip_tags($data['message']),
329 # ]+$this->context
330 # );
331 #
332 # //Try sending message
333 # //XXX: mail delivery may silently fail
334 # try {
335 # //Send message
336 # $mailer->send($message);
337 #
338 # //Redirect on the same route with sent=1 to cleanup form
339 # return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+$request->get('_route_params'));
340 # //Catch obvious transport exception
341 # } catch(TransportExceptionInterface $e) {
342 # if ($message = $e->getMessage()) {
343 # //Add error message mail unreachable
344 # $form->get('mail')->addError(new FormError($this->translator->trans('Unable to contact: %mail%: %message%', ['%mail%' => $this->config['contact']['mail'], '%message%' => $this->translator->trans($message)])));
345 # } else {
346 # //Add error message mail unreachable
347 # $form->get('mail')->addError(new FormError($this->translator->trans('Unable to contact: %mail%', ['%mail%' => $this->config['contact']['mail']])));
348 # }
349 # }
350 }
351 }
352
353 //Render template
354 return $this->render('@RapsysAir/default/dispute.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->context);
355 }
356
357 /**
358 * The index page
359 *
360 * @desc Display all granted sessions with an application or login form
361 *
362 * @param Request $request The request instance
363 *
364 * @return Response The rendered view
365 */
366 public function index(Request $request): Response {
367 //Fetch doctrine
368 $doctrine = $this->getDoctrine();
369
370 //Set section
371 $section = $this->translator->trans('Argentine Tango in Paris');
372
373 //Set description
374 $this->context['description'] = $this->translator->trans('Outdoor Argentine Tango session calendar in Paris');
375
376 //Set keywords
377 $this->context['keywords'] = [
378 $this->translator->trans('Argentine Tango'),
379 $this->translator->trans('Paris'),
380 $this->translator->trans('outdoor'),
381 $this->translator->trans('calendar'),
382 $this->translator->trans('Libre Air')
383 ];
384
385 //Set title
386 $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
387
388 //Compute period
389 $period = new \DatePeriod(
390 //Start from first monday of week
391 new \DateTime('Monday this week'),
392 //Iterate on each day
393 new \DateInterval('P1D'),
394 //End with next sunday and 4 weeks
395 new \DateTime(
396 $this->isGranted('IS_AUTHENTICATED_REMEMBERED')?'Monday this week + 3 week':'Monday this week + 2 week'
397 )
398 );
399
400 //Fetch calendar
401 $calendar = $doctrine->getRepository(Session::class)->fetchCalendarByDatePeriod($this->translator, $period, null, $request->get('session'), !$this->isGranted('IS_AUTHENTICATED_REMEMBERED'));
402
403 //Fetch locations
404 //XXX: we want to display all active locations anyway
405 $locations = $doctrine->getRepository(Location::class)->findTranslatedSortedByPeriod($this->translator, $period);
406
407 //Render the view
408 return $this->render('@RapsysAir/default/index.html.twig', ['title' => $title, 'section' => $section, 'calendar' => $calendar, 'locations' => $locations]+$this->context);
409
410 //Set Cache-Control must-revalidate directive
411 //TODO: add a javascript forced refresh after 1h ? or header refresh ?
412 #$response->setPublic(true);
413 #$response->setMaxAge(300);
414 #$response->mustRevalidate();
415 ##$response->setCache(['public' => true, 'max_age' => 300]);
416
417 //Return the response
418 #return $response;
419 }
420
421 /**
422 * The organizer regulation page
423 *
424 * @desc Display the organizer regulation policy
425 *
426 * @return Response The rendered view
427 */
428 public function organizerRegulation(): Response {
429 //Set section
430 $section = $this->translator->trans('Organizer regulation');
431
432 //Set description
433 $this->context['description'] = $this->translator->trans('Libre Air organizer regulation');
434
435 //Set keywords
436 $this->context['keywords'] = [
437 $this->translator->trans('organizer regulation'),
438 $this->translator->trans('Libre Air')
439 ];
440
441 //Set title
442 $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
443
444 //Render template
445 return $this->render('@RapsysAir/default/organizer_regulation.html.twig', ['title' => $title, 'section' => $section]+$this->context);
446 }
447
448 /**
449 * The terms of service page
450 *
451 * @desc Display the terms of service policy
452 *
453 * @return Response The rendered view
454 */
455 public function termsOfService(): Response {
456 //Set section
457 $section = $this->translator->trans('Terms of service');
458
459 //Set description
460 $this->context['description'] = $this->translator->trans('Libre Air terms of service');
461
462 //Set keywords
463 $this->context['keywords'] = [
464 $this->translator->trans('terms of service'),
465 $this->translator->trans('Libre Air')
466 ];
467
468 //Set title
469 $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
470
471 //Render template
472 return $this->render('@RapsysAir/default/terms_of_service.html.twig', ['title' => $title, 'section' => $section]+$this->context);
473 }
474
475 /**
476 * The frequently asked questions page
477 *
478 * @desc Display the frequently asked questions
479 *
480 * @return Response The rendered view
481 */
482 public function frequentlyAskedQuestions(): Response {
483 //Set section
484 $section = $this->translator->trans('Frequently asked questions');
485
486 //Set description
487 $this->context['description'] = $this->translator->trans('Libre Air frequently asked questions');
488
489 //Set keywords
490 $this->context['keywords'] = [
491 $this->translator->trans('frequently asked questions'),
492 $this->translator->trans('faq'),
493 $this->translator->trans('Libre Air')
494 ];
495
496 //Set title
497 $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
498
499 //Render template
500 return $this->render('@RapsysAir/default/frequently_asked_questions.html.twig', ['title' => $title, 'section' => $section]+$this->context);
501 }
502
503 /**
504 * Return the bundle alias
505 *
506 * {@inheritdoc}
507 */
508 public function getAlias(): string {
509 return 'rapsys_air';
510 }
511
512 /**
513 * Renders a view
514 *
515 * {@inheritdoc}
516 */
517 protected function render(string $view, array $parameters = [], Response $response = null): Response {
518 //Create application form for role_guest
519 if ($this->isGranted('ROLE_GUEST')) {
520 //Without application form
521 if (empty($parameters['forms']['application'])) {
522 //Fetch doctrine
523 $doctrine = $this->getDoctrine();
524
525 //Create ApplicationType form
526 $application = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [
527 //Set the action
528 'action' => $this->generateUrl('rapsys_air_application_add'),
529 //Set the form attribute
530 'attr' => [ 'class' => 'col' ],
531 //Set admin
532 'admin' => $this->isGranted('ROLE_ADMIN'),
533 //Set default user to current
534 'user' => $this->getUser()->getId(),
535 //Set default slot to evening
536 //XXX: default to Evening (3)
537 'slot' => $doctrine->getRepository(Slot::class)->findOneById(3)
538 ]);
539
540 //Add form to context
541 $parameters['forms']['application'] = $application->createView();
542 }
543 //Create login form for anonymous
544 } elseif (!$this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
545 //Create ApplicationType form
546 $login = $this->createForm('Rapsys\UserBundle\Form\LoginType', null, [
547 //Set the action
548 'action' => $this->generateUrl('rapsys_user_login'),
549 //Set the form attribute
550 'attr' => [ 'class' => 'col' ]
551 ]);
552
553 //Add form to context
554 $parameters['forms']['login'] = $login->createView();
555 }
556
557 //Call parent method
558 return $this->_render($view, $parameters, $response);
559 }
560 }