]> Raphaƫl G. Git Repositories - airbundle/blob - Controller/DefaultController.php
Add calendar command
[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 }