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);