<?php
namespace Rapsys\AirBundle\Controller;
use Rapsys\AirBundle\Entity\Application;
use Rapsys\AirBundle\Entity\Location;
use Rapsys\AirBundle\Entity\Session;
use Rapsys\AirBundle\Entity\Slot;
use Rapsys\AirBundle\Entity\User;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Rapsys\UserBundle\Utils\Slugger;
use Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
class DefaultController {
use ControllerTrait {
//Rename render as _render
render as protected _render;
}
///Config array
protected $config;
///Context array
protected $context;
///Router instance
protected $router;
///Translator instance
protected $translator;
/**
* @var ContainerInterface
*/
protected $container;
/**
* Inject container and translator interface
*
* @param ContainerInterface $container The container instance
* @param RouterInterface $router The router instance
* @param TranslatorInterface $translator The translator instance
*/
public function __construct(ContainerInterface $container, RouterInterface $router, RequestStack $requestStack, TranslatorInterface $translator) {
//Retrieve config
$this->config = $container->getParameter($this->getAlias());
//Set the container
$this->container = $container;
//Set the router
$this->router = $router;
//Set the translator
$this->translator = $translator;
//Set the context
$this->context = [
'copy' => [
'by' => $translator->trans($this->config['copy']['by']),
'link' => $this->config['copy']['link'],
'long' => $translator->trans($this->config['copy']['long']),
'short' => $translator->trans($this->config['copy']['short']),
'title' => $this->config['copy']['title']
],
'site' => [
'ico' => $this->config['site']['ico'],
'logo' => $this->config['site']['logo'],
'png' => $this->config['site']['png'],
'svg' => $this->config['site']['svg'],
'title' => $translator->trans($this->config['site']['title']),
'url' => $router->generate($this->config['site']['url']),
],
'canonical' => null,
'alternates' => [],
'forms' => []
];
//Get current locale
#$currentLocale = $router->getContext()->getParameters()['_locale'];
$currentLocale = $requestStack->getCurrentRequest()->getLocale();
//Set translator locale
//XXX: allow LocaleSubscriber on the fly locale change for first page
$this->translator->setLocale($currentLocale);
//Iterate on locales excluding current one
foreach($this->config['locales'] as $locale) {
//Set titles
$titles = [];
//Iterate on other locales
foreach(array_diff($this->config['locales'], [$locale]) as $other) {
$titles[$other] = $translator->trans($this->config['languages'][$locale], [], null, $other);
}
//Get context path
$path = $router->getContext()->getPathInfo();
//Retrieve route matching path
$route = $router->match($path);
//Get route name
$name = $route['_route'];
//Unset route name
unset($route['_route']);
//With current locale
if ($locale == $currentLocale) {
//Set locale locales context
$this->context['canonical'] = $router->generate($name, ['_locale' => $locale]+$route, UrlGeneratorInterface::ABSOLUTE_URL);
} else {
//Set locale locales context
$this->context['alternates'][] = [
'lang' => $locale,
'absolute' => $router->generate($name, ['_locale' => $locale]+$route, UrlGeneratorInterface::ABSOLUTE_URL),
'relative' => $router->generate($name, ['_locale' => $locale]+$route),
'title' => implode('/', $titles),
'translated' => $translator->trans($this->config['languages'][$locale], [], null, $locale)
];
}
}
}
/**
* The contact page
*
* @desc Send a contact mail to configured contact
*
* @param Request $request The request instance
* @param MailerInterface $mailer The mailer instance
*
* @return Response The rendered view or redirection
*/
public function contact(Request $request, MailerInterface $mailer): Response {
//Set section
$section = $this->translator->trans('Contact');
//Set description
$this->context['description'] = $this->translator->trans('Contact Libre Air');
//Set keywords
$this->context['keywords'] = [
$this->translator->trans('contact'),
$this->translator->trans('Libre Air'),
$this->translator->trans('outdoor'),
$this->translator->trans('Argentine Tango'),
$this->translator->trans('calendar')
];
//Set title
$title = $this->translator->trans($this->config['site']['title']).' - '.$section;
//Create the form according to the FormType created previously.
//And give the proper parameters
$form = $this->createForm('Rapsys\AirBundle\Form\ContactType', null, [
'action' => $this->generateUrl('rapsys_air_contact'),
'method' => 'POST'
]);
if ($request->isMethod('POST')) {
// Refill the fields in case the form is not valid.
$form->handleRequest($request);
if ($form->isValid()) {
//Get data
$data = $form->getData();
//Create message
$message = (new TemplatedEmail())
//Set sender
->from(new Address($data['mail'], $data['name']))
//Set recipient
//XXX: remove the debug set in vendor/symfony/mime/Address.php +46
->to(new Address($this->config['contact']['mail'], $this->config['contact']['name']))
//Set subject
->subject($data['subject'])
//Set path to twig templates
->htmlTemplate('@RapsysAir/mail/contact.html.twig')
->textTemplate('@RapsysAir/mail/contact.text.twig')
//Set context
->context(
[
'subject' => $data['subject'],
'message' => strip_tags($data['message']),
]+$this->context
);
//Try sending message
//XXX: mail delivery may silently fail
try {
//Send message
$mailer->send($message);
//Redirect on the same route with sent=1 to cleanup form
return $this->redirectToRoute($request->get('_route'), ['sent' => 1]+$request->get('_route_params'));
//Catch obvious transport exception
} catch(TransportExceptionInterface $e) {
if ($message = $e->getMessage()) {
//Add error message mail unreachable
$form->get('mail')->addError(new FormError($this->translator->trans('Unable to contact: %mail%: %message%', ['%mail%' => $this->config['contact']['mail'], '%message%' => $this->translator->trans($message)])));
} else {
//Add error message mail unreachable
$form->get('mail')->addError(new FormError($this->translator->trans('Unable to contact: %mail%', ['%mail%' => $this->config['contact']['mail']])));
}
}
}
}
//Render template
return $this->render('@RapsysAir/form/contact.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]+$this->context);
}
/**
* The index page
*
* @desc Display all granted sessions with an application or login form
*
* @param Request $request The request instance
*
* @return Response The rendered view
*/
public function index(Request $request): Response {
//Fetch doctrine
$doctrine = $this->getDoctrine();
//Set section
$section = $this->translator->trans('Argentine Tango in Paris');
//Set description
$this->context['description'] = $this->translator->trans('Outdoor Argentine Tango session calendar in Paris');
//Set keywords
$this->context['keywords'] = [
$this->translator->trans('Argentine Tango'),
$this->translator->trans('Paris'),
$this->translator->trans('outdoor'),
$this->translator->trans('calendar'),
$this->translator->trans('Libre Air')
];
//Set title
$title = $this->translator->trans($this->config['site']['title']).' - '.$section;
//Compute period
$period = new \DatePeriod(
//Start from first monday of week
new \DateTime('Monday this week'),
//Iterate on each day
new \DateInterval('P1D'),
//End with next sunday and 4 weeks
new \DateTime(
$this->isGranted('IS_AUTHENTICATED_REMEMBERED')?'Monday this week + 4 week':'Monday this week + 2 week'
)
);
//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', ['title' => $title, 'section' => $section, 'calendar' => $calendar, 'locations' => $locations]+$this->context);
//Set Cache-Control must-revalidate directive
#$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 section
$section = $this->translator->trans('Organizer regulation');
//Set description
$this->context['description'] = $this->translator->trans('Libre Air organizer regulation');
//Set keywords
$this->context['keywords'] = [
$this->translator->trans('organizer regulation'),
$this->translator->trans('Libre Air')
];
//Set title
$title = $this->translator->trans($this->config['site']['title']).' - '.$section;
//Render template
return $this->render('@RapsysAir/default/organizer_regulation.html.twig', ['title' => $title, 'section' => $section]+$this->context);
}
/**
* The terms of service page
*
* @desc Display the terms of service policy
*
* @return Response The rendered view
*/
public function termsOfService(): Response {
//Set section
$section = $this->translator->trans('Terms of service');
//Set description
$this->context['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')
];
//Set title
$title = $this->translator->trans($this->config['site']['title']).' - '.$section;
//Render template
return $this->render('@RapsysAir/default/terms_of_service.html.twig', ['title' => $title, 'section' => $section]+$this->context);
}
/**
* The frequently asked questions page
*
* @desc Display the frequently asked questions
*
* @return Response The rendered view
*/
public function frequentlyAskedQuestions(): Response {
//Set section
$section = $this->translator->trans('Frequently asked questions');
//Set description
$this->context['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')
];
//Set title
$title = $this->translator->trans($this->config['site']['title']).' - '.$section;
//Render template
return $this->render('@RapsysAir/default/frequently_asked_questions.html.twig', ['title' => $title, 'section' => $section]+$this->context);
}
/**
* Return the bundle alias
*
* {@inheritdoc}
*/
public function getAlias(): string {
return 'rapsys_air';
}
/**
* Renders a view
*
* {@inheritdoc}
*/
protected function render(string $view, array $parameters = [], Response $response = null): Response {
//Create application form for role_guest
if ($this->isGranted('ROLE_GUEST')) {
//Without application form
if (empty($parameters['forms']['application'])) {
//Fetch doctrine
$doctrine = $this->getDoctrine();
//Create ApplicationType form
$application = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [
//Set the action
'action' => $this->generateUrl('rapsys_air_application_add'),
//Set the form attribute
'attr' => [ 'class' => 'col' ],
//Set admin
'admin' => $this->isGranted('ROLE_ADMIN'),
//Set default user to current
'user' => $this->getUser()->getId(),
//Set default slot to evening
//XXX: default to Evening (3)
'slot' => $doctrine->getRepository(Slot::class)->findOneById(3)
]);
//Add form to context
$parameters['forms']['application'] = $application->createView();
}
//Create login form for anonymous
} elseif (!$this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
//Create ApplicationType form
$login = $this->createForm('Rapsys\UserBundle\Form\LoginType', null, [
//Set the action
'action' => $this->generateUrl('rapsys_user_login'),
//Set the form attribute
'attr' => [ 'class' => 'col' ]
]);
//Add form to context
$parameters['forms']['login'] = $login->createView();
}
//Call parent method
return $this->_render($view, $parameters, $response);
}
}