--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\RequestContext;
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use Rapsys\AirBundle\Entity\Location;
+use Rapsys\AirBundle\Entity\Snippet;
+use Rapsys\AirBundle\Entity\User;
+
+class SnippetController extends DefaultController {
+       /**
+        * Add snippet
+        *
+        * @desc Persist snippet in database
+        *
+        * @param Request $request The request instance
+        *
+        * @return Response The rendered view or redirection
+        *
+        * @throws \RuntimeException When user has not at least guest role
+        */
+       public function add(Request $request) {
+               //Prevent non-guest to access here
+               $this->denyAccessUnlessGranted('ROLE_GUEST', null, $this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Guest')]));
+
+               //Create ApplicationType form
+               $form = $this->createForm('Rapsys\AirBundle\Form\SnippetType', null, [
+                       //Set the action
+                       'action' => $this->generateUrl('rapsys_air_snippet_add'),
+                       //Set the form attribute
+                       'attr' => []
+               ]);
+
+               //Refill the fields in case of invalid form
+               $form->handleRequest($request);
+
+               //Prevent creating snippet for other user unless admin
+               if ($form->get('user')->getData() !== $this->getUser()) {
+                       //Prevent non-admin to access here
+                       $this->denyAccessUnlessGranted('ROLE_ADMIN', null, $this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Admin')]));
+               }
+
+               //Handle invalid form
+               if (!$form->isSubmitted() || !$form->isValid()) {
+                       //Set section
+                       $section = $this->translator->trans('Snippet add');
+
+                       //Set title
+                       $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
+
+                       //Render the view
+                       return $this->render('@RapsysAir/snippet/add.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView()]+$this->context);
+               }
+
+               //Get doctrine
+               $doctrine = $this->getDoctrine();
+
+               //Get manager
+               $manager = $doctrine->getManager();
+
+               //Get snippet
+               $snippet = $form->getData();
+
+               //Set created
+               $snippet->setCreated(new \DateTime('now'));
+
+               //Set updated
+               $snippet->setUpdated(new \DateTime('now'));
+
+               //Queue snippet save
+               $manager->persist($snippet);
+
+               //Flush to get the ids
+               $manager->flush();
+
+               //Add notice
+               $this->addFlash('notice', $this->translator->trans('Snippet in %locale% %location% for %user% created', ['%locale%' => $snippet->getLocale(), '%location%' => $this->translator->trans('at '.$snippet->getLocation()), '%user%' => $snippet->getUser()]));
+
+               //Extract and process referer
+               if ($referer = $request->headers->get('referer')) {
+                       //Create referer request instance
+                       $req = Request::create($referer);
+
+                       //Get referer path
+                       $path = $req->getPathInfo();
+
+                       //Get referer query string
+                       $query = $req->getQueryString();
+
+                       //Remove script name
+                       $path = str_replace($request->getScriptName(), '', $path);
+
+                       //Try with referer path
+                       try {
+                               //Save old context
+                               $oldContext = $this->router->getContext();
+
+                               //Force clean context
+                               //XXX: prevent MethodNotAllowedException because current context method is POST in onevendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php+42
+                               $this->router->setContext(new RequestContext());
+
+                               //Retrieve route matching path
+                               $route = $this->router->match($path);
+
+                               //Reset context
+                               $this->router->setContext($oldContext);
+
+                               //Clear old context
+                               unset($oldContext);
+
+                               //Extract name
+                               $name = $route['_route'];
+
+                               //Remove route and controller from route defaults
+                               unset($route['_route'], $route['_controller']);
+
+                               //Check if snippet view route
+                               if ($name == 'rapsys_air_organizer_view' && !empty($route['id'])) {
+                                       //Replace id
+                                       $route['id'] = $snippet->getUser()->getId();
+                               //Other routes
+                               } else {
+                                       //Set snippet
+                                       $route['snippet'] = $snippet->getId();
+                               }
+
+                               //Generate url
+                               return $this->redirectToRoute($name, $route);
+                       //No route matched
+                       } catch(MethodNotAllowedException|ResourceNotFoundException $e) {
+                               //Unset referer to fallback to default route
+                               unset($referer);
+                       }
+               }
+
+               //Redirect to cleanup the form
+               return $this->redirectToRoute('rapsys_air', ['snippet' => $snippet->getId()]);
+       }
+
+       /**
+        * Edit snippet
+        *
+        * @desc Persist snippet in database
+        *
+        * @param Request $request The request instance
+        *
+        * @return Response The rendered view or redirection
+        *
+        * @throws \RuntimeException When user has not at least guest role
+        */
+       public function edit(Request $request, $id) {
+               //Prevent non-guest to access here
+               $this->denyAccessUnlessGranted('ROLE_GUEST', null, $this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Guest')]));
+
+               //Get doctrine
+               $doctrine = $this->getDoctrine();
+
+               //Get snippet
+               if (empty($snippet = $doctrine->getRepository(Snippet::class)->findOneById($id))) {
+                       throw $this->createNotFoundException($this->translator->trans('Unable to find snippet: %id%', ['%id%' => $id]));
+               }
+
+               //Create ApplicationType form
+               $form = $this->createForm('Rapsys\AirBundle\Form\SnippetType', $snippet, [
+                       //Set the action
+                       'action' => $this->generateUrl('rapsys_air_snippet_edit', ['id' => $id]),
+                       //Set the form attribute
+                       'attr' => []
+               ]);
+
+               //Refill the fields in case of invalid form
+               $form->handleRequest($request);
+
+               //Prevent creating snippet for other user unless admin
+               if ($form->get('user')->getData() !== $this->getUser()) {
+                       //Prevent non-admin to access here
+                       $this->denyAccessUnlessGranted('ROLE_ADMIN', null, $this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Admin')]));
+               }
+
+               //Handle invalid form
+               if (!$form->isSubmitted() || !$form->isValid()) {
+                       //Set section
+                       $section = $this->translator->trans('Snippet %id%', ['%id%' => $id]);
+
+                       //Set title
+                       $title = $this->translator->trans($this->config['site']['title']).' - '.$section;
+
+                       //Render the view
+                       return $this->render('@RapsysAir/snippet/edit.html.twig', ['id' => $id, 'title' => $title, 'section' => $section, 'form' => $form->createView()]+$this->context);
+               }
+
+               //Get manager
+               $manager = $doctrine->getManager();
+
+               //Set updated
+               $snippet->setUpdated(new \DateTime('now'));
+
+               //Queue snippet save
+               $manager->persist($snippet);
+
+               //Flush to get the ids
+               $manager->flush();
+
+               //Add notice
+               $this->addFlash('notice', $this->translator->trans('Snippet %id% in %locale% %location% for %user% updated', ['%id%' => $id, '%locale%' => $snippet->getLocale(), '%location%' => $this->translator->trans('at '.$snippet->getLocation()), '%user%' => $snippet->getUser()]));
+
+               //Extract and process referer
+               if ($referer = $request->headers->get('referer')) {
+                       //Create referer request instance
+                       $req = Request::create($referer);
+
+                       //Get referer path
+                       $path = $req->getPathInfo();
+
+                       //Get referer query string
+                       $query = $req->getQueryString();
+
+                       //Remove script name
+                       $path = str_replace($request->getScriptName(), '', $path);
+
+                       //Try with referer path
+                       try {
+                               //Save old context
+                               $oldContext = $this->router->getContext();
+
+                               //Force clean context
+                               //XXX: prevent MethodNotAllowedException because current context method is POST in onevendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php+42
+                               $this->router->setContext(new RequestContext());
+
+                               //Retrieve route matching path
+                               $route = $this->router->match($path);
+
+                               //Reset context
+                               $this->router->setContext($oldContext);
+
+                               //Clear old context
+                               unset($oldContext);
+
+                               //Extract name
+                               $name = $route['_route'];
+
+                               //Remove route and controller from route defaults
+                               unset($route['_route'], $route['_controller']);
+
+                               //Check if snippet view route
+                               if ($name == 'rapsys_air_organizer_view' && !empty($route['id'])) {
+                                       //Replace id
+                                       $route['id'] = $snippet->getUser()->getId();
+                               //Other routes
+                               } else {
+                                       //Set snippet
+                                       $route['snippet'] = $snippet->getId();
+                               }
+
+                               //Generate url
+                               return $this->redirectToRoute($name, $route);
+                       //No route matched
+                       } catch(MethodNotAllowedException|ResourceNotFoundException $e) {
+                               //Unset referer to fallback to default route
+                               unset($referer);
+                       }
+               }
+
+               //Redirect to cleanup the form
+               return $this->redirectToRoute('rapsys_air', ['snippet' => $snippet->getId()]);
+       }
+}
 
--- /dev/null
+<?php
+
+namespace Rapsys\AirBundle\Entity;
+
+use Rapsys\AirBundle\Entity\Location;
+use Rapsys\AirBundle\Entity\User;
+
+/**
+ * Snippet
+ */
+class Snippet {
+       /**
+        * @var integer
+        */
+       private $id;
+
+       /**
+        * @var string
+        */
+       protected $locale;
+
+       /**
+        * @var text
+        */
+       protected $description;
+
+       /**
+        * @var \DateTime
+        */
+       protected $created;
+
+       /**
+        * @var \DateTime
+        */
+       protected $updated;
+
+       /**
+        * @var \Rapsys\UserBundle\Entity\Location
+        */
+       protected $location;
+
+       /**
+        * @var \Rapsys\UserBundle\Entity\User
+        */
+       protected $user;
+
+       /**
+        * Get id
+        *
+        * @return integer
+        */
+       public function getId() {
+               return $this->id;
+       }
+
+       /**
+        * Set locale
+        *
+        * @param string $locale
+        *
+        * @return Snippet
+        */
+       public function setLocale($locale) {
+               $this->locale = $locale;
+
+               return $this;
+       }
+
+       /**
+        * Get locale
+        *
+        * @return string
+        */
+       public function getLocale() {
+               return $this->locale;
+       }
+
+       /**
+        * Set description
+        *
+        * @param string $description
+        *
+        * @return Snippet
+        */
+       public function setDescription($description) {
+               $this->description = $description;
+
+               return $this;
+       }
+
+       /**
+        * Get description
+        *
+        * @return string
+        */
+       public function getDescription() {
+               return $this->description;
+       }
+
+       /**
+        * Set created
+        *
+        * @param \DateTime $created
+        *
+        * @return User
+        */
+       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 User
+        */
+       public function setUpdated($updated) {
+               $this->updated = $updated;
+
+               return $this;
+       }
+
+       /**
+        * Get updated
+        *
+        * @return \DateTime
+        */
+       public function getUpdated() {
+               return $this->updated;
+       }
+
+       /**
+        * Set location
+        */
+       public function setLocation(Location $location) {
+               $this->location = $location;
+
+               return $this;
+       }
+
+       /**
+        * Get location
+        */
+       public function getLocation() {
+               return $this->location;
+       }
+
+       /**
+        * Set user
+        */
+       public function setUser(User $user) {
+               $this->user = $user;
+
+               return $this;
+       }
+
+       /**
+        * Get 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\HiddenType;
+use Symfony\Component\Form\Extension\Core\Type\TextType;
+use Symfony\Component\Form\Extension\Core\Type\TextareaType;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
+use Symfony\Component\Validator\Constraints\NotBlank;
+use Rapsys\AirBundle\Form\Extension\Type\HiddenEntityType;
+use Rapsys\AirBundle\Entity\Location;
+use Rapsys\AirBundle\Entity\User;
+use Rapsys\AirBundle\Entity\Snippet;
+
+class SnippetType extends AbstractType {
+       /**
+        * {@inheritdoc}
+        */
+       public function buildForm(FormBuilderInterface $builder, array $options) {
+               return $builder
+                       ->add('locale', HiddenType::class, ['required' => true])
+                       ->add('location', HiddenEntityType::class, ['required' => true])
+                       ->add('user', HiddenEntityType::class, ['required' => true])
+                       ->add('description', TextareaType::class, ['attr' => ['placeholder' => 'Your description', 'cols' => 50, 'rows' => 15], 'constraints' => [new NotBlank(['message' => 'Please provide your description'])], 'required' => true])
+                       ->add('submit', SubmitType::class, ['label' => 'Send', 'attr' => ['class' => 'submit']]);
+                       #->add('delete', SubmitType::class, ['label' => 'Remove', 'attr' => ['class' => 'submit']]);
+       }
+
+       /**
+        * {@inheritdoc}
+        */
+       public function configureOptions(OptionsResolver $resolver) {
+               $resolver->setDefaults(['data_class' => Snippet::class, 'error_bubbling' => true, 'location' => null, 'user' => null]);
+               $resolver->setAllowedTypes('location', [Location::class, 'null']);
+               $resolver->setAllowedTypes('user', [User::class, 'null']);
+       }
+
+       /**
+        * {@inheritdoc}
+        */
+       public function getName() {
+               return 'snippet_form';
+       }
+}