+ //Fetch calendar
+ $calendar = $doctrine->getRepository(Session::class)->fetchCalendarByDatePeriod($this->translator, $period, null, $request->get('session'), !$this->isGranted('IS_AUTHENTICATED_REMEMBERED'));
+
+ //Fetch locations
+ //XXX: we want to display all active locations anyway
+ $locations = $doctrine->getRepository(Location::class)->findTranslatedSortedByPeriod($this->translator, $period);
+
+ //Render the view
+ return $this->render('@RapsysAir/default/index.html.twig', ['calendar' => $calendar, 'locations' => $locations]+$this->context);
+
+ //Set Cache-Control must-revalidate directive
+ //TODO: add a javascript forced refresh after 1h ? or header refresh ?
+ #$response->setPublic(true);
+ #$response->setMaxAge(300);
+ #$response->mustRevalidate();
+ ##$response->setCache(['public' => true, 'max_age' => 300]);
+
+ //Return the response
+ #return $response;
+ }
+
+ /**
+ * The organizer regulation page
+ *
+ * @desc Display the organizer regulation policy
+ *
+ * @return Response The rendered view
+ */
+ public function organizerRegulation(): Response {
+ //Set page
+ $this->context['page']['title'] = $this->translator->trans('Organizer regulation');
+
+ //Set description
+ $this->context['page']['description'] = $this->translator->trans('Libre Air organizer regulation');
+
+ //Set keywords
+ $this->context['keywords'] = [
+ $this->translator->trans('organizer regulation'),
+ $this->translator->trans('Libre Air')
+ ];
+
+ //Render template
+ $response = $this->render('@RapsysAir/default/organizer_regulation.html.twig', $this->context);
+
+ //Set as cachable
+ $response->setEtag(md5($response->getContent()));
+ $response->setPublic();
+ $response->isNotModified($this->request);
+
+ //Return response
+ return $response;
+ }
+
+ /**
+ * The terms of service page
+ *
+ * @desc Display the terms of service policy
+ *
+ * @return Response The rendered view
+ */
+ public function termsOfService(): Response {
+ //Set page
+ $this->context['page']['title'] = $this->translator->trans('Terms of service');
+
+ //Set description
+ $this->context['page']['description'] = $this->translator->trans('Libre Air terms of service');
+
+ //Set keywords
+ $this->context['keywords'] = [
+ $this->translator->trans('terms of service'),
+ $this->translator->trans('Libre Air')
+ ];
+
+ //Render template
+ $response = $this->render('@RapsysAir/default/terms_of_service.html.twig', $this->context);
+
+ //Set as cachable
+ $response->setEtag(md5($response->getContent()));
+ $response->setPublic();
+ $response->isNotModified($this->request);
+
+ //Return response
+ return $response;
+ }
+
+ /**
+ * The frequently asked questions page
+ *
+ * @desc Display the frequently asked questions
+ *
+ * @return Response The rendered view
+ */
+ public function frequentlyAskedQuestions(): Response {
+ //Set page
+ $this->context['page']['title'] = $this->translator->trans('Frequently asked questions');
+
+ //Set description
+ $this->context['page']['description'] = $this->translator->trans('Libre Air frequently asked questions');
+
+ //Set keywords
+ $this->context['keywords'] = [
+ $this->translator->trans('frequently asked questions'),
+ $this->translator->trans('faq'),
+ $this->translator->trans('Libre Air')
+ ];
+
+ //Render template
+ $response = $this->render('@RapsysAir/default/frequently_asked_questions.html.twig', $this->context);
+
+ //Set as cachable
+ $response->setEtag(md5($response->getContent()));
+ $response->setPublic();
+ $response->isNotModified($this->request);
+
+ //Return response
+ return $response;
+ }
+
+ /**
+ * Return the bundle alias
+ *
+ * {@inheritdoc}
+ */
+ public function getAlias(): string {
+ return 'rapsys_air';
+ }
+
+ /**
+ * Return the facebook image
+ *
+ * @desc Generate image in jpeg format or load it from cache
+ *
+ * @return array The image array
+ */
+ protected function getFacebookImage(): array {
+ //Set texts
+ $texts = $this->facebookImage['texts'] ?? [];
+
+ //Set default source
+ $source = $this->facebookImage['source'] ?? 'png/facebook.png';
+
+ //Set default source
+ $updated = $this->facebookImage['updated'] ?? strtotime('last week');
+
+ //Set default destination
+ //XXX: format facebook<pathinfo>.jpeg
+ //XXX: was facebook/<controller>/<action>.<locale>.jpeg
+ $destination = $this->facebookImage['destination'] ?? 'facebook'.$this->request->getPathInfo().'.jpeg';
+
+ //Set source path
+ $src = $this->config['path']['public'].'/'.$source;
+
+ //Set cache path
+ //XXX: remove extension and store as png anyway
+ $cache = $this->config['path']['cache'].'/facebook/'.substr($source, 0, strrpos($source, '.')).'.'.$this->config['facebook']['width'].'x'.$this->config['facebook']['height'].'.png';
+
+ //Set destination path
+ $dest = $this->config['path']['public'].'/'.$destination;
+
+ //Set asset
+ $asset = '@RapsysAir/'.$destination;
+
+ //With up to date generated image
+ if (
+ is_file($dest) &&
+ ($stat = stat($dest)) &&
+ $stat['mtime'] >= $updated
+ ) {
+ //Get image size
+ list ($width, $height) = getimagesize($dest);
+
+ //With canonical in texts
+ if (!empty($texts[$this->context['canonical']])) {
+ //Prevent canonical to finish in alt
+ unset($texts[$this->context['canonical']]);
+ }
+
+ //Return image data
+ return [
+ #'image' => $this->stack->getCurrentRequest()->getUriForPath($this->asset->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
+ 'image:url' => $this->stack->getCurrentRequest()->getUriForPath($this->asset->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
+ #'image:secure_url' => $this->stack->getCurrentRequest()->getUriForPath($this->asset->getUrl($asset), true),#.'?fbrefresh='.$stat['mtime'],
+ 'image:alt' => str_replace("\n", ' ', implode(' - ', array_keys($texts))),
+ 'image:height' => $height,
+ 'image:width' => $width