3 namespace Rapsys\AirBundle\Controller
;
5 use Symfony\Bridge\Twig\Mime\TemplatedEmail
;
6 use Symfony\Bundle\FrameworkBundle\Controller\AbstractController
;
7 use Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait
;
8 use Symfony\Component\Asset\Packages
;
9 use Symfony\Component\Filesystem\Exception\IOExceptionInterface
;
10 use Symfony\Component\Filesystem\Filesystem
;
11 use Symfony\Component\DependencyInjection\ContainerAwareTrait
;
12 use Symfony\Component\DependencyInjection\ContainerInterface
;
13 use Symfony\Component\Form\FormError
;
14 use Symfony\Component\HttpFoundation\Request
;
15 use Symfony\Component\HttpFoundation\RequestStack
;
16 use Symfony\Component\HttpFoundation\Response
;
17 use Symfony\Component\Mailer\Exception\TransportExceptionInterface
;
18 use Symfony\Component\Mailer\MailerInterface
;
19 use Symfony\Component\Mime\Address
;
20 use Symfony\Component\Routing\Generator\UrlGeneratorInterface
;
21 use Symfony\Component\Routing\RouterInterface
;
22 use Symfony\Component\Translation\TranslatorInterface
;
24 use Rapsys\AirBundle\Entity\Application
;
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 use Rapsys\AirBundle\Pdf\DisputePdf
;
30 use Rapsys\UserBundle\Utils\Slugger
;
33 class DefaultController
{
35 //Rename render as _render
36 render
as protected _render
;
48 ///Translator instance
49 protected $translator;
54 ///RequestStack instance
64 * @var ContainerInterface
68 ///Facebook image array
69 protected $facebookImage = [];
72 * Inject container and translator interface
74 * @param ContainerInterface $container The container instance
75 * @param RouterInterface $router The router instance
76 * @param RequestStack $stack The request stack
77 * @param TranslatorInterface $translator The translator instance
79 public function __construct(ContainerInterface
$container, RouterInterface
$router, RequestStack
$stack, TranslatorInterface
$translator, Packages
$asset) {
81 $this->config
= $container->getParameter($this->getAlias());
84 $this->container
= $container;
87 $this->router
= $router;
90 $this->translator
= $translator;
93 $this->asset
= $asset;
95 //Set the request stack
96 $this->stack
= $stack;
101 'title' => $translator->trans($this->config
['contact']['title']),
102 'mail' => $this->config
['contact']['mail']
105 'by' => $translator->trans($this->config
['copy']['by']),
106 'link' => $this->config
['copy']['link'],
107 'long' => $translator->trans($this->config
['copy']['long']),
108 'short' => $translator->trans($this->config
['copy']['short']),
109 'title' => $this->config
['copy']['title']
112 'description' => null,
117 'donate' => $this->config
['site']['donate'],
118 'ico' => $this->config
['site']['ico'],
119 'logo' => $this->config
['site']['logo'],
120 'png' => $this->config
['site']['png'],
121 'svg' => $this->config
['site']['svg'],
122 'title' => $translator->trans($this->config
['site']['title']),
123 'url' => $router->generate($this->config
['site']['url'])
129 'site_name' => $this->translator
->trans($this->config
['site']['title'])
132 #'admins' => $this->config['facebook']['admins'],
133 'app_id' => $this->config
['facebook']['apps']
138 //Get current request
139 $this->request
= $stack->getCurrentRequest();
142 #$this->locale = $router->getContext()->getParameters()['_locale'];
143 $this->locale
= $this->request
->getLocale();
145 //Set translator locale
146 //XXX: allow LocaleSubscriber on the fly locale change for first page
147 $this->translator
->setLocale($this->locale
);
149 //Iterate on locales excluding current one
150 foreach($this->config
['locales'] as $locale) {
154 //Iterate on other locales
155 foreach(array_diff($this->config
['locales'], [$locale]) as $other) {
156 $titles[$other] = $translator->trans($this->config
['languages'][$locale], [], null, $other);
160 $path = $router->getContext()->getPathInfo();
162 //Retrieve route matching path
163 $route = $router->match($path);
166 $name = $route['_route'];
169 unset($route['_route']);
171 //With current locale
172 if ($locale == $this->locale
) {
173 //Set locale locales context
174 $this->context
['canonical'] = $router->generate($name, ['_locale' => $locale]+
$route, UrlGeneratorInterface
::ABSOLUTE_URL
);
176 //Set locale locales context
177 $this->context
['alternates'][$locale] = [
178 'absolute' => $router->generate($name, ['_locale' => $locale]+
$route, UrlGeneratorInterface
::ABSOLUTE_URL
),
179 'relative' => $router->generate($name, ['_locale' => $locale]+
$route),
180 'title' => implode('/', $titles),
181 'translated' => $translator->trans($this->config
['languages'][$locale], [], null, $locale)
186 if (empty($this->context
['alternates'][$shortLocale = substr($locale, 0, 2)])) {
187 //Set locale locales context
188 $this->context
['alternates'][$shortLocale] = [
189 'absolute' => $router->generate($name, ['_locale' => $locale]+
$route, UrlGeneratorInterface
::ABSOLUTE_URL
),
190 'relative' => $router->generate($name, ['_locale' => $locale]+
$route),
191 'title' => implode('/', $titles),
192 'translated' => $translator->trans($this->config
['languages'][$locale], [], null, $locale)
201 * @desc Display the about informations
203 * @return Response The rendered view
205 public function about(): Response
{
207 $this->context
['page']['title'] = $this->translator
->trans('About');
210 $this->context
['page']['description'] = $this->translator
->trans('Libre Air about');
213 $this->context
['keywords'] = [
214 $this->translator
->trans('about'),
215 $this->translator
->trans('Libre Air')
219 $response = $this->render('@RapsysAir/default/about.html.twig', $this->context
);
220 $response->setEtag(md5($response->getContent()));
221 $response->setPublic();
222 $response->isNotModified($this->request
);
231 * @desc Send a contact mail to configured contact
233 * @param Request $request The request instance
234 * @param MailerInterface $mailer The mailer instance
236 * @return Response The rendered view or redirection
238 public function contact(Request
$request, MailerInterface
$mailer): Response
{
240 $this->context
['page']['title'] = $this->translator
->trans('Contact');
243 $this->context
['page']['description'] = $this->translator
->trans('Contact Libre Air');
246 $this->context
['keywords'] = [
247 $this->translator
->trans('contact'),
248 $this->translator
->trans('Libre Air'),
249 $this->translator
->trans('outdoor'),
250 $this->translator
->trans('Argentine Tango'),
251 $this->translator
->trans('calendar')
254 //Create the form according to the FormType created previously.
255 //And give the proper parameters
256 $form = $this->createForm('Rapsys\AirBundle\Form\ContactType', null, [
257 'action' => $this->generateUrl('rapsys_air_contact'),
261 if ($request->isMethod('POST')) {
262 // Refill the fields in case the form is not valid.
263 $form->handleRequest($request);
265 if ($form->isValid()) {
267 $data = $form->getData();
270 $message = (new TemplatedEmail())
272 ->from(new Address($data['mail'], $data['name']))
274 ->to(new Address($this->context
['contact']['mail'], $this->context
['contact']['title']))
276 ->subject($data['subject'])
278 //Set path to twig templates
279 ->htmlTemplate('@RapsysAir/mail/contact.html.twig')
280 ->textTemplate('@RapsysAir/mail/contact.text.twig')
285 'subject' => $data['subject'],
286 'message' => strip_tags($data['message']),
290 //Try sending message
291 //XXX: mail delivery may silently fail
294 $mailer->send($message);
296 //Redirect on the same route with sent=1 to cleanup form
297 return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+
$request->get('_route_params'));
298 //Catch obvious transport exception
299 } catch(TransportExceptionInterface
$e) {
300 if ($message = $e->getMessage()) {
301 //Add error message mail unreachable
302 $form->get('mail')->addError(new FormError($this->translator
->trans('Unable to contact: %mail%: %message%', ['%mail%' => $this->context
['contact']['mail'], '%message%' => $this->translator
->trans($message)])));
304 //Add error message mail unreachable
305 $form->get('mail')->addError(new FormError($this->translator
->trans('Unable to contact: %mail%', ['%mail%' => $this->context
['contact']['mail']])));
312 return $this->render('@RapsysAir/form/contact.html.twig', ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->context
);
318 * @desc Generate a dispute document
320 * @param Request $request The request instance
321 * @param MailerInterface $mailer The mailer instance
323 * @return Response The rendered view or redirection
325 public function dispute(Request
$request, MailerInterface
$mailer): Response
{
326 //Prevent non-guest to access here
327 $this->denyAccessUnlessGranted('ROLE_USER', null, $this->translator
->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator
->trans('User')]));
330 $this->context
['page']['title'] = $this->translator
->trans('Dispute');
333 $this->context
['page']['description'] = $this->translator
->trans('Libre Air dispute');
336 $this->context
['keywords'] = [
337 $this->translator
->trans('dispute'),
338 $this->translator
->trans('Libre Air'),
339 $this->translator
->trans('outdoor'),
340 $this->translator
->trans('Argentine Tango'),
341 $this->translator
->trans('calendar')
344 //Create the form according to the FormType created previously.
345 //And give the proper parameters
346 $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.'], [
347 'action' => $this->generateUrl('rapsys_air_dispute'),
351 if ($request->isMethod('POST')) {
352 // Refill the fields in case the form is not valid.
353 $form->handleRequest($request);
355 if ($form->isValid()) {
357 $data = $form->getData();
360 if (!empty($data['offense']) && $data['offense'] == 'gathering') {
362 $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());
364 } elseif (!empty($data['offense'] && $data['offense'] == 'traffic')) {
366 $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());
367 //Unsupported offense
369 header('Content-Type: text/plain');
374 //Send common headers
375 header('Content-Type: application/pdf');
377 //Send remaining headers
378 header('Cache-Control: private, max-age=0, must-revalidate');
379 header('Pragma: public');
381 //Send content-length
382 header('Content-Length: '.strlen($output));
391 # $message = (new TemplatedEmail())
393 # ->from(new Address($data['mail'], $data['name']))
395 # //XXX: remove the debug set in vendor/symfony/mime/Address.php +46
396 # ->to(new Address($this->config['contact']['mail'], $this->config['contact']['title']))
398 # ->subject($data['subject'])
400 # //Set path to twig templates
401 # ->htmlTemplate('@RapsysAir/mail/contact.html.twig')
402 # ->textTemplate('@RapsysAir/mail/contact.text.twig')
407 # 'subject' => $data['subject'],
408 # 'message' => strip_tags($data['message']),
412 # //Try sending message
413 # //XXX: mail delivery may silently fail
416 # $mailer->send($message);
418 # //Redirect on the same route with sent=1 to cleanup form
419 # return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+$request->get('_route_params'));
420 # //Catch obvious transport exception
421 # } catch(TransportExceptionInterface $e) {
422 # if ($message = $e->getMessage()) {
423 # //Add error message mail unreachable
424 # $form->get('mail')->addError(new FormError($this->translator->trans('Unable to contact: %mail%: %message%', ['%mail%' => $this->config['contact']['mail'], '%message%' => $this->translator->trans($message)])));
426 # //Add error message mail unreachable
427 # $form->get('mail')->addError(new FormError($this->translator->trans('Unable to contact: %mail%', ['%mail%' => $this->config['contact']['mail']])));
434 return $this->render('@RapsysAir/default/dispute.html.twig', ['form' => $form->createView(), 'sent' => $request->query
->get('sent', 0)]+
$this->context
);
440 * @desc Display all granted sessions with an application or login form
442 * @param Request $request The request instance
444 * @return Response The rendered view
446 public function index(Request
$request): Response
{
448 $doctrine = $this->getDoctrine();
451 $this->context
['page']['title'] = $this->translator
->trans('Argentine Tango in Paris');
454 $this->context
['page']['description'] = $this->translator
->trans('Outdoor Argentine Tango session calendar in Paris');
457 $this->context
['keywords'] = [
458 $this->translator
->trans('Argentine Tango'),
459 $this->translator
->trans('Paris'),
460 $this->translator
->trans('outdoor'),
461 $this->translator
->trans('calendar'),
462 $this->translator
->trans('Libre Air')
466 //XXX: only valid for home page
467 $this->context
['ogps']['type'] = 'website';
470 $period = new \
DatePeriod(
471 //Start from first monday of week
472 new \
DateTime('Monday this week'),
473 //Iterate on each day
474 new \
DateInterval('P1D'),
475 //End with next sunday and 4 weeks
477 $this->isGranted('IS_AUTHENTICATED_REMEMBERED')?'Monday this week + 3 week':'Monday this week + 2 week'
482 $calendar = $doctrine->getRepository(Session
::class)->fetchCalendarByDatePeriod($this->translator
, $period, null, $request->get('session'), !$this->isGranted('IS_AUTHENTICATED_REMEMBERED'));
485 //XXX: we want to display all active locations anyway
486 $locations = $doctrine->getRepository(Location
::class)->findTranslatedSortedByPeriod($this->translator
, $period);
489 return $this->render('@RapsysAir/default/index.html.twig', ['calendar' => $calendar, 'locations' => $locations]+
$this->context
);
491 //Set Cache-Control must-revalidate directive
492 //TODO: add a javascript forced refresh after 1h ? or header refresh ?
493 #$response->setPublic(true);
494 #$response->setMaxAge(300);
495 #$response->mustRevalidate();
496 ##$response->setCache(['public' => true, 'max_age' => 300]);
498 //Return the response
503 * The organizer regulation page
505 * @desc Display the organizer regulation policy
507 * @return Response The rendered view
509 public function organizerRegulation(): Response
{
511 $this->context
['page']['title'] = $this->translator
->trans('Organizer regulation');
514 $this->context
['page']['description'] = $this->translator
->trans('Libre Air organizer regulation');
517 $this->context
['keywords'] = [
518 $this->translator
->trans('organizer regulation'),
519 $this->translator
->trans('Libre Air')
523 $response = $this->render('@RapsysAir/default/organizer_regulation.html.twig', $this->context
);
526 $response->setEtag(md5($response->getContent()));
527 $response->setPublic();
528 $response->isNotModified($this->request
);
535 * The terms of service page
537 * @desc Display the terms of service policy
539 * @return Response The rendered view
541 public function termsOfService(): Response
{
543 $this->context
['page']['title'] = $this->translator
->trans('Terms of service');
546 $this->context
['page']['description'] = $this->translator
->trans('Libre Air terms of service');
549 $this->context
['keywords'] = [
550 $this->translator
->trans('terms of service'),
551 $this->translator
->trans('Libre Air')
555 $response = $this->render('@RapsysAir/default/terms_of_service.html.twig', $this->context
);
558 $response->setEtag(md5($response->getContent()));
559 $response->setPublic();
560 $response->isNotModified($this->request
);
567 * The frequently asked questions page
569 * @desc Display the frequently asked questions
571 * @return Response The rendered view
573 public function frequentlyAskedQuestions(): Response
{
575 $this->context
['page']['title'] = $this->translator
->trans('Frequently asked questions');
578 $this->context
['page']['description'] = $this->translator
->trans('Libre Air frequently asked questions');
581 $this->context
['keywords'] = [
582 $this->translator
->trans('frequently asked questions'),
583 $this->translator
->trans('faq'),
584 $this->translator
->trans('Libre Air')
588 $response = $this->render('@RapsysAir/default/frequently_asked_questions.html.twig', $this->context
);
591 $response->setEtag(md5($response->getContent()));
592 $response->setPublic();
593 $response->isNotModified($this->request
);
600 * Return the bundle alias
604 public function getAlias(): string {
609 * Return the facebook image
611 * @desc Generate image in jpeg format or load it from cache
613 * @return array The image array
615 protected function getFacebookImage(): array {
617 $texts = $this->facebookImage
['texts'] ?? [];
620 $source = $this->facebookImage
['source'] ?? 'png/facebook.png';
623 $updated = $this->facebookImage
['updated'] ?? strtotime('last week');
625 //Set default destination
626 //XXX: format facebook<pathinfo>.jpeg
627 //XXX: was facebook/<controller>/<action>.<locale>.jpeg
628 $destination = $this->facebookImage
['destination'] ?? 'facebook'.$this->request
->getPathInfo().'.jpeg';
631 $src = $this->config
['path']['public'].'/'.$source;
634 //XXX: remove extension and store as png anyway
635 $cache = $this->config
['path']['cache'].'/facebook/'.substr($source, 0, strrpos($source, '.')).'.'.$this->config
['facebook']['width'].'x'.$this->config
['facebook']['height'].'.png';
637 //Set destination path
638 $dest = $this->config
['path']['public'].'/'.$destination;
641 $asset = '@RapsysAir/'.$destination;
643 //With up to date generated image
646 ($stat = stat($dest)) &&
647 $stat['mtime'] >= $updated
650 list ($width, $height) = getimagesize($dest);
652 //With canonical in texts
653 if (!empty($texts[$this->context
['canonical']])) {
654 //Prevent canonical to finish in alt
655 unset($texts[$this->context
['canonical']]);
660 #'image' => $this->stack->getCurrentRequest()->getUriForPath($this->asset->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
661 'image:url' => $this->stack
->getCurrentRequest()->getUriForPath($this->asset
->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
662 #'image:secure_url' => $this->stack->getCurrentRequest()->getUriForPath($this->asset->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
663 'image:alt' => str_replace("\n", ' ', implode(' - ', array_keys($texts))),
664 'image:height' => $height,
665 'image:width' => $width
667 //With image candidate
668 } elseif (is_file($src)) {
669 //Create image object
670 $image = new \
Imagick();
673 if (is_file($cache)) {
675 $image->readImage($cache);
676 //Without we generate it
678 //Check target directory
679 if (!is_dir($dir = dirname($cache))) {
680 //Create filesystem object
681 $filesystem = new Filesystem();
685 //XXX: set as 0775, symfony umask (0022) will reduce rights (0755)
686 $filesystem->mkdir($dir, 0775);
687 } catch (IOExceptionInterface
$e) {
689 throw new \
Exception(sprintf('Output directory "%s" do not exists and unable to create it', $dir), 0, $e);
694 $image->readImage($src);
696 //Crop using aspect ratio
697 //XXX: for better result upload image directly in aspect ratio :)
698 $image->cropThumbnailImage($this->config
['facebook']['width'], $this->config
['facebook']['height']);
700 //Strip image exif data and properties
701 $image->stripImage();
704 if (!$image->writeImage($cache)) {
706 throw new \
Exception(sprintf('Unable to write image "%s"', $cache));
709 //Check target directory
710 if (!is_dir($dir = dirname($dest))) {
711 //Create filesystem object
712 $filesystem = new Filesystem();
716 //XXX: set as 0775, symfony umask (0022) will reduce rights (0755)
717 $filesystem->mkdir($dir, 0775);
718 } catch (IOExceptionInterface
$e) {
720 throw new \
Exception(sprintf('Output directory "%s" do not exists and unable to create it', $dir), 0, $e);
725 $width = $image->getImageWidth();
728 $height = $image->getImageHeight();
731 $draw = new \
ImagickDraw();
733 //Set stroke antialias
734 $draw->setStrokeAntialias(true);
737 $draw->setTextAntialias(true);
740 $draw->setStrokeWidth($this->facebookImage
['stroke']??15);
744 'irishgrover' => $this->config
['path']['public'].'/ttf/irishgrover.v10.ttf',
745 'droidsans' => $this->config
['path']['public'].'/ttf/droidsans.regular.ttf',
746 'dejavusans' => $this->config
['path']['public'].'/ttf/dejavusans.2.37.ttf',
747 'labelleaurore' => $this->config
['path']['public'].'/ttf/labelleaurore.v10.ttf'
752 'left' => \Imagick
::ALIGN_LEFT
,
753 'center' => \Imagick
::ALIGN_CENTER
,
754 'right' => \Imagick
::ALIGN_RIGHT
758 $defaultFont = 'dejavusans';
761 $defaultAlign = 'center';
767 $defaultStroke = '#00c3f9';
770 $defaultFill = 'white';
776 $count = count($texts);
778 //Draw each text stroke
779 foreach($texts as $text => $data) {
781 $draw->setFont($fonts[$data['font']??$defaultFont]);
784 $draw->setFontSize($data['size']??$defaultSize);
787 $draw->setTextAlignment($align = ($aligns[$data['align']??$defaultAlign]));
790 $metrics = $image->queryFontMetrics($draw, $text);
793 if (empty($data['y'])) {
794 //Position verticaly each text evenly
795 $texts[$text]['y'] = $data['y'] = (($height +
100) / (count($texts) +
1) * $i) - 50;
799 if (empty($data['x'])) {
800 if ($align == \Imagick
::ALIGN_CENTER
) {
801 $texts[$text]['x'] = $data['x'] = $width/2;
802 } elseif ($align == \Imagick
::ALIGN_LEFT
) {
803 $texts[$text]['x'] = $data['x'] = 50;
804 } elseif ($align == \Imagick
::ALIGN_RIGHT
) {
805 $texts[$text]['x'] = $data['x'] = $width - 50;
810 //XXX: add ascender part then center it back by half of textHeight
811 //TODO: maybe add a boundingbox ???
812 $texts[$text]['y'] = $data['y'] +
= $metrics['ascender'] - $metrics['textHeight']/2;
815 $draw->setStrokeColor(new \
ImagickPixel($data['stroke']??$defaultStroke));
818 $draw->setFillColor(new \
ImagickPixel($data['stroke']??$defaultStroke));
821 $draw->annotation($data['x'], $data['y'], $text);
827 //Create stroke object
828 $stroke = new \
Imagick();
831 $stroke->newImage($width, $height, new \
ImagickPixel('transparent'));
834 $stroke->drawImage($draw);
837 //XXX: blur the stroke canvas only
838 $stroke->blurImage(5,3);
841 //XXX: see https://www.php.net/manual/en/image.evaluateimage.php
842 $stroke->evaluateImage(\Imagick
::EVALUATE_DIVIDE
, 1.5, \Imagick
::CHANNEL_ALPHA
);
845 $image->compositeImage($stroke, \Imagick
::COMPOSITE_OVER
, 0, 0);
857 $draw->setTextAntialias(true);
860 foreach($texts as $text => $data) {
862 $draw->setFont($fonts[$data['font']??$defaultFont]);
865 $draw->setFontSize($data['size']??$defaultSize);
868 $draw->setTextAlignment($aligns[$data['align']??$defaultAlign]);
871 $draw->setFillColor(new \
ImagickPixel($data['fill']??$defaultFill));
874 $draw->annotation($data['x'], $data['y'], $text);
878 $image->drawImage($draw);
880 //Strip image exif data and properties
881 $image->stripImage();
884 $image->setImageFormat('jpeg');
887 if (!$image->writeImage($dest)) {
889 throw new \
Exception(sprintf('Unable to write image "%s"', $dest));
893 //TODO: see if it works every time
896 //With canonical in texts
897 if (!empty($texts[$this->context
['canonical']])) {
898 //Prevent canonical to finish in alt
899 unset($texts[$this->context
['canonical']]);
904 //TODO: see if it works every time
905 #'image' => $this->stack->getCurrentRequest()->getUriForPath($this->asset->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
906 'image:url' => $this->stack
->getCurrentRequest()->getUriForPath($this->asset
->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
907 #'image:secure_url' => $this->stack->getCurrentRequest()->getUriForPath($this->asset->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
908 'image:alt' => str_replace("\n", ' ', implode(' - ', array_keys($texts))),
909 'image:height' => $height,
910 'image:width' => $width
914 //Return empty array without image
923 protected function render(string $view, array $parameters = [], Response
$response = null): Response
{
924 //Create application form for role_guest
925 if ($this->isGranted('ROLE_GUEST')) {
926 //Without application form
927 if (empty($parameters['forms']['application'])) {
929 $doctrine = $this->getDoctrine();
931 //Create ApplicationType form
932 $application = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [
934 'action' => $this->generateUrl('rapsys_air_application_add'),
935 //Set the form attribute
936 'attr' => [ 'class' => 'col' ],
938 'admin' => $this->isGranted('ROLE_ADMIN'),
939 //Set default user to current
940 'user' => $this->getUser()->getId(),
941 //Set default slot to evening
942 //XXX: default to Evening (3)
943 'slot' => $doctrine->getRepository(Slot
::class)->findOneById(3)
946 //Add form to context
947 $parameters['forms']['application'] = $application->createView();
949 //Create login form for anonymous
950 } elseif (!$this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
951 //Create ApplicationType form
952 $login = $this->createForm('Rapsys\UserBundle\Form\LoginType', null, [
954 'action' => $this->generateUrl('rapsys_user_login'),
955 //Set the form attribute
956 'attr' => [ 'class' => 'col' ]
959 //Add form to context
960 $parameters['forms']['login'] = $login->createView();
963 //With page infos and without facebook image
964 if (empty($this->facebookImage
) && !empty($parameters['site']['title']) && !empty($parameters['page']['title']) && !empty($parameters['canonical'])) {
966 $this->facebookImage
= [
968 $parameters['site']['title'] => [
969 'font' => 'irishgrover',
972 $parameters['page']['title'] => [
975 $parameters['canonical'] => [
977 'font' => 'labelleaurore',
985 if (!empty($parameters['canonical'])) {
987 $parameters['ogps']['url'] = $parameters['canonical'];
991 if (!empty($parameters['page']['title'])) {
993 $parameters['ogps']['title'] = $parameters['page']['title'];
996 //With page description
997 if (!empty($parameters['page']['description'])) {
998 //Set facebook description
999 $parameters['ogps']['description'] = $parameters['page']['description'];
1003 if (!empty($this->locale
)) {
1004 //Set facebook locale
1005 $parameters['ogps']['locale'] = str_replace('-', '_', $this->locale
);
1008 //XXX: disabled as we don't support fb_locale=xx_xx
1009 //XXX: see https://stackoverflow.com/questions/20827882/in-open-graph-markup-whats-the-use-of-oglocalealternate-without-the-locati
1010 #if (!empty($parameters['alternates'])) {
1011 # //Iterate on alternates
1012 # foreach($parameters['alternates'] as $lang => $alternate) {
1013 # if (strlen($lang) == 5) {
1014 # //Set facebook locale alternate
1015 # $parameters['ogps']['locale:alternate'] = str_replace('-', '_', $lang);
1021 //With facebook image defined
1022 if (!empty($this->facebookImage
)) {
1023 //Get facebook image
1024 $parameters['ogps'] +
= $this->getFacebookImage();
1027 //Call parent method
1028 return $this->_render($view, $parameters, $response);