--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Controller\Controller;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Rapsys\AirBundle\Entity\Session;
+use Rapsys\AirBundle\Entity\Application;
+use Symfony\Component\Form\FormError;
+
+class DefaultController extends Controller {
+ public function contactAction(Request $request) {
+ //Get translator
+ $trans = $this->get('translator');
+
+ //Set section
+ $section = $trans->trans('Contact');
+
+ //Set title
+ $title = $section.' - '.$trans->trans($this->getParameter('rapsys_air.title'));
+
+ //Create the form according to the FormType created previously.
+ //And give the proper parameters
+ $form = $this->createForm('Rapsys\AirBundle\Form\ContactType', null, [
+ // To set the action use $this->generateUrl('route_identifier')
+ '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();
+
+ //Get contact name
+ $contactName = $this->getParameter('rapsys_air.contact_name');
+
+ //Get contact mail
+ $contactMail = $this->getParameter('rapsys_air.contact_mail');
+
+ //Get logo
+ $logo = $this->getParameter('rapsys_air.logo');
+
+ //Get title
+ $title = $trans->trans($this->getParameter('rapsys_air.title'));
+
+ //Get subtitle
+ $subtitle = $trans->trans('Hi,').' '.$contactName;
+
+ $message = \Swift_Message::newInstance()
+ ->setSubject($data['subject'])
+ ->setFrom([$data['mail'] => $data['name']])
+ ->setTo([$contactMail => $contactName])
+ ->setBody($data['message'])
+ ->addPart(
+ $this->renderView(
+ '@RapsysAir/mail/generic.html.twig',
+ [
+ 'logo' => $logo,
+ 'title' => $title,
+ 'subtitle' => $subtitle,
+ 'home' => $this->get('router')->generate('rapsys_air_homepage', [], UrlGeneratorInterface::ABSOLUTE_URL),
+ 'subject' => $data['subject'],
+ 'contact_name' => $contactName,
+ 'message' => strip_tags($data['message'])
+ ]
+ ),
+ 'text/html'
+ );
+ //Send message
+ if ($this->get('mailer')->send($message)) {
+ //Redirect to cleanup the form
+ return $this->redirectToRoute('rapsys_air_contact', ['sent' => 1]);
+ }
+ }
+ }
+
+ //Render template
+ return $this->render('@RapsysAir/form/contact.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView(), 'sent' => $request->query->get('sent', 0)]);
+ }
+
+ public function indexAction() {
+ //Get translator
+ $trans = $this->get('translator');
+
+ //Set section
+ $section = $trans->trans('Index');
+
+ //Set title
+ $title = $section.' - '.$trans->trans($this->getParameter('rapsys_air.title'));
+
+ return $this->render('@RapsysAir/page/index.html.twig', ['title' => $title, 'section' => $section]);
+ }
+
+ public function adminAction(Request $request) {
+ $this->denyAccessUnlessGranted('ROLE_ADMIN', null, 'Unable to access this page!');
+
+ //Get translator
+ $trans = $this->get('translator');
+
+ //Set section
+ $section = $trans->trans('Admin');
+
+ //Set title
+ $title = $section.' - '.$trans->trans($this->getParameter('rapsys_air.title'));
+
+ //Create the form according to the FormType created previously.
+ //And give the proper parameters
+ $form = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [
+ // To set the action use $this->generateUrl('route_identifier')
+ 'action' => $this->generateUrl('rapsys_air_admin'),
+ 'method' => 'POST',
+ 'attr' => [ 'class' => 'form_col' ]
+ ]);
+
+ //Get doctrine
+ $doctrine = $this->getDoctrine();
+
+ //Handle request
+ 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();
+
+ //Get manager
+ $manager = $doctrine->getManager();
+
+ //Protect session fetching
+ try {
+ $session = $doctrine->getRepository(Session::class)->findOneByLocationSlotDate($data['location'], $data['slot'], $data['date']);
+ //Catch no session case
+ } catch (\Doctrine\ORM\NoResultException $e) {
+ //Create the session
+ $session = new Session();
+ $session->setLocation($data['location']);
+ $session->setSlot($data['slot']);
+ $session->setDate($data['date']);
+ $session->setCreated(new \DateTime('now'));
+ $session->setUpdated(new \DateTime('now'));
+ $manager->persist($session);
+ //Flush to get the ids
+ #$manager->flush();
+ }
+
+ //Init application
+ $application = false;
+
+ //Protect application fetching
+ try {
+ //TODO: handle admin case where we provide a user in extra
+ $application = $doctrine->getRepository(Application::class)->findOneBySessionUser($session, $this->getUser());
+
+ //Add error message to mail field
+ $form->get('slot')->addError(new FormError($trans->trans('Application already exists')));
+ //Catch no application cases
+ //XXX: combine these catch when php 7.1 is available
+ } catch (\Doctrine\ORM\NoResultException $e) {
+ //Catch invalid argument because session is not already persisted
+ } catch(\Doctrine\ORM\ORMInvalidArgumentException $e) {
+ }
+
+ //Create new application if none found
+ if (!$application) {
+ //Create the application
+ $application = new Application();
+ $application->setSession($session);
+ //TODO: handle admin case where we provide a user in extra
+ $application->setUser($this->getUser());
+ $application->setCreated(new \DateTime('now'));
+ $application->setUpdated(new \DateTime('now'));
+ $manager->persist($application);
+
+ //Flush to get the ids
+ $manager->flush();
+
+ //Add notice in flash message
+ $this->addFlash('notice', $trans->trans('Application request the %date% for %location% on the slot %slot% saved', ['%location%' => $data['location']->getTitle(), '%slot%' => $data['slot']->getTitle(), '%date%' => $data['date']->format('Y-m-d')]));
+
+ //Redirect to cleanup the form
+ return $this->redirectToRoute('rapsys_air_admin');
+ }
+ }
+ }
+
+ //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('Monday this week + 5 week')
+ );
+
+ //Fetch sessions
+ $sessions = $doctrine->getRepository(Session::class)->findByDatePeriod($period);
+
+ //Init calendar
+ $calendar = [];
+
+ //Init month
+ $month = null;
+
+ //Iterate on each day
+ foreach($period as $date) {
+ //Init day in calendar
+ $calendar[$Ymd = $date->format('Ymd')] = [
+ 'title' => $date->format('d'),
+ 'class' => [],
+ 'sessions' => []
+ ];
+ //Append month for first day of month
+ if ($month != $date->format('m')) {
+ $month = $date->format('m');
+ $calendar[$Ymd]['title'] .= '/'.$month;
+ }
+ //Deal with today
+ if ($date->format('U') == ($today = strtotime('today'))) {
+ $calendar[$Ymd]['title'] .= '/'.$month;
+ $calendar[$Ymd]['current'] = true;
+ $calendar[$Ymd]['class'][] = 'current';
+ }
+ //Disable passed days
+ if ($date->format('U') < $today) {
+ $calendar[$Ymd]['disabled'] = true;
+ $calendar[$Ymd]['class'][] = 'disabled';
+ }
+ //Set next month days
+ if ($date->format('m') > date('m')) {
+ $calendar[$Ymd]['next'] = true;
+ $calendar[$Ymd]['class'][] = 'next';
+ }
+ //Iterate on each session to find the one of the day
+ foreach($sessions as $session) {
+ if (($sessionYmd = $session->getDate()->format('Ymd')) == $Ymd) {
+ //Count number of application
+ $count = count($session->getApplications());
+
+ //Compute classes
+ $class = [];
+ if ($session->getApplication()) {
+ $class[] = 'granted';
+ } elseif ($count == 0) {
+ $class[] = 'orphaned';
+ } elseif ($count > 1) {
+ $class[] = 'disputed';
+ } else {
+ $class[] = 'pending';
+ }
+
+ //Add the session
+ $calendar[$Ymd]['sessions'][$session->getSlot()->getId().$session->getLocation()->getId()] = [
+ 'id' => $session->getId(),
+ 'title' => ($count > 1?'['.$count.'] ':'').$session->getSlot()->getTitle().' '.$session->getLocation()->getTitle(),
+ 'class' => $class
+ ];
+ }
+ }
+
+ //Sort sessions
+ ksort($calendar[$Ymd]['sessions']);
+ }
+
+ return $this->render('@RapsysAir/admin/index.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView(), 'calendar' => $calendar]);
+ }
+
+ public function sessionAction(Request $request, $id) {
+ /*header('Content-Type: text/plain');
+ var_dump($calendar);
+ exit;*/
+
+ //Get translator
+ $trans = $this->get('translator');
+
+ //Set section
+ $section = $trans->trans('Session %id%', ['%id%' => $id]);
+
+ //Set title
+ $title = $section.' - '.$trans->trans($this->getParameter('rapsys_air.title'));
+
+ //Create the form according to the FormType created previously.
+ //And give the proper parameters
+ /*$form = $this->createForm('Rapsys\AirBundle\Form\ApplicationType', null, [
+ // To set the action use $this->generateUrl('route_identifier')
+ 'action' => $this->generateUrl('rapsys_air_admin'),
+ 'method' => 'POST',
+ 'attr' => [ 'class' => 'form_col' ]
+ ]);*/
+
+ //Get doctrine
+ $doctrine = $this->getDoctrine();
+
+ //Fetch session
+ $session = $doctrine->getRepository(Session::class)->findOneById($id);
+
+ return $this->render('@RapsysAir/admin/session.html.twig', ['title' => $title, 'section' => $section, /*'form' => $form->createView(),*/ 'session' => $session]);
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\DataFixtures;
+
+use Rapsys\AirBundle\Entity\Title;
+use Rapsys\AirBundle\Entity\Group;
+use Rapsys\AirBundle\Entity\User;
+use Rapsys\AirBundle\Entity\Location;
+use Rapsys\AirBundle\Entity\Slot;
+
+class AirFixtures extends \Doctrine\Bundle\FixturesBundle\Fixture implements \Symfony\Component\DependencyInjection\ContainerAwareInterface {
+ /**
+ * @var ContainerInterface
+ */
+ private $container;
+
+ public function setContainer(\Symfony\Component\DependencyInjection\ContainerInterface $container = null)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function load(\Doctrine\Common\Persistence\ObjectManager $manager) {
+ $encoder = $this->container->get('security.password_encoder');
+
+ //Title tree
+ $titleTree = array(
+ 'M.' => 'Monsieur',
+ 'Mlle' => 'Mademoiselle',
+ 'Mme' => 'Madame'
+ );
+
+ //Create titles
+ $titles = array();
+ foreach($titleTree as $shortData => $titleData) {
+ $title = new Title();
+ $title->setShort($shortData);
+ $title->setTitle($titleData);
+ $title->setCreated(new \DateTime('now'));
+ $title->setUpdated(new \DateTime('now'));
+ $manager->persist($title);
+ $titles[$shortData] = $title;
+ unset($title);
+ }
+
+ //Group tree
+ $groupTree = array(
+ 'ROLE_USER',
+ 'ROLE_ADMIN',
+ 'ROLE_SUPER'
+ );
+
+ //Create groups
+ $groups = array();
+ foreach($groupTree as $groupData) {
+ $group = new Group($groupData);
+ $group->setCreated(new \DateTime('now'));
+ $group->setUpdated(new \DateTime('now'));
+ $manager->persist($group);
+ $groups[$groupData] = $group;
+ unset($group);
+ }
+
+ //Flush to get the ids
+ $manager->flush();
+
+ //User tree
+ $userTree = array(
+ array(
+ 'short' => 'M.',
+ 'group' => 'ROLE_SUPER',
+ 'mail' => 'airlibre@rapsys.eu',
+ 'pseudonym' => 'Rapsys',
+ 'forename' => 'Raphaël',
+ 'surname' => 'Gertz',
+ 'password' => 'test'
+ ),
+ array(
+ 'short' => 'M.',
+ 'group' => 'ROLE_ADMIN',
+ 'mail' => 'rannou402@orange.fr',
+ 'pseudonym' => 'Mitch',
+ 'forename' => 'Michel',
+ 'surname' => 'Rannou',
+ 'password' => 'test'
+ ),
+ array(
+ 'short' => 'Mlle',
+ 'group' => 'ROLE_ADMIN',
+ 'mail' => 'roxmaps@gmail.com',
+ 'pseudonym' => 'Roxana',
+ 'forename' => 'Roxana',
+ 'surname' => 'Prado',
+ 'password' => 'test'
+ ),
+ array(
+ 'short' => 'M.',
+ 'group' => 'ROLE_ADMIN',
+ 'mail' => 'majid.ghedjatti@gmail.com',
+ 'pseudonym' => 'El Guerrillero',
+ 'forename' => 'Majid',
+ 'surname' => 'Ghedjatti',
+ 'password' => 'test'
+ ),
+ array(
+ 'short' => 'M.',
+ 'group' => 'ROLE_ADMIN',
+ 'mail' => 'denis.courvoisier@wanadoo.fr',
+ 'pseudonym' => 'Sined',
+ 'forename' => 'Denis',
+ 'surname' => 'Courvoisier',
+ 'password' => 'test'
+ ),
+ array(
+ 'short' => 'M.',
+ 'group' => 'ROLE_ADMIN',
+ 'mail' => 'kastango13@gmail.com',
+ 'pseudonym' => 'Kastrat',
+ 'forename' => 'Kastrat',
+ 'surname' => 'Hasaj',
+ 'password' => 'test'
+ ),
+ );
+
+ //Create users
+ $users = array();
+ foreach($userTree as $userData) {
+ $user = new User();
+ $user->setMail($userData['mail']);
+ $user->setPseudonym($userData['pseudonym']);
+ $user->setForename($userData['forename']);
+ $user->setSurname($userData['surname']);
+ $user->setPassword($encoder->encodePassword($user, $userData['password']));
+ $user->setActive(true);
+ $user->setTitle($titles[$userData['short']]);
+ $user->addGroup($groups[$userData['group']]);
+ $user->setCreated(new \DateTime('now'));
+ $user->setUpdated(new \DateTime('now'));
+ $manager->persist($user);
+ $users[] = $user;
+ unset($user);
+ }
+
+ //Flush to get the ids
+ $manager->flush();
+
+ //Location tree
+ $locationTree = [
+ [
+ 'title' => 'Esplanade du Trocadéro',
+ 'address' => '1 Avenue Hussein 1er de Jordanie',
+ #75016 pour meteo-france, accuweather supporte 75116
+ 'zipcode' => '75116',
+ 'city' => 'Paris',
+ 'latitude' => 48.8619,
+ 'longitude' => 2.2888
+ ],
+ [
+ 'title' => 'Opéra Garnier',
+ 'address' => 'Place de l\'Opéra',
+ 'zipcode' => '75009',
+ 'city' => 'Paris',
+ 'latitude' => 48.871365,
+ 'longitude' => 2.332026
+ ],
+ [
+ 'title' => 'Marché Saint Honoré',
+ 'address' => '1 Passage des Jacobins',
+ 'zipcode' => '75001',
+ 'city' => 'Paris',
+ 'latitude' => 48.8668,
+ 'longitude' => 2.331659
+ ],
+ [
+ 'title' => 'Jardin Tino-Rossi',
+ 'address' => '2 Quai Saint-Bernard',
+ 'zipcode' => '75005',
+ 'city' => 'Paris',
+ 'latitude' => 48.847736,
+ 'longitude' => 2.360953
+ ],
+ [
+ 'title' => 'Palais de Tokyo',
+ 'address' => '13 Avenue du Président Wilson',
+ 'zipcode' => '75116',
+ 'city' => 'Paris',
+ 'latitude' => 48.864567,
+ 'longitude' => 2.296892
+ ]
+ ];
+
+ //Create locations
+ $locations = array();
+ foreach($locationTree as $locationData) {
+ $location = new Location();
+ $location->setTitle($locationData['title']);
+ $location->setAddress($locationData['address']);
+ $location->setZipcode($locationData['zipcode']);
+ $location->setCity($locationData['city']);
+ $location->setLatitude($locationData['latitude']);
+ $location->setLongitude($locationData['longitude']);
+ $location->setCreated(new \DateTime('now'));
+ $location->setUpdated(new \DateTime('now'));
+ $manager->persist($location);
+ $locations[$locationData['title']] = $location;
+ unset($location);
+ }
+
+ //Flush to get the ids
+ $manager->flush();
+
+ //Slot tree
+ $slotTree = [
+ [
+ 'begin' => '14:00:00 UTC',
+ 'end' => '19:00:00 UTC'
+ ],
+ [
+ 'begin' => '19:00:00 UTC',
+ 'end' => '23:00:00 UTC'
+ ],
+ [
+ 'begin' => '23:00:00 UTC',
+ 'end' => '02:00:00 UTC'
+ ]
+ ];
+
+ //Create slots
+ $slots = array();
+ foreach($slotTree as $slotData) {
+ $slot = new Slot();
+ $slot->setBegin(new \DateTime($slotData['begin']));
+ $slot->setEnd(new \DateTime($slotData['end']));
+ $slot->setCreated(new \DateTime('now'));
+ $slot->setUpdated(new \DateTime('now'));
+ $manager->persist($slot);
+ $slots[$slot->getId()] = $slot;
+ unset($slot);
+ }
+
+ //Flush to get the ids
+ $manager->flush();
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\Config\FileLocator;
+use Symfony\Component\HttpKernel\DependencyInjection\Extension;
+use Symfony\Component\DependencyInjection\Loader;
+
+/**
+ * This is the class that loads and manages your bundle configuration.
+ *
+ * @link http://symfony.com/doc/current/cookbook/bundles/extension.html
+ */
+class RapsysAirExtension extends Extension {
+ /**
+ * {@inheritdoc}
+ */
+ public function load(array $configs, ContainerBuilder $container) {
+ $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
+ $loader->load('services.yml');
+
+ $configuration = new Configuration();
+ $config = $this->processConfiguration($configuration, $configs);
+
+ //Set default config in parameter
+ if (!$container->hasParameter($alias = $this->getAlias())) {
+ $container->setParameter($alias, $config[$alias]);
+ } else {
+ $config[$alias] = $container->getParameter($alias);
+ }
+
+ //Transform the one level tree in flat parameters
+ foreach($config[$alias] as $k => $v) {
+ //Set is as parameters
+ $container->setParameter($alias.'.'.$k, $v);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getAlias() {
+ return 'rapsys_air';
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Entity;
+
+/**
+ * Application
+ */
+class Application
+{
+ /**
+ * @var integer
+ */
+ private $id;
+
+ /**
+ * @var \DateTime
+ */
+ private $created;
+
+ /**
+ * @var \DateTime
+ */
+ private $updated;
+
+ /**
+ * @var \Doctrine\Common\Collections\Collection
+ */
+ private $votes;
+
+ /**
+ * @var \Rapsys\AirBundle\Entity\Session
+ */
+ private $session;
+
+ /**
+ * @var \Rapsys\AirBundle\Entity\User
+ */
+ private $user;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->votes = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+
+ /**
+ * Get id
+ *
+ * @return integer
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Set created
+ *
+ * @param \DateTime $created
+ *
+ * @return Application
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+
+ return $this;
+ }
+
+ /**
+ * Get created
+ *
+ * @return \DateTime
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * Set updated
+ *
+ * @param \DateTime $updated
+ *
+ * @return Application
+ */
+ public function setUpdated($updated)
+ {
+ $this->updated = $updated;
+
+ return $this;
+ }
+
+ /**
+ * Get updated
+ *
+ * @return \DateTime
+ */
+ public function getUpdated()
+ {
+ return $this->updated;
+ }
+
+ /**
+ * Add vote
+ *
+ * @param \Rapsys\AirBundle\Entity\Vote $vote
+ *
+ * @return Application
+ */
+ public function addVote(\Rapsys\AirBundle\Entity\Vote $vote)
+ {
+ $this->votes[] = $vote;
+
+ return $this;
+ }
+
+ /**
+ * Remove vote
+ *
+ * @param \Rapsys\AirBundle\Entity\Vote $vote
+ */
+ public function removeVote(\Rapsys\AirBundle\Entity\Vote $vote)
+ {
+ $this->votes->removeElement($vote);
+ }
+
+ /**
+ * Get votes
+ *
+ * @return \Doctrine\Common\Collections\Collection
+ */
+ public function getVotes()
+ {
+ return $this->votes;
+ }
+
+ /**
+ * Set session
+ *
+ * @param \Rapsys\AirBundle\Entity\Session $session
+ *
+ * @return Application
+ */
+ public function setSession(\Rapsys\AirBundle\Entity\Session $session = null)
+ {
+ $this->session = $session;
+
+ return $this;
+ }
+
+ /**
+ * Get session
+ *
+ * @return \Rapsys\AirBundle\Entity\Session
+ */
+ public function getSession()
+ {
+ return $this->session;
+ }
+
+ /**
+ * Set user
+ *
+ * @param \Rapsys\AirBundle\Entity\User $user
+ *
+ * @return Application
+ */
+ public function setUser(\Rapsys\AirBundle\Entity\User $user = null)
+ {
+ $this->user = $user;
+
+ return $this;
+ }
+
+ /**
+ * Get user
+ *
+ * @return \Rapsys\AirBundle\Entity\User
+ */
+ public function getUser()
+ {
+ return $this->user;
+ }
+}
--- /dev/null
+<?php
+
+// src/Rapsys/AirBundle/Entity/Group.php
+namespace Rapsys\AirBundle\Entity;
+
+class Group extends \Rapsys\UserBundle\Entity\Group {}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Entity;
+
+/**
+ * Location
+ */
+class Location
+{
+ /**
+ * @var integer
+ */
+ private $id;
+
+ /**
+ * @var string
+ */
+ private $title;
+
+ /**
+ * @var string
+ */
+ private $address;
+
+ /**
+ * @var string
+ */
+ private $zipcode;
+
+ /**
+ * @var string
+ */
+ private $city;
+
+ /**
+ * @var string
+ */
+ private $latitude;
+
+ /**
+ * @var string
+ */
+ private $longitude;
+
+ /**
+ * @var \DateTime
+ */
+ private $created;
+
+ /**
+ * @var \DateTime
+ */
+ private $updated;
+
+ /**
+ * @var \Doctrine\Common\Collections\Collection
+ */
+ private $sessions;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->sessions = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+
+ /**
+ * Get id
+ *
+ * @return integer
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Set title
+ *
+ * @param string $title
+ *
+ * @return Location
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+
+ return $this;
+ }
+
+ /**
+ * Get title
+ *
+ * @return string
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * Set address
+ *
+ * @param string $address
+ *
+ * @return Location
+ */
+ public function setAddress($address)
+ {
+ $this->address = $address;
+
+ return $this;
+ }
+
+ /**
+ * Get address
+ *
+ * @return string
+ */
+ public function getAddress()
+ {
+ return $this->address;
+ }
+
+ /**
+ * Set zipcode
+ *
+ * @param string $zipcode
+ *
+ * @return Location
+ */
+ public function setZipcode($zipcode)
+ {
+ $this->zipcode = $zipcode;
+
+ return $this;
+ }
+
+ /**
+ * Get zipcode
+ *
+ * @return string
+ */
+ public function getZipcode()
+ {
+ return $this->zipcode;
+ }
+
+ /**
+ * Set city
+ *
+ * @param string $city
+ *
+ * @return Location
+ */
+ public function setCity($city)
+ {
+ $this->city = $city;
+
+ return $this;
+ }
+
+ /**
+ * Get city
+ *
+ * @return string
+ */
+ public function getCity()
+ {
+ return $this->city;
+ }
+
+ /**
+ * Set latitude
+ *
+ * @param string $latitude
+ *
+ * @return Location
+ */
+ public function setLatitude($latitude)
+ {
+ $this->latitude = $latitude;
+
+ return $this;
+ }
+
+ /**
+ * Get latitude
+ *
+ * @return string
+ */
+ public function getLatitude()
+ {
+ return $this->latitude;
+ }
+
+ /**
+ * Set longitude
+ *
+ * @param string $longitude
+ *
+ * @return Location
+ */
+ public function setLongitude($longitude)
+ {
+ $this->longitude = $longitude;
+
+ return $this;
+ }
+
+ /**
+ * Get longitude
+ *
+ * @return string
+ */
+ public function getLongitude()
+ {
+ return $this->longitude;
+ }
+
+ /**
+ * Set created
+ *
+ * @param \DateTime $created
+ *
+ * @return Location
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+
+ return $this;
+ }
+
+ /**
+ * Get created
+ *
+ * @return \DateTime
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * Set updated
+ *
+ * @param \DateTime $updated
+ *
+ * @return Location
+ */
+ public function setUpdated($updated)
+ {
+ $this->updated = $updated;
+
+ return $this;
+ }
+
+ /**
+ * Get updated
+ *
+ * @return \DateTime
+ */
+ public function getUpdated()
+ {
+ return $this->updated;
+ }
+
+ /**
+ * Add session
+ *
+ * @param \Rapsys\AirBundle\Entity\Session $session
+ *
+ * @return Location
+ */
+ public function addSession(\Rapsys\AirBundle\Entity\Session $session)
+ {
+ $this->sessions[] = $session;
+
+ return $this;
+ }
+
+ /**
+ * Remove session
+ *
+ * @param \Rapsys\AirBundle\Entity\Session $session
+ */
+ public function removeSession(\Rapsys\AirBundle\Entity\Session $session)
+ {
+ $this->sessions->removeElement($session);
+ }
+
+ /**
+ * Get sessions
+ *
+ * @return \Doctrine\Common\Collections\Collection
+ */
+ public function getSessions()
+ {
+ return $this->sessions;
+ }
+}
+
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Entity;
+
+/**
+ * Session
+ */
+class Session {
+ /**
+ * @var integer
+ */
+ private $id;
+
+ /**
+ * @var \DateTime
+ */
+ private $date;
+
+ /**
+ * @var \DateTime
+ */
+ private $begin;
+
+ /**
+ * @var \DateTime
+ */
+ private $end;
+
+ /**
+ * @var \DateTime
+ */
+ private $created;
+
+ /**
+ * @var \DateTime
+ */
+ private $updated;
+
+ /**
+ * @var \Doctrine\Common\Collections\Collection
+ */
+ private $applications;
+
+ /**
+ * @var \Rapsys\AirBundle\Entity\Location
+ */
+ private $location;
+
+ /**
+ * @var \Rapsys\AirBundle\Entity\Application
+ */
+ private $application;
+
+ /**
+ * Constructor
+ */
+ public function __construct() {
+ $this->applications = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+
+ /**
+ * Get id
+ *
+ * @return integer
+ */
+ public function getId() {
+ return $this->id;
+ }
+
+ /**
+ * Set date
+ *
+ * @param \DateTime $date
+ *
+ * @return Session
+ */
+ public function setDate($date) {
+ $this->date = $date;
+
+ return $this;
+ }
+
+ /**
+ * Get date
+ *
+ * @return \DateTime
+ */
+ public function getDate() {
+ return $this->date;
+ }
+
+ /**
+ * Set begin
+ *
+ * @param \DateTime $begin
+ *
+ * @return Session
+ */
+ public function setBegin($begin) {
+ $this->begin = $begin;
+
+ return $this;
+ }
+
+ /**
+ * Get begin
+ *
+ * @return \DateTime
+ */
+ public function getBegin() {
+ return $this->begin;
+ }
+
+ /**
+ * Set end
+ *
+ * @param \DateTime $end
+ *
+ * @return Session
+ */
+ public function setEnd($end) {
+ $this->end = $end;
+
+ return $this;
+ }
+
+ /**
+ * Get end
+ *
+ * @return \DateTime
+ */
+ public function getEnd() {
+ return $this->end;
+ }
+
+ /**
+ * Set created
+ *
+ * @param \DateTime $created
+ *
+ * @return Session
+ */
+ public function setCreated($created) {
+ $this->created = $created;
+
+ return $this;
+ }
+
+ /**
+ * Get created
+ *
+ * @return \DateTime
+ */
+ public function getCreated() {
+ return $this->created;
+ }
+
+ /**
+ * Set updated
+ *
+ * @param \DateTime $updated
+ *
+ * @return Session
+ */
+ public function setUpdated($updated) {
+ $this->updated = $updated;
+
+ return $this;
+ }
+
+ /**
+ * Get updated
+ *
+ * @return \DateTime
+ */
+ public function getUpdated() {
+ return $this->updated;
+ }
+
+ /**
+ * Add application
+ *
+ * @param \Rapsys\AirBundle\Entity\Application $application
+ *
+ * @return Session
+ */
+ public function addApplication(\Rapsys\AirBundle\Entity\Application $application) {
+ $this->applications[] = $application;
+
+ return $this;
+ }
+
+ /**
+ * Remove application
+ *
+ * @param \Rapsys\AirBundle\Entity\Application $application
+ */
+ public function removeApplication(\Rapsys\AirBundle\Entity\Application $application) {
+ $this->applications->removeElement($application);
+ }
+
+ /**
+ * Get applications
+ *
+ * @return \Doctrine\Common\Collections\Collection
+ */
+ public function getApplications() {
+ return $this->applications;
+ }
+
+ /**
+ * Set location
+ *
+ * @param \Rapsys\AirBundle\Entity\Location $location
+ *
+ * @return Session
+ */
+ public function setLocation(\Rapsys\AirBundle\Entity\Location $location = null) {
+ $this->location = $location;
+
+ return $this;
+ }
+
+ /**
+ * Get location
+ *
+ * @return \Rapsys\AirBundle\Entity\Location
+ */
+ public function getLocation() {
+ return $this->location;
+ }
+ /**
+ * @var \Rapsys\AirBundle\Entity\Slot
+ */
+ private $slot;
+
+
+ /**
+ * Set slot
+ *
+ * @param \Rapsys\AirBundle\Entity\Slot $slot
+ *
+ * @return Session
+ */
+ public function setSlot(\Rapsys\AirBundle\Entity\Slot $slot = null) {
+ $this->slot = $slot;
+
+ return $this;
+ }
+
+ /**
+ * Get slot
+ *
+ * @return \Rapsys\AirBundle\Entity\Slot
+ */
+ public function getSlot() {
+ return $this->slot;
+ }
+
+ /**
+ * Set application
+ *
+ * @param \Rapsys\AirBundle\Entity\Application $application
+ *
+ * @return Session
+ */
+ public function setApplication(\Rapsys\AirBundle\Entity\Application $application = null) {
+ $this->application = $application;
+
+ return $this;
+ }
+
+ /**
+ * Get application
+ *
+ * @return \Rapsys\AirBundle\Entity\Application
+ */
+ public function getApplication() {
+ return $this->application;
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Entity;
+
+/**
+ * Slot
+ */
+class Slot
+{
+ /**
+ * @var integer
+ */
+ private $id;
+
+ /**
+ * @var \DateTime
+ */
+ private $begin;
+
+ /**
+ * @var \DateTime
+ */
+ private $end;
+
+ /**
+ * @var \DateTime
+ */
+ private $created;
+
+ /**
+ * @var \DateTime
+ */
+ private $updated;
+
+ /**
+ * @var \Doctrine\Common\Collections\Collection
+ */
+ private $sessions;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->sessions = new \Doctrine\Common\Collections\ArrayCollection();
+ }
+
+ /**
+ * Get id
+ *
+ * @return integer
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Set begin
+ *
+ * @param \DateTime $begin
+ *
+ * @return Slot
+ */
+ public function setBegin($begin)
+ {
+ $this->begin = $begin;
+
+ return $this;
+ }
+
+ /**
+ * Get begin
+ *
+ * @return \DateTime
+ */
+ public function getBegin()
+ {
+ return $this->begin;
+ }
+
+ /**
+ * Set end
+ *
+ * @param \DateTime $end
+ *
+ * @return Slot
+ */
+ public function setEnd($end)
+ {
+ $this->end = $end;
+
+ return $this;
+ }
+
+ /**
+ * Get end
+ *
+ * @return \DateTime
+ */
+ public function getEnd()
+ {
+ return $this->end;
+ }
+
+ /**
+ * Set created
+ *
+ * @param \DateTime $created
+ *
+ * @return Slot
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+
+ return $this;
+ }
+
+ /**
+ * Get created
+ *
+ * @return \DateTime
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * Set updated
+ *
+ * @param \DateTime $updated
+ *
+ * @return Slot
+ */
+ public function setUpdated($updated)
+ {
+ $this->updated = $updated;
+
+ return $this;
+ }
+
+ /**
+ * Get updated
+ *
+ * @return \DateTime
+ */
+ public function getUpdated()
+ {
+ return $this->updated;
+ }
+
+ /**
+ * Add session
+ *
+ * @param \Rapsys\AirBundle\Entity\Session $session
+ *
+ * @return Slot
+ */
+ public function addSession(\Rapsys\AirBundle\Entity\Session $session)
+ {
+ $this->sessions[] = $session;
+
+ return $this;
+ }
+
+ /**
+ * Remove session
+ *
+ * @param \Rapsys\AirBundle\Entity\Session $session
+ */
+ public function removeSession(\Rapsys\AirBundle\Entity\Session $session)
+ {
+ $this->sessions->removeElement($session);
+ }
+
+ /**
+ * Get sessions
+ *
+ * @return \Doctrine\Common\Collections\Collection
+ */
+ public function getSessions()
+ {
+ return $this->sessions;
+ }
+
+ public function getTitle() {
+ return $this->begin->format('H:i').'-'.$this->end->format('H:i');
+ }
+}
--- /dev/null
+<?php
+
+// src/Rapsys/AirBundle/Entity/Title.php
+namespace Rapsys\AirBundle\Entity;
+
+class Title extends \Rapsys\UserBundle\Entity\Title {
+}
--- /dev/null
+<?php
+
+// src/Rapsys/AirBundle/Entity/User.php
+namespace Rapsys\AirBundle\Entity;
+
+class User extends \Rapsys\UserBundle\Entity\User {
+ /**
+ * @var \Doctrine\Common\Collections\Collection
+ */
+ private $votes;
+
+ /**
+ * @var \Doctrine\Common\Collections\Collection
+ */
+ private $applications;
+
+ /**
+ * Constructor
+ */
+ public function __construct() {
+ parent::__construct();
+ }
+
+ /**
+ * Add vote
+ *
+ * @param \Rapsys\AirBundle\Entity\Vote $vote
+ *
+ * @return User
+ */
+ public function addVote(\Rapsys\AirBundle\Entity\Vote $vote) {
+ $this->votes[] = $vote;
+
+ return $this;
+ }
+
+ /**
+ * Remove vote
+ *
+ * @param \Rapsys\AirBundle\Entity\Vote $vote
+ */
+ public function removeVote(\Rapsys\AirBundle\Entity\Vote $vote) {
+ $this->votes->removeElement($vote);
+ }
+
+ /**
+ * Get votes
+ *
+ * @return \Doctrine\Common\Collections\Collection
+ */
+ public function getVotes() {
+ return $this->votes;
+ }
+
+ /**
+ * Add application
+ *
+ * @param \Rapsys\AirBundle\Entity\Application $application
+ *
+ * @return User
+ */
+ public function addApplication(\Rapsys\AirBundle\Entity\Application $application) {
+ $this->applications[] = $application;
+
+ return $this;
+ }
+
+ /**
+ * Remove application
+ *
+ * @param \Rapsys\AirBundle\Entity\Application $application
+ */
+ public function removeApplication(\Rapsys\AirBundle\Entity\Application $application) {
+ $this->applications->removeElement($application);
+ }
+
+ /**
+ * Get applications
+ *
+ * @return \Doctrine\Common\Collections\Collection
+ */
+ public function getApplications() {
+ return $this->applications;
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Entity;
+
+/**
+ * Vote
+ */
+class Vote
+{
+ /**
+ * @var integer
+ */
+ private $id;
+
+ /**
+ * @var \DateTime
+ */
+ private $created;
+
+ /**
+ * @var \DateTime
+ */
+ private $updated;
+
+ /**
+ * @var \Rapsys\AirBundle\Entity\Application
+ */
+ private $application;
+
+ /**
+ * @var \Rapsys\AirBundle\Entity\User
+ */
+ private $user;
+
+
+ /**
+ * Get id
+ *
+ * @return integer
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Set created
+ *
+ * @param \DateTime $created
+ *
+ * @return Vote
+ */
+ public function setCreated($created)
+ {
+ $this->created = $created;
+
+ return $this;
+ }
+
+ /**
+ * Get created
+ *
+ * @return \DateTime
+ */
+ public function getCreated()
+ {
+ return $this->created;
+ }
+
+ /**
+ * Set updated
+ *
+ * @param \DateTime $updated
+ *
+ * @return Vote
+ */
+ public function setUpdated($updated)
+ {
+ $this->updated = $updated;
+
+ return $this;
+ }
+
+ /**
+ * Get updated
+ *
+ * @return \DateTime
+ */
+ public function getUpdated()
+ {
+ return $this->updated;
+ }
+
+ /**
+ * Set application
+ *
+ * @param \Rapsys\AirBundle\Entity\Application $application
+ *
+ * @return Vote
+ */
+ public function setApplication(\Rapsys\AirBundle\Entity\Application $application = null)
+ {
+ $this->application = $application;
+
+ return $this;
+ }
+
+ /**
+ * Get application
+ *
+ * @return \Rapsys\AirBundle\Entity\Application
+ */
+ public function getApplication()
+ {
+ return $this->application;
+ }
+
+ /**
+ * Set user
+ *
+ * @param \Rapsys\AirBundle\Entity\User $user
+ *
+ * @return Vote
+ */
+ public function setUser(\Rapsys\AirBundle\Entity\User $user = null)
+ {
+ $this->user = $user;
+
+ return $this;
+ }
+
+ /**
+ * Get user
+ *
+ * @return \Rapsys\AirBundle\Entity\User
+ */
+ public function getUser()
+ {
+ return $this->user;
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Form;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Bridge\Doctrine\Form\Type\EntityType;
+use Symfony\Component\Form\Extension\Core\Type\DateType;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+use Symfony\Component\Validator\Constraints\Date;
+use Symfony\Component\Validator\Constraints\NotBlank;
+
+class ApplicationType extends AbstractType {
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(FormBuilderInterface $builder, array $options) {
+ return $builder
+ ->add('location', EntityType::class, array('class' => 'RapsysAirBundle:Location', 'choice_label' => 'title', 'attr' => array('placeholder' => 'Your location'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your location')))))
+ ->add('date', DateType::class, array('attr' => [ 'placeholder' => 'Your date', 'class' => 'date' ], 'html5' => true, 'input' => 'datetime', 'data' => new \DateTime('+7 day'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your date')), new Date(array('message' => 'Your date doesn\'t seems to be valid')))))
+ ->add('slot', EntityType::class, array('class' => 'RapsysAirBundle:Slot', 'choice_label' => 'title', 'attr' => array('placeholder' => 'Your slot'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your slot')))))
+ ->add('submit', SubmitType::class, array('label' => 'Send', 'attr' => array('class' => 'submit')));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function configureOptions(OptionsResolver $resolver) {
+ $resolver->setDefaults(['error_bubbling' => true]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName() {
+ return 'rapsys_air_application';
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Form;
+
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Component\Form\Extension\Core\Type\TextType;
+use Symfony\Component\Form\Extension\Core\Type\TextareaType;
+use Symfony\Component\Form\Extension\Core\Type\EmailType;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+use Symfony\Component\Validator\Constraints\Email;
+use Symfony\Component\Validator\Constraints\NotBlank;
+
+class ContactType extends AbstractType {
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(FormBuilderInterface $builder, array $options) {
+ return $builder->add('name', TextType::class, array('attr' => array('placeholder' => 'Your name'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your name')))))
+ ->add('subject', TextType::class, array('attr' => array('placeholder' => 'Subject'), 'constraints' => array(new NotBlank(array('message' => 'Please provide your subject')))))
+ ->add('mail', EmailType::class, array('attr' => array('placeholder' => 'Your mail address'), 'constraints' => array(new NotBlank(array('message' => 'Please provide a valid mail')), new Email(array('message' => 'Your mail doesn\'t seems to be valid')))))
+ ->add('message', TextareaType::class, array('attr' => array('placeholder' => 'Your message here', 'cols' => 50, 'rows' => 15), 'constraints' => array(new NotBlank(array('message' => 'Please provide your message')))))
+ ->add('submit', SubmitType::class, array('label' => 'Send', 'attr' => array('class' => 'submit')));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function configureOptions(OptionsResolver $resolver) {
+ $resolver->setDefaults(['error_bubbling' => true]);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName() {
+ return 'contact_form';
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class RapsysAirBundle extends Bundle
+{
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Repository;
+
+/**
+ * ApplicationRepository
+ */
+class ApplicationRepository extends \Doctrine\ORM\EntityRepository {
+ /**
+ * Find session by session and user
+ *
+ * @param $session The session
+ * @param $user The user
+ */
+ public function findOneBySessionUser($session, $user) {
+ //Fetch article
+ $ret = $this->getEntityManager()
+ ->createQuery('SELECT a FROM RapsysAirBundle:Application a WHERE (a.session = :session AND a.user = :user)')
+ ->setParameter('session', $session)
+ ->setParameter('user', $user)
+ ->getSingleResult();
+
+ //Send result
+ return $ret;
+ }
+}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Repository;
+
+/**
+ * SessionRepository
+ */
+class SessionRepository extends \Doctrine\ORM\EntityRepository {
+ /**
+ * Find session by location, slot and date
+ *
+ * @param $location The location
+ * @param $slot The slot
+ * @param $date The datetime
+ */
+ public function findOneByLocationSlotDate($location, $slot, $date) {
+ //Fetch session
+ $ret = $this->getEntityManager()
+ ->createQuery('SELECT s FROM RapsysAirBundle:Session s WHERE (s.location = :location AND s.slot = :slot AND s.date = :date)')
+ ->setParameter('location', $location)
+ ->setParameter('slot', $slot)
+ ->setParameter('date', $date)
+ ->getSingleResult();
+
+ //Send result
+ return $ret;
+ }
+
+ /**
+ * Find sessions by date period
+ *
+ * @param $period The date period
+ */
+ public function findByDatePeriod($period) {
+ //Fetch sessions
+ $ret = $this->getEntityManager()
+ ->createQuery('SELECT s FROM RapsysAirBundle:Session s WHERE s.date BETWEEN :begin AND :end')
+ ->setParameter('begin', $period->getStartDate())
+ ->setParameter('end', $period->getEndDate())
+ ->getResult();
+
+ //Send result
+ return $ret;
+ }
+}
--- /dev/null
+Rapsys\AirBundle\Entity\Application:
+ type: entity
+ repositoryClass: Rapsys\AirBundle\Repository\ApplicationRepository
+ table: applications
+ id:
+ id:
+ type: integer
+ generator:
+ strategy: AUTO
+ options:
+ unsigned: true
+ fields:
+ created:
+ type: datetime
+ updated:
+ type: datetime
+ manyToOne:
+ session:
+ targetEntity: Rapsys\AirBundle\Entity\Session
+ inversedBy: applications
+ user:
+ targetEntity: Rapsys\AirBundle\Entity\User
+ inversedBy: applications
+ oneToMany:
+ votes:
+ targetEntity: Rapsys\AirBundle\Entity\Vote
+ mappedBy: application
--- /dev/null
+Rapsys\AirBundle\Entity\Group:
+ type: entity
+ #repositoryClass: Rapsys\AirBundle\Repository\GroupRepository
+ table: groups
+ manyToMany:
+ users:
+ targetEntity: Rapsys\AirBundle\Entity\User
+ mappedBy: groups
--- /dev/null
+Rapsys\AirBundle\Entity\Location:
+ type: entity
+ #repositoryClass: Rapsys\AirBundle\Repository\LocationRepository
+ table: locations
+ id:
+ id:
+ type: integer
+ generator:
+ strategy: AUTO
+ options:
+ unsigned: true
+ fields:
+ title:
+ type: string
+ length: 24
+ address:
+ type: string
+ length: 32
+ zipcode:
+ type: string
+ length: 5
+ city:
+ type: string
+ length: 64
+ latitude:
+ type: decimal
+ precision: 8
+ scale: 6
+ longitude:
+ type: decimal
+ precision: 9
+ scale: 6
+ created:
+ type: datetime
+ updated:
+ type: datetime
+ oneToMany:
+ sessions:
+ targetEntity: Rapsys\AirBundle\Entity\Session
+ mappedBy: location
+
+# manyToOne:
+# title:
+# targetEntity: Rapsys\UserBundle\Entity\Title
+# inversedBy: users
+# manyToMany:
+# groups:
+# targetEntity: Rapsys\UserBundle\Entity\Group
+# inversedBy: users
+# joinTable:
+# name: groups_users
+#
+# manyToOne:
+# site:
+# targetEntity: Rapsys\BlogBundle\Entity\Site
+# inversedBy: articles
+# author:
+# targetEntity: Rapsys\BlogBundle\Entity\Author
+# inversedBy: articles
+# manyToMany:
+# keywords:
+# targetEntity: Rapsys\BlogBundle\Entity\Keyword
+# inversedBy: articles
+# joinTable:
+# name: articles_keywords
+# oneToMany:
+# article_translations:
+# targetEntity: Rapsys\BlogBundle\Entity\ArticleTranslation
+# mappedBy: article
--- /dev/null
+Rapsys\AirBundle\Entity\Session:
+ type: entity
+ repositoryClass: Rapsys\AirBundle\Repository\SessionRepository
+ table: sessions
+ id:
+ id:
+ type: integer
+ generator:
+ strategy: AUTO
+ options:
+ unsigned: true
+ fields:
+ date:
+ type: date
+ begin:
+ type: time
+ nullable: true
+ end:
+ type: time
+ nullable: true
+ created:
+ type: datetime
+ updated:
+ type: datetime
+ oneToOne:
+ application:
+ targetEntity: Rapsys\AirBundle\Entity\Application
+ manyToOne:
+ location:
+ targetEntity: Rapsys\AirBundle\Entity\Location
+ inversedBy: sessions
+ slot:
+ targetEntity: Rapsys\AirBundle\Entity\Slot
+ inversedBy: sessions
+ oneToMany:
+ applications:
+ targetEntity: Rapsys\AirBundle\Entity\Application
+ mappedBy: session
+ uniqueConstraints:
+ date_location_slot:
+ columns: [ date, location_id, slot_id ]
--- /dev/null
+Rapsys\AirBundle\Entity\Slot:
+ type: entity
+ #repositoryClass: Rapsys\AirBundle\Repository\SlotRepository
+ table: slots
+ id:
+ id:
+ type: integer
+ generator:
+ strategy: AUTO
+ options:
+ unsigned: true
+ fields:
+ begin:
+ type: time
+ end:
+ type: time
+ created:
+ type: datetime
+ updated:
+ type: datetime
+ oneToMany:
+ sessions:
+ targetEntity: Rapsys\AirBundle\Entity\Session
+ mappedBy: slot
--- /dev/null
+Rapsys\AirBundle\Entity\Title:
+ type: entity
+ #repositoryClass: Rapsys\AirBundle\Repository\TitleRepository
+ table: titles
+ oneToMany:
+ users:
+ targetEntity: User
+ mappedBy: title
--- /dev/null
+Rapsys\AirBundle\Entity\User:
+ type: entity
+ #repositoryClass: Rapsys\AirBundle\Repository\UserRepository
+ table: users
+ oneToMany:
+ votes:
+ targetEntity: Rapsys\AirBundle\Entity\Vote
+ mappedBy: user
+ applications:
+ targetEntity: Rapsys\AirBundle\Entity\Application
+ mappedBy: user
+# manyToMany:
+# groups:
+# targetEntity: Group
+# inversedBy: users
+# joinTable:
+# name: groups_users
+ associationOverride:
+ groups:
+ joinTable:
+ name: groups_users
+ joinColumns:
+ id:
+ name: user_id
+ inverseJoinColumns:
+ id:
+ name: group_id
--- /dev/null
+Rapsys\AirBundle\Entity\Vote:
+ type: entity
+ #repositoryClass: Rapsys\AirBundle\Repository\VoteRepository
+ table: votes
+ id:
+ id:
+ type: integer
+ generator:
+ strategy: AUTO
+ options:
+ unsigned: true
+ fields:
+ created:
+ type: datetime
+ updated:
+ type: datetime
+ manyToOne:
+ application:
+ targetEntity: Rapsys\AirBundle\Entity\Application
+ inversedBy: votes
+ user:
+ targetEntity: Rapsys\AirBundle\Entity\User
+ inversedBy: votes
--- /dev/null
+rapsys_air_homepage:
+ path: /
+ defaults: { _controller: RapsysAirBundle:Default:index }
+
+rapsys_air_admin:
+ path: /admin
+ defaults: { _controller: RapsysAirBundle:Default:admin }
+
+rapsys_air_contact:
+ path: /contact
+ defaults: { _controller: RapsysAirBundle:Default:contact }
+
+rapsys_air_session:
+ path: /admin/session/{id}
+ defaults: { _controller: RapsysAirBundle:Default:session }
+ requirements:
+ id: '\d+'
--- /dev/null
+services:
+ rapsys_air.twig.file_get_contents:
+ class: Rapsys\AirBundle\Twig\FileGetContentsExtension
+ tags: [ twig.extension ]
+ rapsys_air.twig.base64:
+ class: Rapsys\AirBundle\Twig\Base64Extension
+ tags: [ twig.extension ]
+ rapsys_air.twig.bb2html:
+ class: Rapsys\AirBundle\Twig\Bb2htmlExtension
+ tags: [ twig.extension ]
+ Rapsys\AirBundle\DataFixtures\AirFixtures:
+ tags: [ doctrine.fixture.orm ]
+# rapsys_air.example:
+# class: Rapsys\AirBundle\Example
+# arguments: ["@service_id", "plain_value", "%parameter%"]
--- /dev/null
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center, dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video, input, textarea, button, select, option {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+
+article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+
+body {
+ line-height: 1;
+}
+
+ol, ul {
+ list-style: none;
+}
+
+blockquote, q {
+ quotes: none;
+}
+
+blockquote:before, blockquote:after, q:before, q:after {
+ content: '';
+ content: none;
+}
+
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
--- /dev/null
+/* Reset link */
+a {
+ text-decoration: none;
+ color: #066;
+}
+
+a:hover {
+ text-decoration: underline solid #00c3f9;
+}
+
+h1::first-letter,
+h2::first-letter,
+h3::first-letter,
+h4::first-letter,
+h5::first-letter,
+h6::first-letter,
+a::first-letter {
+ color: #00c3f9;
+}
+
+/* Default styling */
+h1 {
+ font-size: 2rem;
+ margin: 1.34rem 0;
+}
+
+h2 {
+ font-size: 1.5rem;
+ margin: 1.245rem 0;
+}
+
+h3 {
+ font-size: 1.17rem;
+ margin: 1.17rem 0;
+}
+
+h4 {
+ font-size: 1rem;
+ margin: 1.33rem 0;
+}
+
+h5 {
+ font-size: .83rem;
+ margin: 1.386rem 0;
+}
+
+h6 {
+ font-size: .67rem;
+ margin: 1.561rem 0;
+}
+
+p {
+}
+
+body {
+ display: flex;
+ flex-flow: column wrap;
+ color: #066;
+}
+
+/* Header */
+#header {
+ border: .1rem solid #00c3f9;
+ border-top: 0;
+ border-radius: 0 0 .5rem .5rem;
+ margin: .5rem;
+ margin-top: 0;
+ padding: .5rem;
+ left: 0;
+ right: 0;
+ display: flex;
+ justify-content: space-between;
+ min-width: 180px;
+}
+
+#header h1 {
+ order: 0;
+ padding: 0;
+ margin: 0;
+ vertical-align: middle;
+ white-space: nowrap;
+}
+
+#header h1 a {
+ display: flex;
+}
+
+/*#header h2 {
+ order: 1;
+ font-size: 1.5rem;
+ margin: 0;
+ white-space: nowrap;
+}
+
+#header h2:before {
+ content: ">\00a0";
+}*/
+
+#header nav {
+ order: 3;
+ margin-left: auto;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: flex-end;
+}
+
+#header nav h2 {
+ display: none;
+}
+
+#header nav a {
+ text-align: center;
+ border-radius: .25rem;
+ padding: .375rem .5rem .25rem .5rem;
+ margin: 0 0 .1rem .5rem;
+ border: .1rem solid #00c3f9;
+ font-weight: bold;
+ background-color: #cff;
+}
+
+/* Message */
+div.error::before,
+div.error::after {
+ content: "⚠";
+ line-height: 100%;
+ margin: auto 0;
+}
+
+div.error {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ border: .05rem solid #c33333;
+ background-color: #f9c3c3;
+ color: #c33333;
+ font-size: .9rem;
+ padding: .2rem;
+ border-radius: .2rem;
+ text-align: center;
+}
+
+div.flash {
+ margin: 0 .5rem .5rem;
+}
+
+/*ul#error::before,
+ul#error::after,
+ul.error::before,
+ul.error::after,
+ul#notice::before,
+ul#notice::after {
+ content: "⚠";
+ padding: .1rem .5rem 0 .5rem;
+ position: absolute;
+}
+
+ul#error::before,
+ul#error::after {
+ padding-top: .2rem;
+}
+
+ul#notice::before,
+ul#notice::after {
+ content: "ℹ";
+ padding-top: .3rem;
+}
+
+ul#notice::after,
+ul#error::after {
+ margin-left: 37.8rem;
+}
+
+ul.error::after {
+ margin-left: 34rem;
+}
+
+ul#notice,
+ul#error,
+ul.error {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ box-sizing: border-box;
+ text-align: center;
+ border: .05rem solid #c33333;
+ background-color: #f9c3c3;
+ color: #c33333;
+ font-size: .9rem;
+ padding: .2rem;
+ border-radius: .2rem;
+ width: 40rem;
+ margin: 0 auto .5rem auto;
+}
+
+ul.error {
+ width: 36rem;
+ margin: .2rem 0 0 0;
+}
+
+ul#notice {
+ border: .05rem solid #3333c3;
+ background-color: #c3c3f9;
+ color: #3333c3;
+}
+
+ul.error {
+ margin-top: .2rem;
+}*/
+
+/* Content */
+#form,
+#content,
+#dashboard {
+ border: .1rem solid #00c3f9;
+ border-radius: .5rem;
+ margin: .5rem;
+ margin-top: 0;
+ overflow: hidden;
+ padding: .5rem;
+}
+
+section h2 {
+ background-color: #cff;
+ border-bottom: .1rem solid #00c3f9;
+ margin: -.5rem -.5rem .5rem -.5rem;
+ padding: .5rem;
+ padding-bottom: .4rem;
+}
+
+/* Form */
+form {
+ display: flex;
+ flex-direction: column;
+ border: .05rem solid #00c3f9;
+ border-radius: .2rem;
+ padding: .5rem;
+}
+
+form section {
+ margin-bottom: 1rem;
+}
+
+form section:only-child,
+form section:last-child,
+form section:last-of-type {
+ margin-bottom: .5rem;
+}
+
+form section section,
+form section section:only-child,
+form section section:last-child,
+form section section:last-of-type {
+ width: 50%;
+ margin-bottom: 0;
+}
+
+form div {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ margin-bottom: .5rem;
+}
+
+form div:only-child,
+form div:last-child,
+form div:last-of-type {
+ margin-bottom: 0;
+}
+
+form section div.error {
+ margin: 0 1rem;
+}
+
+form section section div.error {
+ margin: .25rem 0 0 0;
+}
+
+label {
+ min-width: 5rem;
+ font-size: .9rem;
+ padding: .2rem 0;
+ text-align: right;
+ white-space: nowrap;
+}
+
+button,
+input,
+select,
+textarea {
+ box-sizing: border-box;
+ width: 100%;
+ padding: .1rem;
+ border: .05rem solid #00c3f9;
+ border-radius: .2rem;
+ font-size: .8rem;
+ color: #066;
+}
+
+button.submit {
+ width: 25%;
+ min-width: 8rem;
+ margin: 0 auto;
+ padding: .2rem .1rem;
+}
+
+/* Vertical form */
+.form_col {
+ margin-left: .5rem;
+ width: 10rem;
+}
+
+.form_col div {
+ flex-direction: column;
+}
+
+.form_col div.error {
+ flex-direction: row;
+}
+
+.form_col label {
+ text-align: center;
+}
+
+.form_col section section,
+.form_col section section:only-child,
+.form_col section section:last-child,
+.form_col section section:last-of-type {
+ width: auto;
+}
+
+.form_col div.date {
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+/* Dashboard */
+#dashboard .panel {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ place-content: space-between;
+}
+
+#dashboard .grid {
+ display: table;
+ border: .05rem solid #00c3f9;
+ flex-grow: 1;
+ border-radius: .2rem; /* marche pas sur chrome */
+ table-layout: fixed;
+ width: calc(100% - 12rem);
+ border-collapse: collapse;
+}
+
+#dashboard .cell {
+ display: table-cell;
+ text-align: left;
+ border: .05rem solid #00c3f9;
+ font-size: initial;
+ height: 8rem;
+}
+
+#dashboard dl.cell {
+ height: 3rem;
+}
+
+#dashboard .cell h3 {
+ font-size: 1rem;
+ padding: .25rem;
+ margin: 0;
+}
+
+#dashboard .cell dd {
+ text-align: center;
+}
+
+#dashboard .seventh {
+ width: calc(100% / 7);
+}
+
+#dashboard .disabled {
+ color: #acc;
+ background-color: #bee;
+}
+
+#dashboard .current {
+ background-color: #cff;
+}
+
+#dashboard .next {
+ background-color: #eff;
+}
+
+#dashboard .session {
+ border-radius: .2rem;
+ border: .1rem solid #00c3f9;
+ font-size: .8rem;
+ padding: .2rem;
+ margin: 0 .1rem .1rem .1rem;
+ overflow-x: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+#dashboard .pending {
+ background-color: #ccc;
+}
+
+#dashboard .granted {
+ background-color: #cff;
+ /*background-color: #33b679;
+ border-color: #33b679;*/
+}
+
+#dashboard .disputed {
+ background-color: #fcc;
+}
+
+#dashboard .orphaned {
+ background-color: #fc9;
+}
+
+/* Footer */
+#footer {
+ border: .1rem solid #00c3f9;
+ border-radius: .5rem;
+ margin: .5rem;
+ margin-top: 0;
+ padding: .5rem;
+ text-align: center;
+ font-size: .8rem;
+ display: flex;
+ justify-content: space-between;
+ background-color: #cff;
+}
+
+#footer details {
+ font-weight: bold;
+}
+
+#footer summary::after {
+ display: none;
+}
+
+#footer summary::-webkit-details-marker {
+ display: none;
+}
+
+/* viewport responsive hack */
+@media ( max-width: 650px ) {
+ #header {
+ flex-wrap: wrap;
+ }
+
+ #dashboard .panel {
+ place-content: center;
+ flex-direction: column;
+ }
+
+ #dashboard .grid {
+ width: 100%;
+ }
+
+ #dashboard div.grid {
+ display: grid;
+ }
+
+ .form_col {
+ margin: .5rem auto 0 auto;
+ }
+}
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ viewBox="0 0 210 297"
+ version="1.1"
+ id="svg4570"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)"
+ sodipodi:docname="openair.logo.svg">
+ <title
+ id="title5131">Open Air Logo</title>
+ <defs
+ id="defs4564">
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5174"
+ id="radialGradient5140"
+ cx="3.5708413"
+ cy="290.94611"
+ fx="3.5708413"
+ fy="290.94611"
+ r="3.5708413"
+ gradientTransform="matrix(0.96030384,0.85677319,-2.1146358,1.886651,616.04931,-259.20651)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5174">
+ <stop
+ id="stop5166"
+ offset="0"
+ style="stop-color:#00c3f9;stop-opacity:0" />
+ <stop
+ style="stop-color:#00c3f9;stop-opacity:0.33"
+ offset="0.40000001"
+ id="stop5168" />
+ <stop
+ id="stop5172"
+ offset="1"
+ style="stop-color:#00c3f9;stop-opacity:1;" />
+ </linearGradient>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="15.839192"
+ inkscape:cx="19.689661"
+ inkscape:cy="10.360728"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="2560"
+ inkscape:window-height="1537"
+ inkscape:window-x="-4"
+ inkscape:window-y="-4"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4567">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Open Air Logo</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ inkscape:connector-curvature="0"
+ id="path5017"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:url(#radialGradient5140);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.11197994;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ d="m 4.2394596,289.42973 c -0.7893188,-7.7e-4 -1.6132823,0.29881 -2.1442353,0.89641 -0.5268689,0.5976 -0.790304,1.41203 -0.790304,2.44326 0,1.02758 0.2634351,1.84019 0.790304,2.43778 0.530953,0.5976 1.2456986,0.89641 2.1442353,0.89641 0.8985367,0 1.6091981,-0.29881 2.1319828,-0.89641 0.5268689,-0.59759 0.790304,-1.4102 0.790304,-2.43778 0,-1.03123 -0.2634351,-1.84566 -0.790304,-2.44326 -0.5227847,-0.5976 -1.3463617,-0.89563 -2.1319828,-0.89641 z m 0,-0.8964 c 1.2824569,0 2.3076057,0.38444 3.0754463,1.1533 0.7678406,0.76523 1.1517608,1.7928 1.1517608,3.08277 0,1.2863 -0.3839202,2.3139 -1.1517608,3.08275 C 6.5470653,296.61738 5.5219165,297 4.2394596,297 2.9529184,297 1.9236856,296.61738 1.1517607,295.85215 0.38392027,295.08693 0,294.05936 0,292.7694 c 0,-1.28997 0.38392027,-2.31754 1.1517607,-3.08277 0.7719249,-0.76886 1.8011577,-1.1533 3.0876989,-1.1533 z"
+ sodipodi:nodetypes="acscscscascscscscs"
+ inkscape:export-xdpi="100.34"
+ inkscape:export-ydpi="100.34" />
+ </g>
+</svg>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ viewBox="0 0 210 297"
+ version="1.1"
+ id="svg8"
+ sodipodi:docname="logo.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <defs
+ id="defs2">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5174">
+ <stop
+ id="stop5166"
+ offset="0"
+ style="stop-color:#00c3f9;stop-opacity:0" />
+ <stop
+ style="stop-color:#00c3f9;stop-opacity:0.33"
+ offset="0.40000001"
+ id="stop5168" />
+ <stop
+ id="stop5172"
+ offset="1"
+ style="stop-color:#00c3f9;stop-opacity:1;" />
+ </linearGradient>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath18">
+ <path
+ d="M 3044.85,0 C 1363.23,0 0,203.461 0,454.441 0,705.41 1363.23,908.859 3044.85,908.859 4726.47,908.859 6089.69,705.41 6089.69,454.441 6089.69,203.461 4726.47,0 3044.85,0"
+ id="path20" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath30">
+ <path
+ d="M 0,3832 0,0 l 6089.69,0 0,3832 L 0,3832 Z"
+ id="path32" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath80">
+ <path
+ d="m 2788.36,2246.6 -256.48,0 c -3.06,0.66 -19.07,4.34 -19.07,4.34 -17.41,4.1 -33.17,8.18 -48.17,12.44 l -6.49,1.93 c -15.5,4.52 -30.45,9.28 -44.44,14.09 l -4.55,1.52 c -13.92,4.85 -28.16,10.26 -43.53,16.52 l -8.06,3.3 c -14.03,5.88 -27.59,11.99 -40.31,18.1 l -6.54,3.26 c -14.56,7.15 -27.3,13.83 -39.59,20.71 -11.57,6.57 -23.65,13.86 -36.94,22.42 l -5.91,3.79 c -11.33,7.43 -22.51,15.21 -33.21,23.16 l -5.56,4.17 c -11.98,9.07 -22.38,17.36 -31.8,25.43 l -1.19,1.03 c -9.72,8.35 -19.3,17.09 -29.29,26.74 l -3.52,3.35 c -8.91,8.76 -17.92,18.14 -26.74,27.89 l -4.06,4.54 c -9.19,10.33 -17.29,19.98 -24.77,29.48 l -1.68,2.18 c -8.07,10.36 -15.78,20.86 -22.89,31.21 l -1.03,1.46 c -6.93,10.11 -13.69,20.71 -21.23,33.28 l -1.86,3.11 c -6.58,11.16 -12.75,22.33 -18.31,33.13 l -1.27,2.53 c -11.68,22.94 -22.2,46.97 -31.59,72.27 l -0.64,1.7 c -4.41,12.01 -8.53,24.3 -12.26,36.52 l -0.6,1.99 c -11.33,37.51 -19.82,76.79 -25.31,117.56 -0.35,2.6 -0.55,5.25 -0.88,7.85 30.2,9.7 62.33,15.04 95.71,15.04 9.99,0 20.46,-0.6 32,-1.82 l 15.43,-1.64 1.44,15.45 c 15.75,169.23 79.48,321.07 167.3,405.86 -19.6,-51.67 -34.76,-105.27 -45.24,-160 -18.26,-95.59 -21.4,-190.06 -9.27,-280.74 5.48,-40.77 13.97,-80.05 25.31,-117.56 l 0.59,-1.99 c 3.73,-12.22 7.86,-24.51 12.27,-36.52 l 0.63,-1.7 c 9.39,-25.3 19.91,-49.33 31.6,-72.27 l 1.26,-2.53 c 5.56,-10.8 11.74,-21.97 18.31,-33.13 l 1.87,-3.11 c 7.53,-12.57 14.3,-23.17 21.22,-33.28 l 1.04,-1.46 c 7.11,-10.35 14.82,-20.85 22.89,-31.21 l 1.67,-2.18 c 7.49,-9.5 15.58,-19.15 24.77,-29.48 l 4.06,-4.54 c 8.82,-9.75 17.83,-19.13 26.75,-27.89 l 3.51,-3.35 c 9.99,-9.65 19.58,-18.39 29.29,-26.74 l 1.19,-1.03 c 9.42,-8.07 19.83,-16.36 31.8,-25.43 l 5.56,-4.17 c 10.71,-7.95 21.89,-15.73 33.21,-23.16 l 5.91,-3.79 c 13.29,-8.56 25.37,-15.85 36.95,-22.42 12.28,-6.88 25.03,-13.56 39.59,-20.71 l 6.53,-3.26 c 12.72,-6.11 26.28,-12.22 40.31,-18.1 l 8.06,-3.3 c 15.38,-6.26 29.61,-11.67 43.53,-16.52 l 4.55,-1.52 c 13.99,-4.81 28.95,-9.57 44.45,-14.09 l 6.47,-1.93 c 15.01,-4.26 30.77,-8.34 48.18,-12.44 0,0 16.02,-3.68 19.07,-4.34"
+ id="path82" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath92">
+ <path
+ d="m 4078.74,2296.83 c -70.64,7.85 -137.5,18.24 -200.68,31.03 150.52,95.28 244.88,262.64 244.88,443.38 0,245.43 -173.93,461.07 -413.56,512.75 l -7.73,1.66 -3.11,7.27 c -86.59,201.73 -254.36,351.23 -455.56,417.29 11.47,19.88 20.58,32.95 25.61,37.54 299.13,-1.39 568.3,-179.6 686.42,-454.83 l 3.12,-7.27 7.73,-1.66 c 239.62,-51.68 413.56,-267.32 413.56,-512.75 0,-202.21 -117.9,-387.97 -300.68,-474.41"
+ id="path94" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath104">
+ <path
+ d="m 3549.34,2246.6 -62.19,0 c -87.81,0 -171.3,4.24 -250.34,12.59 -23.74,5.79 -47.08,12.04 -69.74,19.01 -13.3,4.1 -26.3,8.41 -39.2,12.89 l -1.92,0.68 c -12.67,4.47 -25.13,9.11 -37.23,13.88 l -1.87,0.74 c -12.34,4.9 -24.42,9.97 -36.99,15.52 -116.98,51.84 -215.06,122.74 -292.07,211.34 -7.01,8.09 -13.8,16.3 -20.4,24.61 l -1.27,1.6 c -6.44,8.15 -12.67,16.4 -18.71,24.74 l -1.44,1.99 c -5.99,8.35 -11.81,16.78 -17.36,25.22 l -1.17,1.8 c -5.69,8.69 -11.2,17.48 -16.94,27.12 -47.66,80.21 -80.73,170.1 -98.31,267.17 l -0.3,1.63 c -1.73,9.67 -3.29,19.39 -4.89,30.48 l -0.24,1.59 c -1.34,9.5 -2.52,19 -3.58,28.53 l -0.38,3.54 c -1,9.47 -1.86,18.96 -2.58,28.51 l -0.25,3.42 c -0.68,9.61 -1.23,19.25 -1.63,28.84 l -0.08,2.66 c -0.4,9.98 -0.65,19.98 -0.73,30.57 -0.65,93.21 11.69,187.94 36.97,282.57 2.61,9.73 5.36,19.4 8.22,29.04 l 0.48,1.61 c 2.86,9.55 5.84,19.05 8.94,28.51 l 0.51,1.54 c 0.69,2.07 1.41,4.17 2.11,6.24 131.82,235.2 366.62,359.44 498.49,391.61 -19.1,-17.91 -37.78,-37.4 -55.88,-58.3 -74,-85.49 -135.6,-192.8 -178.13,-310.32 -3.67,-10.2 -6.95,-19.7 -10.11,-29.23 l -0.5,-1.54 c -3.11,-9.46 -6.09,-18.96 -8.95,-28.51 l -0.48,-1.61 c -2.87,-9.64 -5.61,-19.31 -8.22,-29.04 -25.28,-94.63 -37.62,-189.36 -36.96,-282.57 0.08,-10.59 0.32,-20.59 0.72,-30.57 l 0.09,-2.66 c 0.39,-9.59 0.95,-19.23 1.62,-28.84 l 0.25,-3.42 c 0.72,-9.55 1.59,-19.04 2.59,-28.51 l 0.38,-3.54 c 1.05,-9.53 2.23,-19.03 3.57,-28.53 l 0.24,-1.59 c 1.61,-11.09 3.16,-20.81 4.89,-30.48 l 0.31,-1.63 c 17.56,-97.07 50.65,-186.96 98.31,-267.17 5.74,-9.64 11.25,-18.43 16.93,-27.12 l 1.17,-1.8 c 5.56,-8.44 11.37,-16.87 17.37,-25.22 l 1.43,-1.99 c 6.05,-8.34 12.28,-16.59 18.72,-24.74 l 1.27,-1.6 c 6.59,-8.31 13.39,-16.52 20.4,-24.61 76.99,-88.6 175.08,-159.5 292.06,-211.34 12.56,-5.55 24.66,-10.62 36.99,-15.52 l 1.87,-0.74 c 12.11,-4.77 24.55,-9.41 37.25,-13.88 l 1.91,-0.68 c 12.89,-4.48 25.91,-8.79 39.21,-12.89 40.2,-12.38 82.15,-22.92 125.77,-31.6"
+ id="path106" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath18-8">
+ <path
+ d="M 3044.85,0 C 1363.23,0 0,203.461 0,454.441 0,705.41 1363.23,908.859 3044.85,908.859 4726.47,908.859 6089.69,705.41 6089.69,454.441 6089.69,203.461 4726.47,0 3044.85,0"
+ id="path20-1" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath30-2">
+ <path
+ d="M 0,3832 0,0 l 6089.69,0 0,3832 L 0,3832 Z"
+ id="path32-0" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath80-2">
+ <path
+ d="m 2788.36,2246.6 -256.48,0 c -3.06,0.66 -19.07,4.34 -19.07,4.34 -17.41,4.1 -33.17,8.18 -48.17,12.44 l -6.49,1.93 c -15.5,4.52 -30.45,9.28 -44.44,14.09 l -4.55,1.52 c -13.92,4.85 -28.16,10.26 -43.53,16.52 l -8.06,3.3 c -14.03,5.88 -27.59,11.99 -40.31,18.1 l -6.54,3.26 c -14.56,7.15 -27.3,13.83 -39.59,20.71 -11.57,6.57 -23.65,13.86 -36.94,22.42 l -5.91,3.79 c -11.33,7.43 -22.51,15.21 -33.21,23.16 l -5.56,4.17 c -11.98,9.07 -22.38,17.36 -31.8,25.43 l -1.19,1.03 c -9.72,8.35 -19.3,17.09 -29.29,26.74 l -3.52,3.35 c -8.91,8.76 -17.92,18.14 -26.74,27.89 l -4.06,4.54 c -9.19,10.33 -17.29,19.98 -24.77,29.48 l -1.68,2.18 c -8.07,10.36 -15.78,20.86 -22.89,31.21 l -1.03,1.46 c -6.93,10.11 -13.69,20.71 -21.23,33.28 l -1.86,3.11 c -6.58,11.16 -12.75,22.33 -18.31,33.13 l -1.27,2.53 c -11.68,22.94 -22.2,46.97 -31.59,72.27 l -0.64,1.7 c -4.41,12.01 -8.53,24.3 -12.26,36.52 l -0.6,1.99 c -11.33,37.51 -19.82,76.79 -25.31,117.56 -0.35,2.6 -0.55,5.25 -0.88,7.85 30.2,9.7 62.33,15.04 95.71,15.04 9.99,0 20.46,-0.6 32,-1.82 l 15.43,-1.64 1.44,15.45 c 15.75,169.23 79.48,321.07 167.3,405.86 -19.6,-51.67 -34.76,-105.27 -45.24,-160 -18.26,-95.59 -21.4,-190.06 -9.27,-280.74 5.48,-40.77 13.97,-80.05 25.31,-117.56 l 0.59,-1.99 c 3.73,-12.22 7.86,-24.51 12.27,-36.52 l 0.63,-1.7 c 9.39,-25.3 19.91,-49.33 31.6,-72.27 l 1.26,-2.53 c 5.56,-10.8 11.74,-21.97 18.31,-33.13 l 1.87,-3.11 c 7.53,-12.57 14.3,-23.17 21.22,-33.28 l 1.04,-1.46 c 7.11,-10.35 14.82,-20.85 22.89,-31.21 l 1.67,-2.18 c 7.49,-9.5 15.58,-19.15 24.77,-29.48 l 4.06,-4.54 c 8.82,-9.75 17.83,-19.13 26.75,-27.89 l 3.51,-3.35 c 9.99,-9.65 19.58,-18.39 29.29,-26.74 l 1.19,-1.03 c 9.42,-8.07 19.83,-16.36 31.8,-25.43 l 5.56,-4.17 c 10.71,-7.95 21.89,-15.73 33.21,-23.16 l 5.91,-3.79 c 13.29,-8.56 25.37,-15.85 36.95,-22.42 12.28,-6.88 25.03,-13.56 39.59,-20.71 l 6.53,-3.26 c 12.72,-6.11 26.28,-12.22 40.31,-18.1 l 8.06,-3.3 c 15.38,-6.26 29.61,-11.67 43.53,-16.52 l 4.55,-1.52 c 13.99,-4.81 28.95,-9.57 44.45,-14.09 l 6.47,-1.93 c 15.01,-4.26 30.77,-8.34 48.18,-12.44 0,0 16.02,-3.68 19.07,-4.34"
+ id="path82-9" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath92-4">
+ <path
+ d="m 4078.74,2296.83 c -70.64,7.85 -137.5,18.24 -200.68,31.03 150.52,95.28 244.88,262.64 244.88,443.38 0,245.43 -173.93,461.07 -413.56,512.75 l -7.73,1.66 -3.11,7.27 c -86.59,201.73 -254.36,351.23 -455.56,417.29 11.47,19.88 20.58,32.95 25.61,37.54 299.13,-1.39 568.3,-179.6 686.42,-454.83 l 3.12,-7.27 7.73,-1.66 c 239.62,-51.68 413.56,-267.32 413.56,-512.75 0,-202.21 -117.9,-387.97 -300.68,-474.41"
+ id="path94-6" />
+ </clipPath>
+ <clipPath
+ clipPathUnits="userSpaceOnUse"
+ id="clipPath104-6">
+ <path
+ d="m 3549.34,2246.6 -62.19,0 c -87.81,0 -171.3,4.24 -250.34,12.59 -23.74,5.79 -47.08,12.04 -69.74,19.01 -13.3,4.1 -26.3,8.41 -39.2,12.89 l -1.92,0.68 c -12.67,4.47 -25.13,9.11 -37.23,13.88 l -1.87,0.74 c -12.34,4.9 -24.42,9.97 -36.99,15.52 -116.98,51.84 -215.06,122.74 -292.07,211.34 -7.01,8.09 -13.8,16.3 -20.4,24.61 l -1.27,1.6 c -6.44,8.15 -12.67,16.4 -18.71,24.74 l -1.44,1.99 c -5.99,8.35 -11.81,16.78 -17.36,25.22 l -1.17,1.8 c -5.69,8.69 -11.2,17.48 -16.94,27.12 -47.66,80.21 -80.73,170.1 -98.31,267.17 l -0.3,1.63 c -1.73,9.67 -3.29,19.39 -4.89,30.48 l -0.24,1.59 c -1.34,9.5 -2.52,19 -3.58,28.53 l -0.38,3.54 c -1,9.47 -1.86,18.96 -2.58,28.51 l -0.25,3.42 c -0.68,9.61 -1.23,19.25 -1.63,28.84 l -0.08,2.66 c -0.4,9.98 -0.65,19.98 -0.73,30.57 -0.65,93.21 11.69,187.94 36.97,282.57 2.61,9.73 5.36,19.4 8.22,29.04 l 0.48,1.61 c 2.86,9.55 5.84,19.05 8.94,28.51 l 0.51,1.54 c 0.69,2.07 1.41,4.17 2.11,6.24 131.82,235.2 366.62,359.44 498.49,391.61 -19.1,-17.91 -37.78,-37.4 -55.88,-58.3 -74,-85.49 -135.6,-192.8 -178.13,-310.32 -3.67,-10.2 -6.95,-19.7 -10.11,-29.23 l -0.5,-1.54 c -3.11,-9.46 -6.09,-18.96 -8.95,-28.51 l -0.48,-1.61 c -2.87,-9.64 -5.61,-19.31 -8.22,-29.04 -25.28,-94.63 -37.62,-189.36 -36.96,-282.57 0.08,-10.59 0.32,-20.59 0.72,-30.57 l 0.09,-2.66 c 0.39,-9.59 0.95,-19.23 1.62,-28.84 l 0.25,-3.42 c 0.72,-9.55 1.59,-19.04 2.59,-28.51 l 0.38,-3.54 c 1.05,-9.53 2.23,-19.03 3.57,-28.53 l 0.24,-1.59 c 1.61,-11.09 3.16,-20.81 4.89,-30.48 l 0.31,-1.63 c 17.56,-97.07 50.65,-186.96 98.31,-267.17 5.74,-9.64 11.25,-18.43 16.93,-27.12 l 1.17,-1.8 c 5.56,-8.44 11.37,-16.87 17.37,-25.22 l 1.43,-1.99 c 6.05,-8.34 12.28,-16.59 18.72,-24.74 l 1.27,-1.6 c 6.59,-8.31 13.39,-16.52 20.4,-24.61 76.99,-88.6 175.08,-159.5 292.06,-211.34 12.56,-5.55 24.66,-10.62 36.99,-15.52 l 1.87,-0.74 c 12.11,-4.77 24.55,-9.41 37.25,-13.88 l 1.91,-0.68 c 12.89,-4.48 25.91,-8.79 39.21,-12.89 40.2,-12.38 82.15,-22.92 125.77,-31.6"
+ id="path106-1" />
+ </clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5174"
+ id="linearGradient5075"
+ x1="1.018965"
+ y1="285.02298"
+ x2="7.7508168"
+ y2="285.02298"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5174"
+ id="radialGradient5140"
+ cx="3.5708413"
+ cy="290.94611"
+ fx="3.5708413"
+ fy="290.94611"
+ r="3.5708413"
+ gradientTransform="matrix(0.81002191,0.81002303,-1.7837077,1.7837053,519.6412,-230.90846)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5174"
+ id="radialGradient5202"
+ cx="34.65731"
+ cy="290.9346"
+ fx="34.65731"
+ fy="290.9346"
+ r="3.534668"
+ gradientTransform="matrix(1,0,0,1.0913743,0,-26.583936)"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="33.962344"
+ inkscape:cy="136.63132"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1666"
+ inkscape:window-height="1294"
+ inkscape:window-x="436"
+ inkscape:window-y="107"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#006666;fill-opacity:1;stroke:none;stroke-width:0.26458332;"
+ x="7.7265034"
+ y="294.79858"
+ id="text4105"
+ inkscape:export-xdpi="99.20594"
+ inkscape:export-ydpi="99.20594"><tspan
+ sodipodi:role="line"
+ id="tspan4103"
+ x="7.7265034"
+ y="294.79858"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.26458332;fill:#006666;fill-opacity:1;">pen</tspan></text>
+ <path
+ inkscape:connector-curvature="0"
+ id="path5017"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:10.58333302px;line-height:1.25;font-family:'DejaVu Sans';-inkscape-font-specification:'DejaVu Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:url(#radialGradient5140);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:markers stroke fill"
+ d="m 3.576009,287.79126 c -0.6657944,-7.3e-4 -1.3608126,0.2825 -1.808675,0.84749 -0.4444173,0.565 -0.666626,1.33498 -0.666626,2.30994 0,0.97152 0.2222087,1.73978 0.666626,2.30477 0.4478624,0.56499 1.0507541,0.84749 1.808675,0.84749 0.757921,0 1.3573676,-0.2825 1.7983398,-0.84749 0.4444173,-0.56499 0.666626,-1.33325 0.666626,-2.30477 0,-0.97496 -0.2222087,-1.74494 -0.666626,-2.30994 -0.4409722,-0.56499 -1.1356634,-0.84676 -1.7983398,-0.84749 z m 0,-0.84749 c 1.08176,0 1.946479,0.36346 2.5941569,1.09037 0.6476779,0.72347 0.9715169,1.69498 0.9715169,2.91455 0,1.21612 -0.323839,2.18764 -0.9715169,2.91455 -0.6476779,0.72347 -1.5123969,1.08521 -2.5941569,1.08521 -1.085205,0 -1.953369,-0.36174 -2.60449208,-1.08521 C 0.32383899,293.13977 2.1886081e-8,292.16826 2.1886081e-8,290.94869 2.1886081e-8,289.72912 0.32383899,288.75761 0.97151692,288.03414 1.62264,287.30723 2.490804,286.94377 3.576009,286.94377 Z"
+ sodipodi:nodetypes="acscscscascscscscs"
+ inkscape:export-xdpi="99.20594"
+ inkscape:export-ydpi="99.20594" />
+ <rect
+ style="fill:url(#linearGradient5075);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.1;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0, 1.09999998;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers stroke fill"
+ id="rect5067"
+ width="6.7318516"
+ height="1.3363476"
+ x="1.018965"
+ y="284.3548" />
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:url(#radialGradient5202);fill-opacity:1.0;stroke:none;stroke-width:0.26458332"
+ x="31.039961"
+ y="294.79224"
+ id="text5152"
+ inkscape:export-xdpi="99.20594"
+ inkscape:export-ydpi="99.20594"><tspan
+ sodipodi:role="line"
+ id="tspan5150"
+ x="31.039961"
+ y="294.79224"
+ style="fill:url(#radialGradient5202);fill-opacity:1.0;stroke-width:0.26458332">A</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:10.58333302px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#006666;fill-opacity:1;stroke:none;stroke-width:0.26458332;"
+ x="38.277328"
+ y="294.79953"
+ id="text5156"
+ inkscape:export-xdpi="99.20594"
+ inkscape:export-ydpi="99.20594"><tspan
+ sodipodi:role="line"
+ id="tspan5154"
+ x="38.277328"
+ y="294.79953"
+ style="fill:#006666;fill-opacity:1;stroke-width:0.26458332;">ir</tspan></text>
+ </g>
+</svg>
--- /dev/null
+'Outdoor space reservation system': 'Système de réservation d''espace en plein air'
+'Open Air': 'Air libre'
+Navigation: Navigation
+About: 'À propos'
+Index: Accueil
+Admin: Administration
+Contact: Contact
+'Raphaël Gertz all rights reserved': 'Raphaël Gertz tous droits réservés'
+'Copyright 2018': 'Droit d''auteur 2018'
+Send: Envoyer
+Subject: Sujet
+'Your name': 'Votre nom'
+'Your mail address': 'Votre courriel'
+'Your message has been sent': 'Votre message a bien été envoyé'
+'Your message here': 'Votre message ici'
+'Your password': 'Votre mot de passe'
+Logout: Déconnection
+Register: Enregistrement
+Login: Identification
+Recover: Récupération
+Dashboard: Tableau de bord
+'Hi, %name%': 'Salut, %name%'
+'Subject:': 'Sujet :'
+'Name': 'Nom'
+'Message': 'Message'
+'Title': 'Civilité'
+'Your title': 'Votre civilité'
+'Forename': 'Prénom'
+'Your forename': 'Votre prénom'
+'Surname': 'Nom'
+'Your surname': 'Votre nom'
+'Pseudonym': 'Pseudonyme'
+'Your pseudonym': 'Votre pseudonyme'
+'Mail': 'Courriel'
+'Password': 'Mot de passe'
+'Confirm password': 'Confirmation'
+'Your password confirmation': 'Votre confirmation de mot de passe'
+'Welcome to %title%': 'Bienvenue sur %title%'
+'Thanks so much for joining us, from now on, you can reserve your %title% spaces.': 'Merci de nous avoir rejoint, à partir de maintenant, vous pouvez réserver vos espaces à l''%title%.'
+'Your account has been created': 'Votre compte a bien été créé'
+'Invalid credentials.': 'Identifiants invalides'
+'Thanks so much for joining us, to recover your account you can follow this link: <a href="%url%">%url%</a>': 'Merci de nous avoir rejoint, pour récupérer votre compte vous pouvez suivre ce lien : <a href="%url%">%url%</a>'
+'Your password is updated and an account recover message has been sent': 'Votre mot de passe est modifié et un message de récupération de compte a été envoyé'
+'Unable to find account': 'Impossible de trouver le compte'
+'Account already exists: %mail%': 'Le compte existe déjà : %mail%'
+'Your recover account message has been sent': 'Votre message de récupération de compte a été envoyé'
+'To recover your account click here': 'Pour récupérer votre compte cliquez ici'
+'Recover account on %title%': 'Récupération de compte sur %title%'
+'Account recovered on %title%': 'Compte récupéré sur %title%'
+'Your account password has been changed, to recover your account you can follow this link: <a href="%url%">%url%</a>': 'Votre mot de passe a été changé, pour récupérer votre compte vous pouvez suivre ce lien : <a href="%url%">%url%</a>'
+'Authentication request could not be processed due to a system problem.': 'Authentification impossible suite à un problème système'
+Location: Emplacement
+Your location: Votre emplacement
+Date: Date
+Your date: Votre date
+Slot: Créneau
+Your slot: Votre créneau
+'Application request the %date% for %location% on the slot %slot% saved': 'Réservation le %date% pour %location% sur le créneau %slot% enregistrée'
+#'Application request the %date% for %location% on the slot %slot% already exists': 'Réservation le %date% pour %location% sur le créneau %slot% déjà existante'
+'Application already exists': 'Réservation déjà existante'
--- /dev/null
+'Please provide your name': 'Veuillez fournir votre nom'
+'Please provide your mail': 'Veuillez fournir votre courriel'
+'Please provide a valid mail': 'Veuillez fournir un courriel valide'
+'Please provide your pseudonym': 'Veuillez fournir votre pseudonyme'
+'Please provide your forename': 'Veuillez fournir votre prénom'
+'Please provide your surname': 'Veuillez fournir votre nom'
+'Please provide your password': 'Veuillez fournir votre mot de passe'
+'Please provide your subject': 'Veuillez fournir votre sujet'
+'Please provide your message': 'Veuillez fournir votre message'
+'The password and confirmation must match': 'Le mot de passe doit correspondre à la confirmation'
+'Your mail doesn''t seems to be valid': 'Votre courriel ne semble pas valable'
--- /dev/null
+{% extends '@RapsysAir/base.html.twig' %}
+{% block content %}
+<section id="dashboard">
+ <h2>{% trans %}Dashboard{% endtrans %}</h2>
+ <div class="panel">
+ {% if calendar is defined and calendar %}
+ <table class="grid">
+ <tbody>
+ <tr>
+ {% for date, day in calendar %}
+ <td class="{{ ['cell', 'seventh']|merge(day.class)|join(' ') }}">
+ <h3>{{ day.title }}</h3>
+ {% if day.sessions is not empty %}
+ <ul>
+ {% for session in day.sessions %}
+ <li class="{{ ['session']|merge(session.class)|join(' ') }}">
+ <a href="{{ path('rapsys_air_session', {'id': session.id}) }}" title="{{ session.title }}">{{ session.title }}</a>
+ </li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ </td>
+ {% if loop.index % 7 == 0 and not loop.last %}
+ </tr>
+ <tr>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ </tbody>
+ </table>
+ {% endif %}
+ <div>
+ {{ form_start(form) }}
+
+ <header>{{ form_errors(form) }}</header>
+
+ <section>
+ {{ form_row(form.location) }}
+
+ {{ form_row(form.date) }}
+
+ {{ form_row(form.slot) }}
+ </section>
+
+ {{ form_row(form.submit) }}
+
+ {# Render CSRF token etc .#}
+ <footer style="display:none">
+ {{ form_rest(form) }}
+ </footer>
+
+ {{ form_end(form) }}
+ </div>
+ </div>
+ {# dump(calendar) #}
+</section>
+{% endblock %}
--- /dev/null
+|length > 21 ? session.title|slice(0, 21) ~ '...' : session.title
--- /dev/null
+{% extends '@RapsysAir/base.html.twig' %}
+{% block content %}
+<section id="dashboard">
+ <h2>{{ section }}</h2>
+ <div class="panel">
+ <div class="grid">
+ <dl class="cell">
+ <dt><h3>{% trans %}Location{% endtrans %}</h3></dt>
+ <dd>{{ session.location.getTitle() }}</dd>
+ </dl>
+ <dl class="cell">
+ <dt><h3>{% trans %}Date{% endtrans %}</h3></dt>
+ <dd>{{ session.date.format('Y-m-d') }}</dd>
+ </dl>
+ <dl class="cell">
+ <dt><h3>{% trans %}Slot{% endtrans %}</h3></dt>
+ <dd>{{ session.slot.getTitle() }}</dd>
+ </dl>
+ <dl class="cell">
+ <dt><h3>{% trans %}Application{% endtrans %}</h3></dt>
+ {% if session.application is null %}
+ <dd>{% trans %}None{% endtrans %}</dd>
+ {% else %}
+ <dd>{{ session.application.getTitle() }}</dd>
+ {% endif %}
+ </dl>
+ </div>
+ </div>
+ {{ dump(session) }}
+</section>
+{% endblock %}
--- /dev/null
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8" />
+ <title>{% block title %}{{ title }}{% endblock %}</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ {% block stylesheet %}
+ {% stylesheet '//fonts.googleapis.com/css?family=Irish+Grover' '//fonts.googleapis.com/css?family=La+Belle+Aurore' '@RapsysAirBundle/Resources/public/css/{reset,screen}.css' %}
+ <link href="{{ asset_url }}" type="text/css" rel="stylesheet" />
+ {% endstylesheet %}
+ {% endblock %}
+ <!--{% block javascript %}
+ {% javascript '@RapsysAirBundle/Resources/public/js/*.js' %}
+ <script src="{{ asset_url }}"></script>
+ {% endjavascript %}
+ {% endblock %}-->
+ <link rel="icon" type="image/png" href="{{ asset('bundles/rapsysair/png/favicon.png') }}" sizes="192x192" />
+ <link rel="shortcut icon" type="image/x-icon" href="{{ asset('bundles/rapsysair/ico/favicon.ico') }}" />
+ </head>
+ {% block body %}
+ <body>
+ {% block header %}
+ <header id="header">
+ {% block header_title %}
+ {% block blog_title %}<h1><a href="{{ path('rapsys_air_homepage') }}"><img src="{{ asset('bundles/rapsysair/png/logo.png') }}" alt="{% trans %}Open Air{% endtrans %}" /></a></h1>{% endblock %}
+ {% block header_nav %}
+ <nav>
+ <h2>{% trans %}Navigation{% endtrans %}</h2>
+ <a href="{{ path('rapsys_air_admin') }}">{% trans %}Admin{% endtrans %}</a>
+ <a href="{{ path('rapsys_air_contact') }}">{% trans %}Contact{% endtrans %}</a>
+ {% if is_granted('IS_AUTHENTICATED_REMEMBERED') %}
+ <a href="{{ path('rapsys_user_logout') }}">{% trans %}Logout{% endtrans %}</a>
+ {% else %}
+ <a href="{{ path('rapsys_user_register') }}">{% trans %}Register{% endtrans %}</a>
+ {% endif %}
+ </nav>
+ {% endblock %}
+ {% block blog_subtitle %}{% endblock %}
+ {% block blog_tagline %}
+ {% if tags is defined and tags %}
+ <ul>
+ {% for id, tag in tags %}
+ <li><h2><a href="#">Tag</a></h2></li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {% endblock %}
+ {% endblock %}
+ </header>
+ {% endblock %}
+
+ {# pass an array argument to get the messages of those types (['warning', 'error']) #}
+ {% for label, messages in app.flashes %}
+ {% if messages %}
+ <div class="flash {{label}}">
+ <ul>
+ {% for message in messages %}
+ <li>{{ message }}</li>
+ {% endfor %}
+ </ul>
+ </div>
+ {% endif %}
+ {% endfor %}
+
+ {% block sidebar %}<aside id="sidebar"></aside>{% endblock %}
+
+ {% block content %}<section id="content"></section>{% endblock %}
+
+ {% block footer %}
+ <footer id="footer">
+ <span> </span>
+ <details><summary>{% trans %}Raphaël Gertz all rights reserved{% endtrans %}</summary><span>{% trans %}Copyright 2018{% endtrans %}.</span></details>
+ <span> </span>
+ </footer>
+ {% endblock %}
+ </body>
+ {% endblock %}
+</html>
--- /dev/null
+{% extends '@RapsysAir/base.html.twig' %}
+{% block content %}
+ <section id="form">
+ <h2><a href="{{ path('rapsys_air_contact') }}">{{ section }}</a></h2>
+ {% if sent %}
+ <p>{% trans %}Your message has been sent{% endtrans %}</p>
+ {% else %}
+ <div>
+ {{ form_start(form) }}
+
+ <header>{{ form_errors(form) }}</header>
+
+ <section>
+ {{ form_row(form.subject) }}
+
+ {{ form_row(form.name) }}
+
+ {{ form_row(form.mail) }}
+
+ {{ form_row(form.message) }}
+ </section>
+
+ {{ form_row(form.submit) }}
+
+ {# Render CSRF token etc .#}
+ <footer style="display:none">
+ {{ form_rest(form) }}
+ </footer>
+
+ {{ form_end(form) }}
+ </div>
+ {% endif %}
+ </section>
+{% endblock %}
--- /dev/null
+{# Widgets #}
+
+{%- block form_widget -%}
+ {% if compound %}
+ {{- block('form_widget_compound') -}}
+ {% else %}
+ {{- block('form_widget_simple') -}}
+ {% endif %}
+{%- endblock form_widget -%}
+
+{%- block form_widget_simple -%}
+ {%- set type = type|default('text') -%}
+ <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
+{%- endblock form_widget_simple -%}
+
+{%- block form_widget_compound -%}
+ <div {{ block('widget_container_attributes') }}>
+ {%- if form is rootform -%}
+ {{ form_errors(form) }}
+ {%- endif -%}
+ {{- block('form_rows') -}}
+ {{- form_rest(form) -}}
+ </div>
+{%- endblock form_widget_compound -%}
+
+{%- block collection_widget -%}
+ {% if prototype is defined %}
+ {%- set attr = attr|merge({'data-prototype': form_row(prototype) }) -%}
+ {% endif %}
+ {{- block('form_widget') -}}
+{%- endblock collection_widget -%}
+
+{%- block textarea_widget -%}
+ <textarea {{ block('widget_attributes') }}>{{ value }}</textarea>
+{%- endblock textarea_widget -%}
+
+{%- block choice_widget -%}
+ {% if expanded %}
+ {{- block('choice_widget_expanded') -}}
+ {% else %}
+ {{- block('choice_widget_collapsed') -}}
+ {% endif %}
+{%- endblock choice_widget -%}
+
+{%- block choice_widget_expanded -%}
+ <div {{ block('widget_container_attributes') }}>
+ {%- for child in form %}
+ {{- form_widget(child) -}}
+ {{- form_label(child, null, {translation_domain: choice_translation_domain}) -}}
+ {% endfor -%}
+ </div>
+{%- endblock choice_widget_expanded -%}
+
+{%- block choice_widget_collapsed -%}
+ {%- if required and placeholder is none and not placeholder_in_choices and not multiple and (attr.size is not defined or attr.size <= 1) -%}
+ {% set required = false %}
+ {%- endif -%}
+ <select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
+ {%- if placeholder is not none -%}
+ <option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder != '' ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) }}</option>
+ {%- endif -%}
+ {%- if preferred_choices|length > 0 -%}
+ {% set options = preferred_choices %}
+ {{- block('choice_widget_options') -}}
+ {%- if choices|length > 0 and separator is not none -%}
+ <option disabled="disabled">{{ separator }}</option>
+ {%- endif -%}
+ {%- endif -%}
+ {%- set options = choices -%}
+ {{- block('choice_widget_options') -}}
+ </select>
+{%- endblock choice_widget_collapsed -%}
+
+{%- block choice_widget_options -%}
+ {% for group_label, choice in options %}
+ {%- if choice is iterable -%}
+ <optgroup label="{{ choice_translation_domain is same as(false) ? group_label : group_label|trans({}, choice_translation_domain) }}">
+ {% set options = choice %}
+ {{- block('choice_widget_options') -}}
+ </optgroup>
+ {%- else -%}
+ <option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}</option>
+ {%- endif -%}
+ {% endfor %}
+{%- endblock choice_widget_options -%}
+
+{%- block checkbox_widget -%}
+ <input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
+{%- endblock checkbox_widget -%}
+
+{%- block radio_widget -%}
+ <input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
+{%- endblock radio_widget -%}
+
+{%- block datetime_widget -%}
+ {% if widget == 'single_text' %}
+ {{- block('form_widget_simple') -}}
+ {%- else -%}
+ <div {{ block('widget_container_attributes') }}>
+ {{- form_errors(form.date) -}}
+ {{- form_errors(form.time) -}}
+ {{- form_widget(form.date) -}}
+ {{- form_widget(form.time) -}}
+ </div>
+ {%- endif -%}
+{%- endblock datetime_widget -%}
+
+{%- block date_widget -%}
+ {%- if widget == 'single_text' -%}
+ {{ block('form_widget_simple') }}
+ {%- else -%}
+ <div {{ block('widget_container_attributes') }}>
+ {{- date_pattern|replace({
+ '{{ year }}': form_widget(form.year),
+ '{{ month }}': form_widget(form.month),
+ '{{ day }}': form_widget(form.day),
+ })|raw -}}
+ </div>
+ {%- endif -%}
+{%- endblock date_widget -%}
+
+{%- block time_widget -%}
+ {%- if widget == 'single_text' -%}
+ {{ block('form_widget_simple') }}
+ {%- else -%}
+ {%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%}
+ <div {{ block('widget_container_attributes') }}>
+ {{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %}
+ </div>
+ {%- endif -%}
+{%- endblock time_widget -%}
+
+{%- block dateinterval_widget -%}
+ {%- if widget == 'single_text' -%}
+ {{- block('form_widget_simple') -}}
+ {%- else -%}
+ <div {{ block('widget_container_attributes') }}>
+ {{- form_errors(form) -}}
+ <table class="{{ table_class|default('') }}" role="presentation">
+ <thead>
+ <tr>
+ {%- if with_years %}<th>{{ form_label(form.years) }}</th>{% endif -%}
+ {%- if with_months %}<th>{{ form_label(form.months) }}</th>{% endif -%}
+ {%- if with_weeks %}<th>{{ form_label(form.weeks) }}</th>{% endif -%}
+ {%- if with_days %}<th>{{ form_label(form.days) }}</th>{% endif -%}
+ {%- if with_hours %}<th>{{ form_label(form.hours) }}</th>{% endif -%}
+ {%- if with_minutes %}<th>{{ form_label(form.minutes) }}</th>{% endif -%}
+ {%- if with_seconds %}<th>{{ form_label(form.seconds) }}</th>{% endif -%}
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ {%- if with_years %}<td>{{ form_widget(form.years) }}</td>{% endif -%}
+ {%- if with_months %}<td>{{ form_widget(form.months) }}</td>{% endif -%}
+ {%- if with_weeks %}<td>{{ form_widget(form.weeks) }}</td>{% endif -%}
+ {%- if with_days %}<td>{{ form_widget(form.days) }}</td>{% endif -%}
+ {%- if with_hours %}<td>{{ form_widget(form.hours) }}</td>{% endif -%}
+ {%- if with_minutes %}<td>{{ form_widget(form.minutes) }}</td>{% endif -%}
+ {%- if with_seconds %}<td>{{ form_widget(form.seconds) }}</td>{% endif -%}
+ </tr>
+ </tbody>
+ </table>
+ {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
+ </div>
+ {%- endif -%}
+{%- endblock dateinterval_widget -%}
+
+{%- block number_widget -%}
+ {# type="number" doesn't work with floats #}
+ {%- set type = type|default('text') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock number_widget -%}
+
+{%- block integer_widget -%}
+ {%- set type = type|default('number') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock integer_widget -%}
+
+{%- block money_widget -%}
+ {{ money_pattern|replace({ '{{ widget }}': block('form_widget_simple') })|raw }}
+{%- endblock money_widget -%}
+
+{%- block url_widget -%}
+ {%- set type = type|default('url') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock url_widget -%}
+
+{%- block search_widget -%}
+ {%- set type = type|default('search') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock search_widget -%}
+
+{%- block percent_widget -%}
+ {%- set type = type|default('text') -%}
+ {{ block('form_widget_simple') }} %
+{%- endblock percent_widget -%}
+
+{%- block password_widget -%}
+ {%- set type = type|default('password') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock password_widget -%}
+
+{%- block hidden_widget -%}
+ {%- set type = type|default('hidden') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock hidden_widget -%}
+
+{%- block email_widget -%}
+ {%- set type = type|default('email') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock email_widget -%}
+
+{%- block range_widget -%}
+ {% set type = type|default('range') %}
+ {{- block('form_widget_simple') -}}
+{%- endblock range_widget %}
+
+{%- block button_widget -%}
+ {%- if label is empty -%}
+ {%- if label_format is not empty -%}
+ {% set label = label_format|replace({
+ '%name%': name,
+ '%id%': id,
+ }) %}
+ {%- elseif label is same as(false) -%}
+ {% set translation_domain = false %}
+ {%- else -%}
+ {% set label = name|humanize %}
+ {%- endif -%}
+ {%- endif -%}
+ <button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}</button>
+{%- endblock button_widget -%}
+
+{%- block submit_widget -%}
+ {%- set type = type|default('submit') -%}
+ {{ block('button_widget') }}
+{%- endblock submit_widget -%}
+
+{%- block reset_widget -%}
+ {%- set type = type|default('reset') -%}
+ {{ block('button_widget') }}
+{%- endblock reset_widget -%}
+
+{%- block tel_widget -%}
+ {%- set type = type|default('tel') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock tel_widget -%}
+
+{%- block color_widget -%}
+ {%- set type = type|default('color') -%}
+ {{ block('form_widget_simple') }}
+{%- endblock color_widget -%}
+
+{# Labels #}
+
+{%- block form_label -%}
+ {% if label is not same as(false) -%}
+ {% if not compound -%}
+ {% set label_attr = label_attr|merge({'for': id}) %}
+ {%- endif -%}
+ {% if required -%}
+ {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
+ {%- endif -%}
+ {% if label is empty -%}
+ {%- if label_format is not empty -%}
+ {% set label = label_format|replace({
+ '%name%': name,
+ '%id%': id,
+ }) %}
+ {%- else -%}
+ {% set label = name|humanize %}
+ {%- endif -%}
+ {%- endif -%}
+ <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>
+ {%- if translation_domain is same as(false) -%}
+ {{- label -}}
+ {%- else -%}
+ {{- label|trans({}, translation_domain) -}}
+ {%- endif -%}
+ </{{ element|default('label') }}>
+ {%- endif -%}
+{%- endblock form_label -%}
+
+{%- block button_label -%}{%- endblock -%}
+
+{# Rows #}
+
+{%- block repeated_row -%}
+ {#
+ No need to render the errors here, as all errors are mapped
+ to the first child (see RepeatedTypeValidatorExtension).
+ #}
+ {{- block('form_rows') -}}
+{%- endblock repeated_row -%}
+
+{%- block form_row -%}
+ <div>
+ {{- form_label(form) -}}
+ <section>
+ {{- form_widget(form) -}}
+ {%- if errors|length > 0 -%}
+ <div class="error">
+ {{- form_errors(form) -}}
+ </div>
+ {%- endif -%}
+ </section>
+ </div>
+{%- endblock form_row -%}
+
+{%- block button_row -%}
+ <div>
+ {{- form_widget(form) -}}
+ </div>
+{%- endblock button_row -%}
+
+{%- block hidden_row -%}
+ {{ form_widget(form) }}
+{%- endblock hidden_row -%}
+
+{# Misc #}
+
+{%- block form -%}
+ {{ form_start(form) }}
+ {{- form_widget(form) -}}
+ {{ form_end(form) }}
+{%- endblock form -%}
+
+{%- block form_start -%}
+ {%- do form.setMethodRendered() -%}
+ {% set method = method|upper %}
+ {%- if method in ["GET", "POST"] -%}
+ {% set form_method = method %}
+ {%- else -%}
+ {% set form_method = "POST" %}
+ {%- endif -%}
+ <form name="{{ name }}" method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{% for attrname, attrvalue in attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}{% if multipart %} enctype="multipart/form-data"{% endif %}>
+ {%- if form_method != method -%}
+ <input type="hidden" name="_method" value="{{ method }}" />
+ {%- endif -%}
+{%- endblock form_start -%}
+
+{%- block form_end -%}
+ {%- if not render_rest is defined or render_rest -%}
+ {{ form_rest(form) }}
+ {%- endif -%}
+ </form>
+{%- endblock form_end -%}
+
+{%- block form_errors -%}
+ {%- if errors|length > 0 -%}
+ <ul>
+ {%- for error in errors -%}
+ <li>{{ error.message }}</li>
+ {%- endfor -%}
+ </ul>
+ {%- endif -%}
+{%- endblock form_errors -%}
+
+{%- block form_rest -%}
+ {% for child in form -%}
+ {% if not child.rendered %}
+ {{- form_row(child) -}}
+ {% endif %}
+ {%- endfor -%}
+
+ {% if not form.methodRendered and form is rootform %}
+ {%- do form.setMethodRendered() -%}
+ {% set method = method|upper %}
+ {%- if method in ["GET", "POST"] -%}
+ {% set form_method = method %}
+ {%- else -%}
+ {% set form_method = "POST" %}
+ {%- endif -%}
+
+ {%- if form_method != method -%}
+ <input type="hidden" name="_method" value="{{ method }}" />
+ {%- endif -%}
+ {% endif -%}
+{% endblock form_rest %}
+
+{# Support #}
+
+{%- block form_rows -%}
+ {% for child in form %}
+ {{- form_row(child) -}}
+ {% endfor %}
+{%- endblock form_rows -%}
+
+{%- block widget_attributes -%}
+ id="{{ id }}" name="{{ full_name }}"
+ {%- if disabled %} disabled="disabled"{% endif -%}
+ {%- if required %} required="required"{% endif -%}
+ {{ block('attributes') }}
+{%- endblock widget_attributes -%}
+
+{%- block widget_container_attributes -%}
+ {%- if id is not empty %}id="{{ id }}"{% endif -%}
+ {{ block('attributes') }}
+{%- endblock widget_container_attributes -%}
+
+{%- block button_attributes -%}
+ id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%}
+ {{ block('attributes') }}
+{%- endblock button_attributes -%}
+
+{% block attributes -%}
+ {%- for attrname, attrvalue in attr -%}
+ {{- " " -}}
+ {%- if attrname in ['placeholder', 'title'] -%}
+ {{- attrname }}="{{ translation_domain is same as(false) ? attrvalue : attrvalue|trans({}, translation_domain) }}"
+ {%- elseif attrvalue is same as(true) -%}
+ {{- attrname }}="{{ attrname }}"
+ {%- elseif attrvalue is not same as(false) -%}
+ {{- attrname }}="{{ attrvalue }}"
+ {%- endif -%}
+ {%- endfor -%}
+{%- endblock attributes -%}
--- /dev/null
+{% extends '@RapsysAir/base.html.twig' %}
+{% block content %}
+ <section id="form">
+ <h2><a href="{{ path('rapsys_user_login') }}">{% trans %}Login{% endtrans %}</a></h2>
+ <div>
+ {{ form_start(form) }}
+
+ <header>{{ form_errors(form) }}</header>
+
+ <section>
+ {{ form_row(form.mail) }}
+
+ {{ form_row(form.password) }}
+
+ {% if error %}
+ <div class="error">
+ <ul><li><a href="{{ path('rapsys_user_recover') }}">{% trans %}To recover your account click here{% endtrans %}</a></li></ul>
+ </div>
+ {% endif %}
+ </section>
+
+ {{ form_row(form.submit) }}
+
+ {# Render CSRF token etc .#}
+ <footer style="display:none">
+ {{ form_rest(form) }}
+ </footer>
+
+ {{ form_end(form) }}
+ </div>
+ </section>
+{% endblock %}
--- /dev/null
+{% extends '@RapsysAir/base.html.twig' %}
+{% block content %}
+ <section id="form">
+ <h2><a href="{{ path('rapsys_user_recover') }}">{% trans %}Recover{% endtrans %}</a></h2>
+ {% if sent %}
+ <p>{% trans %}Your recover account message has been sent{% endtrans %}</p>
+ {% else %}
+ <div>
+ {{ form_start(form) }}
+
+ <header>{{ form_errors(form) }}</header>
+
+ <section>
+ {{ form_row(form.mail) }}
+ </section>
+
+ {{ form_row(form.submit) }}
+
+ {# Render CSRF token etc .#}
+ <footer style="display:none">
+ {{ form_rest(form) }}
+ </footer>
+
+ {{ form_end(form) }}
+ </div>
+ {% endif %}
+ </section>
+{% endblock %}
--- /dev/null
+{% extends '@RapsysAir/base.html.twig' %}
+{% block content %}
+ <section id="form">
+ <h2><a href="{{ path('rapsys_user_recover') }}">{% trans %}Recover{% endtrans %}</a></h2>
+ {% if sent %}
+ <p>{% trans %}Your password is updated and an account recover message has been sent{% endtrans %}</p>
+ {% elseif notfound %}
+ <p>{% trans %}Unable to find account{% endtrans %}</p>
+ {% else %}
+ <div>
+ {{ form_start(form) }}
+
+ <header>{{ form_errors(form) }}</header>
+
+ <section>
+ {{ form_row(form.password) }}
+ </section>
+
+ {{ form_row(form.submit) }}
+
+ {# Render CSRF token etc .#}
+ <footer style="display:none">
+ {{ form_rest(form) }}
+ </footer>
+
+ {{ form_end(form) }}
+ </div>
+ {% endif %}
+ </section>
+{% endblock %}
--- /dev/null
+{% extends '@RapsysAir/base.html.twig' %}
+{% block content %}
+ <section id="form">
+ <h2>{{ title|trans }}</h2>
+ {% if sent %}
+ <p>{% trans %}Your account has been created{% endtrans %}</p>
+ {% else %}
+ <div>
+ {{ form_start(form) }}
+
+ <header>{{ form_errors(form) }}</header>
+
+ <section>
+ {{ form_row(form.mail) }}
+
+ {{ form_row(form.password.first) }}
+
+ {{ form_row(form.password.second) }}
+ </section>
+
+ <section>
+ {{ form_row(form.title) }}
+
+ {{ form_row(form.forename) }}
+
+ {{ form_row(form.surname) }}
+
+ {{ form_row(form.pseudonym) }}
+ </section>
+
+ {{ form_row(form.submit) }}
+
+ {# Render CSRF token etc .#}
+ <footer style="display:none">
+ {{ form_rest(form) }}
+ </footer>
+
+ {{ form_end(form) }}
+ </div>
+ {% endif %}
+ </section>
+{% endblock %}
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta name="viewport" content="width=device-width" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>{{ subject }}</title>
+ <style>
+ body {background:white;color:#066}
+ a {text-decoration:none;color:#066}
+ a:hover {text-decoration:underline}
+ table {width: 100%;border-radius: .5rem}
+ table.head {border:.1rem solid #00c3f9;text-align:center}
+ table.body {background:white;border:.1rem solid #00c3f9;margin:.5rem 0}
+ table.footer {border:.1rem solid #00c3f9;text-align:center;font-weight:bold}
+ table.footer summary:after {display:none}
+ table.footer summary::-webkit-details-marker {display:none}
+ </style>
+</head>
+<body>
+ <table class="head">
+ <tr>
+ <td><a href="{{ url }}"><img src="data:image/png;base64, {{ logo|file_get_contents|base64_encode }}" alt="{{ title|trans }}" /></a></td>
+ <td><h1><a href="{{ url }}">{{ title|trans }}</a></h1></td>
+ </tr>
+ </table>
+ <table class="body">
+ <tr>
+ <td> </td>
+ <td>
+ <h2>{% trans %}Hi,{% endtrans %} {{ contact_name }}</h2>
+ <h3>{% trans %}Subject:{% endtrans %} {{ subject }}</h3>
+ <p>{{ message|nl2br }}</p>
+ </td>
+ <td> </td>
+ </tr>
+ </table>
+ <table class="footer">
+ <tr>
+ <td>{% trans %}Raphaël Gertz all rights reserved{% endtrans %} - {% trans %}Copyright 2018{% endtrans %}.</td>
+ </tr>
+ </table>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta name="viewport" content="width=device-width" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>{{ title }}</title>
+ <style>
+ body {background:white;color:#066}
+ a {text-decoration:none;color:#066}
+ a:hover {text-decoration:underline}
+ table {width: 100%;border-radius: .5rem}
+ table.head {border:.1rem solid #00c3f9;text-align:center}
+ table.body {background:white;border:.1rem solid #00c3f9;margin:.5rem 0}
+ table.footer {border:.1rem solid #00c3f9;text-align:center;font-weight:bold}
+ table.footer summary:after {display:none}
+ table.footer summary::-webkit-details-marker {display:none}
+ </style>
+</head>
+<body>
+ <table class="head">
+ <tr>
+ <td><a href="{{ home }}"><img src="data:image/png;base64, {{ logo|file_get_contents|base64_encode }}" alt="{{ title }}" /></a></td>
+ <td><h1><a href="{{ home }}">{{ title }}</a></h1></td>
+ </tr>
+ </table>
+ <table class="body">
+ <tr>
+ <td> </td>
+ <td>
+ <h2>{{ subtitle }}</h2>
+ {% if subject %}
+ <h3>{% trans %}Subject:{% endtrans %} {{ subject }}</h3>
+ {% endif %}
+ {% if raw is defined %}
+ <p>{{ raw|raw }}</p>
+ {% else %}
+ <p>{{ message|nl2br }}</p>
+ {% endif %}
+ </td>
+ <td> </td>
+ </tr>
+ </table>
+ <table class="footer">
+ <tr>
+ <td>{% trans %}Raphaël Gertz all rights reserved{% endtrans %} - {% trans %}Copyright 2018{% endtrans %}.</td>
+ </tr>
+ </table>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <meta name="viewport" content="width=device-width" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>{{ 'Welcome to %title%'|trans({'%title%': title}) }}</title>
+ <style>
+ body {background:white;color:#066}
+ a {text-decoration:none;color:#066}
+ a:hover {text-decoration:underline}
+ table {width: 100%;border-radius: .5rem}
+ table.head {border:.1rem solid #00c3f9;text-align:center}
+ table.body {background:white;border:.1rem solid #00c3f9;margin:.5rem 0}
+ table.footer {border:.1rem solid #00c3f9;text-align:center;font-weight:bold}
+ table.footer summary:after {display:none}
+ table.footer summary::-webkit-details-marker {display:none}
+ </style>
+</head>
+<body>
+ <table class="head">
+ <tr>
+ <td><a href="{{ url }}"><img src="data:image/png;base64, {{ logo|file_get_contents|base64_encode }}" alt="{{ title|trans }}" /></a></td>
+ <td><h1><a href="{{ url }}">{{ title|trans }}</a></h1></td>
+ </tr>
+ </table>
+ <table class="body">
+ <tr>
+ <td> </td>
+ <td>
+ <h2>{% trans %}Hi,{% endtrans %} {{ contact_name }}</h2>
+ <h3>{% trans %}Subject:{% endtrans %} {{ 'Welcome to %title%'|trans({'%title%': title|trans}) }}</h3>
+ <p>{{ 'Thanks so much for joining us, from now you can reserver your %title% spaces.'|trans({'%title%': title|trans}) }}</p>
+ </td>
+ <td> </td>
+ </tr>
+ </table>
+ <table class="footer">
+ <tr>
+ <td>{% trans %}Raphaël Gertz all rights reserved{% endtrans %} - {% trans %}Copyright 2018{% endtrans %}.</td>
+ </tr>
+ </table>
+</body>
+</html>
--- /dev/null
+{% extends '@RapsysAir/base.html.twig' %}
+{% block content %}
+<section id="content">
+ <h2><a href="{{ path('rapsys_air_homepage') }}">{{ section }}</a></h2>
+ <p>{% trans %}Outdoor space reservation system{% endtrans %}</p>
+</section>
+{% endblock %}
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Tests\Controller;
+
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+
+class DefaultControllerTest extends WebTestCase
+{
+ public function testIndex()
+ {
+ $client = static::createClient();
+
+ $crawler = $client->request('GET', '/');
+
+ $this->assertContains('Hello World', $client->getResponse()->getContent());
+ }
+}
--- /dev/null
+<?php
+// src/Rapsys/AirBundle/Twig/Base64Extension.php
+namespace Rapsys\AirBundle\Twig;
+
+class Base64Extension extends \Twig_Extension {
+ public function getFilters() {
+ return array(
+ new \Twig_SimpleFilter('base64_encode', 'base64_encode'),
+ new \Twig_SimpleFilter('base64_decode', 'base64_decode')
+ );
+ }
+}
--- /dev/null
+<?php
+// src/Rapsys/AirBundle/Twig/Bb2htmlExtension.php
+namespace Rapsys\AirBundle\Twig;
+
+class Bb2htmlExtension extends \Twig_Extension {
+ public function getFilters() {
+ return array(
+ new \Twig\TwigFilter(
+ 'bb2html',
+ function($text) {
+ $ctx = bbcode_create(
+ array(
+ '' => array('type' => BBCODE_TYPE_ROOT),
+ 'code' => array(
+ 'type' => BBCODE_TYPE_OPTARG,
+ 'open_tag' => '<pre class="{PARAM}">',
+ 'close_tag' => '</pre>',
+ 'default_arg' => '{CONTENT}'
+ ),
+ 'ul' => array(
+ 'type' => BBCODE_TYPE_NOARG,
+ 'open_tag' => '<ul>',
+ 'close_tag' => '</ul>',
+ 'childs' => 'li'
+ ),
+ 'li' => array(
+ 'type' => BBCODE_TYPE_NOARG,
+ 'open_tag' => '<li>',
+ 'close_tag' => '</li>',
+ 'parent' => 'ul',
+ 'childs' => 'url'
+ ),
+ 'url' => array(
+ 'type' => BBCODE_TYPE_OPTARG,
+ 'open_tag' => '<a href="{PARAM}">',
+ 'close_tag' => '</a>',
+ 'default_arg' => '{CONTENT}',
+ 'parent' => 'p,li'
+ )
+ )
+ );
+ $text = nl2br(bbcode_parse($ctx, htmlspecialchars($text)));
+ if (preg_match_all('#\<pre[^>]*\>(.*?)\</pre\>#s', $text, $matches) && !empty($matches[1])) {
+ foreach($matches[1] as $string) {
+ $text = str_replace($string, str_replace('<br />', '', $string), $text);
+ }
+ }
+ if (preg_match_all('#\<ul[^>]*\>(.*?)\</ul\>#s', $text, $matches) && !empty($matches[1])) {
+ foreach($matches[1] as $string) {
+ $text = str_replace($string, str_replace('<br />', '', $string), $text);
+ }
+ }
+ $text = preg_replace(
+ array('#(<br />(\r?\n?))*<pre#s', '#</pre>(<br />(\r?\n?))*#', '#(<br />(\r?\n?))*<ul#s', '#</ul>(<br />(\r?\n?))*#', '#(<br />(\r?\n?)){2,}#'),
+ array('</p>\2<pre', '</pre>\2<p>', '</p>\2<ul', '</ul>\2<p>', '</p>\2<p>'),
+ $text
+ );
+ return $text;
+ },
+ array('is_safe' => array('html'))
+ )
+ );
+ }
+}
--- /dev/null
+<?php
+// src/Rapsys/AirBundle/Twig/FileGetContentsExtension.php
+namespace Rapsys\AirBundle\Twig;
+
+class FileGetContentsExtension extends \Twig_Extension {
+ public function getFilters() {
+ return array(
+ new \Twig_SimpleFilter('file_get_contents', 'file_get_contents', array(false, null))
+ );
+ }
+}