1 <?php
declare(strict_types
=1);
4 * This file is part of the Rapsys AirBundle package.
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Rapsys\AirBundle\Controller
;
14 use Symfony\Component\Asset\Packages
;
15 use Symfony\Component\Filesystem\Exception\IOExceptionInterface
;
16 use Symfony\Component\Filesystem\Filesystem
;
17 use Symfony\Component\HttpFoundation\BinaryFileResponse
;
18 use Symfony\Component\HttpFoundation\Request
;
19 use Symfony\Component\HttpFoundation\Response
;
20 use Symfony\Component\Routing\Exception\MethodNotAllowedException
;
21 use Symfony\Component\Routing\Exception\ResourceNotFoundException
;
22 use Symfony\Component\Routing\Generator\UrlGeneratorInterface
;
23 use Symfony\Component\Routing\RequestContext
;
25 use Rapsys\AirBundle\Entity\Application
;
26 use Rapsys\AirBundle\Entity\Dance
;
27 use Rapsys\AirBundle\Entity\User
;
28 use Rapsys\AirBundle\Entity\Slot
;
29 use Rapsys\AirBundle\Entity\Session
;
30 use Rapsys\AirBundle\Entity\Location
;
32 class SessionController
extends AbstractController
{
36 * @desc Display all sessions with an application or login form
38 * @param Request $request The request instance
40 * @return Response The rendered view
42 public function index(Request
$request): Response
{
44 $this->context
['locations'] = $this->doctrine
->getRepository(Location
::class)->findAllAsArray($this->period
);
47 $this->context
['cities'] = $this->doctrine
->getRepository(Location
::class)->findCitiesAsArray($this->period
);
50 $this->context
['calendar'] = $this->doctrine
->getRepository(Session
::class)->findAllByPeriodAsCalendarArray($this->period
, !$this->checker
->isGranted('IS_AUTHENTICATED_REMEMBERED'), null, null, 1);
53 $this->context
['dances'] = $this->doctrine
->getRepository(Dance
::class)->findNamesAsArray();
56 $this->modified
= max(array_map(function ($v) { return $v
['modified']; }, array_merge($this->context
['calendar'], $this->context
['cities'], $this->context
['dances'])));
59 $response = new Response();
62 if ($this->checker
->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
64 $response->setLastModified(new \
DateTime('-1 year'));
67 $response->setPrivate();
71 //XXX: only for public to force revalidation by last modified
72 $response->setEtag(md5(serialize(array_merge($this->context
['calendar'], $this->context
['cities'], $this->context
['dances']))));
75 $response->setLastModified($this->modified
);
78 $response->setPublic();
80 //Without role and modification
81 if ($response->isNotModified($request)) {
88 if (!empty($this->context
['cities'])) {
92 //Iterate on each cities
93 foreach($this->context
['cities'] as $city) {
94 //Iterate on each locations
95 foreach($city['locations'] as $location) {
97 $locations[$location['id']] = $location;
102 $this->context
['multimap'] = $this->map
->getMultiMap($this->translator
->trans('Libre Air cities sector map'), $this->modified
->getTimestamp(), $locations);
105 $cities = array_map(function ($v) { return $v
['in']; }, $this->context
['cities']);
108 $dances = array_map(function ($v) { return $v
['name']; }, $this->context
['dances']);
118 //TODO: use splice instead of that shit !!!
119 //TODO: handle smartly indoor and outdoor !!!
120 $this->context
['keywords'] = array_values(
125 $this->translator
->trans('indoor'),
126 $this->translator
->trans('outdoor'),
127 $this->translator
->trans('sessions'),
128 $this->translator
->trans('session list'),
129 $this->translator
->trans('listing'),
130 $this->translator
->trans('Libre Air')
136 $cities = implode($this->translator
->trans(' and '), array_filter(array_merge([implode(', ', array_slice($cities, 0, -1))], array_slice($cities, -1)), 'strlen'));
139 $dances = implode($this->translator
->trans(' and '), array_filter(array_merge([implode(', ', array_slice($dances, 0, -1))], array_slice($dances, -1)), 'strlen'));
142 $this->context
['title']['page'] = $this->translator
->trans('%dances% %cities% sessions', ['%dances%' => $dances, '%cities%' => $cities]);
145 $this->context
['description'] = $this->translator
->trans('%dances% indoor and outdoor session calendar %cities%', ['%dances%' => $dances, '%cities%' => $cities]);
148 return $this->render('@RapsysAir/session/index.html.twig', $this->context
);
152 * List all sessions for tango argentin
154 * @desc Display all sessions in tango argentin json format
156 * @todo Drop it if unused by tangoargentin ???
158 * @param Request $request The request instance
160 * @return Response The rendered view or redirection
162 public function tangoargentin(Request
$request): Response
{
163 //Retrieve events to update
164 $sessions = $this->doctrine
->getRepository(Session
::class)->findAllByPeriodAsCalendarArray($this->period
);
169 //Flatten sessions tree
170 $sessions = array_reduce($sessions, function ($c, $v) { return array_merge($c
, $v
['sessions']); }, []);
172 //Iterate on sessions
173 foreach($sessions as $sessionId => $session) {
175 $routeParams = $this->router
->match($session['link']);
178 $route = $routeParams['_route'];
180 //Drop _route from route params
181 unset($routeParams['_route']);
184 $ret[$session['id']] = [
185 'start' => $session['start']->format(\DateTime
::ISO8601
),
186 'stop' => $session['start']->format(\DateTime
::ISO8601
),
187 'fromto' => $this->translator
->trans('from %start% to %stop%', ['%start%' => $session['start']->format('H\hi'), '%stop%' => $session['stop']->format('H\hi')]),
188 'title' => $this->slugger
->latin($session['application']['user']['title'])/*.' '.$this->translator->trans('at '.$session['location']['title'])*/,
189 'short' => $session['rate']['short'],
190 'rate' => $session['rate']['title'],
191 'location' => implode(' ', [$session['location']['address'], $session['location']['zipcode'], $session['location']['city']]),
192 'status' => in_array('canceled', $session['class'])?'annulé':'confirmé',
193 'modified' => $session['modified']->format(\DateTime
::ISO8601
),
194 #'organizer' => $session['application']['user']['title'],
195 #'source' => $this->router->generate('rapsys_air_session_view', ['id' => $sessionId, 'location' => $this->translator->trans($session['l_title'])], UrlGeneratorInterface::ABSOLUTE_URL)
196 'source' => $this->router
->generate($route, $routeParams, UrlGeneratorInterface
::ABSOLUTE_URL
)
201 $response = new Response(json_encode($ret));
204 $response->headers
->set('Content-Type', 'application/json');
213 * @todo XXX: TODO: add <link rel="prev|next" for sessions or classes ? />
214 * @todo XXX: TODO: like described in: https://www.alsacreations.com/article/lire/1400-attribut-rel-relations.html#xnf-rel-attribute
215 * @todo XXX: TODO: or here: http://microformats.org/wiki/existing-rel-values#HTML5_link_type_extensions
217 * @todo: generate a background from @RapsysAir/Resources/public/location/<location>.png or @RapsysAir/Resources/public/location/<user>/<location>.png when available
219 * @todo: generate a share picture @RapsysAir/seance/363/place-saint-sulpice/bal-et-cours-de-tango-argentin/milonga-raphael/share.jpeg ?
220 * (with date, organiser, type, location, times and logo ?)
222 * @todo: add picture stuff about location ???
224 * @param Request $request The request instance
225 * @param int $id The session id
227 * @return Response The rendered view
229 * @throws NotFoundHttpException When session is not found
231 public function view(Request
$request, int $id): Response
{
233 if (empty($this->context
['session'] = $this->doctrine
->getRepository(Session
::class)->findOneByIdAsArray($id))) {
235 throw $this->createNotFoundException($this->translator
->trans('Unable to find session: %id%', ['%id%' => $id]));
238 //Get locations at less than 1 km
239 $this->context
['locations'] = $this->doctrine
->getRepository(Location
::class)->findAllByLatitudeLongitudeAsArray($this->context
['session']['location']['latitude'], $this->context
['session']['location']['longitude'], $this->period
, 2);
242 //XXX: dance modified is already computed inside calendar modified
243 $this->modified
= max(array_merge([$this->context
['session']['modified']], array_map(function ($v) { return $v
['modified']; }, $this->context
['locations'])));
246 $response = new Response();
249 if ($this->checker
->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
251 $response->setLastModified(new \
DateTime('-1 year'));
254 $response->setPrivate();
255 //Without logged user
258 //XXX: only for public to force revalidation by last modified
259 $response->setEtag(md5(serialize(array_merge($this->context
['session'], $this->context
['locations']))));
262 $response->setLastModified($this->modified
);
265 $response->setPublic();
267 //Without role and modification
268 if ($response->isNotModified($request)) {
269 //Return 304 response
275 $route = $request->attributes
->get('_route');
278 $routeParams = $request->attributes
->get('_route_params');
283 //Without location or invalid location
284 if (empty($routeParams['location']) || $this->context
['session']['location']['slug'] !== $routeParams['location']) {
286 $routeParams['location'] = $this->context
['session']['location']['slug'];
292 //With dance slug without dance or invalid dance
293 if (!empty($this->context
['session']['application']['dance']['slug']) && (empty($routeParams['dance']) || $this->context
['session']['application']['dance']['slug'] !== $routeParams['dance'])) {
295 $routeParams['dance'] = $this->context
['session']['application']['dance']['slug'];
299 //Without dance slug with dance
300 } elseif (empty($this->context
['session']['application']['dance']['slug']) && !empty($routeParams['dance'])) {
302 unset($routeParams['dance']);
308 //With user slug without user or invalid user
309 if (!empty($this->context
['session']['application']['user']['slug']) && (empty($routeParams['user']) || $this->context
['session']['application']['user']['slug'] !== $routeParams['user'])) {
311 $routeParams['user'] = $this->context
['session']['application']['user']['slug'];
315 //Without user slug with user
316 } elseif (empty($this->context
['session']['application']['user']['slug']) && !empty($routeParams['user'])) {
318 unset($routeParams['user']);
327 return $this->redirectToRoute($route, $routeParams, $this->context
['session']['stop'] <= new \
DateTime('now') ? Response
::HTTP_MOVED_PERMANENTLY
: Response
::HTTP_FOUND
);
331 $this->context
['map'] = $this->map
->getMap($this->context
['session']['location']['map'], $this->modified
->getTimestamp(), $this->context
['session']['location']['latitude'], $this->context
['session']['location']['longitude']);
334 $this->context
['multimap'] = $this->map
->getMultiMap($this->context
['session']['location']['multimap'], $this->modified
->getTimestamp(), $this->context
['locations']);
337 $this->context
['canonical'] = $this->context
['session']['canonical'];
340 $this->context
['alternates'] = $this->context
['session']['alternates'];
342 //Set localization date formater
343 $intlDate = new \
IntlDateFormatter($this->locale
, \IntlDateFormatter
::TRADITIONAL
, \IntlDateFormatter
::NONE
);
345 //Set localization time formater
346 $intlTime = new \
IntlDateFormatter($this->locale
, \IntlDateFormatter
::NONE
, \IntlDateFormatter
::SHORT
);
349 if (!empty($this->context
['session']['application'])) {
351 $this->context
['title']['page'] = $this->translator
->trans('%dance% %id% by %pseudonym%', ['%id%' => $id, '%dance%' => $this->context
['session']['application']['dance']['title'], '%pseudonym%' => $this->context
['session']['application']['user']['title']]);
354 $this->context
['description'] = ucfirst($this->translator
->trans('%dance% %location% %city% %slot% on %date% at %time%', [
355 '%dance%' => $this->context
['session']['application']['dance']['title'],
356 '%location%' => $this->context
['session']['location']['at'],
357 '%city%' => $this->context
['session']['location']['in'],
358 '%slot%' => $this->context
['session']['slot']['the'],
359 '%date%' => $intlDate->format($this->context
['session']['start']),
360 '%time%' => $intlTime->format($this->context
['session']['start']),
364 //TODO: readd outdoor ???
365 $this->context
['keywords'] = [
366 $this->context
['session']['application']['dance']['type'],
367 $this->context
['session']['application']['dance']['name'],
368 $this->context
['session']['location']['title'],
369 $this->context
['session']['application']['user']['title'],
370 $this->translator
->trans($this->context
['session']['location']['indoor']?'indoor':'outdoor')
372 //Without application
375 $this->context
['title']['page'] = $this->translator
->trans('Session %id%', ['%id%' => $id]);
378 $this->context
['description'] = ucfirst($this->translator
->trans('%location% %city% %slot% on %date% at %time%', [
379 '%city%' => ucfirst($this->context
['session']['location']['in']),
380 '%location%' => $this->context
['session']['location']['at'],
381 '%slot%' => $this->context
['session']['slot']['the'],
382 '%date%' => $intlDate->format($this->context
['session']['start']),
383 '%time%' => $intlTime->format($this->context
['session']['start'])
387 //TODO: readd outdoor ???
388 $this->context
['keywords'] = [
389 $this->context
['session']['location']['title'],
390 $this->translator
->trans($this->context
['session']['location']['indoor']?'indoor':'outdoor')
395 $this->context
['section'] = $this->context
['session']['location']['title'];
398 $this->context
['facebook']['og:title'] = $this->context
['title']['page'].' '.$this->context
['session']['location']['at'];
401 $this->context
['fbimage'] = [
403 $this->context
['session']['application']['user']['title']??$this->context
['title']['page'] => [
404 'font' => 'irishgrover',
407 ucfirst($intlDate->format($this->context
['session']['start']))."\n".$this->translator
->trans('Around %start% until %stop%', ['%start%' => $intlTime->format($this->context
['session']['start']), '%stop%' => $intlTime->format($this->context
['session']['stop'])]) => [
408 'font' => 'irishgrover',
411 $this->context
['session']['location']['at'] => [
413 'font' => 'labelleaurore',
417 'updated' => $this->context
['session']['updated']->format('U')
418 ]+
$this->context
['facebook'];
420 //Create application form for role_guest
421 if ($this->checker
->isGranted('ROLE_GUEST')) {
423 $now = new \
DateTime('now');
425 //Default favorites and dances
426 $danceFavorites = $dances = [];
428 $danceDefault = null;
431 if ($this->checker
->isGranted('ROLE_ADMIN')) {
432 //Get favorites dances
433 $danceFavorites = $this->doctrine
->getRepository(Dance
::class)->findByUserId($this->security
->getUser()->getId());
436 $dances = $this->doctrine
->getRepository(Dance
::class)->findAllIndexed();
439 $danceDefault = !empty($this->context
['session']['application'])?$dances[$this->context
['session']['application']['dance']['id']]:null;
442 //Create SessionType form
443 //TODO: move to named form ???
444 $sessionForm = $this->factory
->create('Rapsys\AirBundle\Form\SessionType', null, [
446 'action' => $this->generateUrl('rapsys_air_session_view', ['id' => $id, 'location' => $this->context
['session']['location']['slug'], 'dance' => $this->context
['session']['application']['dance']['slug']??null, 'user' => $this->context
['session']['application']['user']['slug']??null]),
447 //Set the form attribute
448 'attr' => [ 'class' => 'col' ],
450 'admin' => $this->checker
->isGranted('ROLE_ADMIN'),
452 'dance_choices' => $dances,
454 'dance_default' => $danceDefault,
455 //Set dance favorites
456 'dance_favorites' => $danceFavorites,
457 //Set to session slot or evening by default
458 //XXX: default to Evening (3)
459 'slot_default' => $this->doctrine
->getRepository(Slot
::class)->findOneById($this->context
['session']['slot']['id']??3),
460 //Set default user to current
461 'user' => $this->security
->getUser()->getId(),
463 'date' => $this->context
['session']['date'],
465 'begin' => $this->context
['session']['begin'],
467 'length' => $this->context
['session']['length'],
469 'raincancel' => ($this->checker
->isGranted('ROLE_ADMIN') || !empty($this->context
['session']['application']['user']['id']) && $this->security
->getUser()->getId() == $this->context
['session']['application']['user']['id']) && $this->context
['session']['rainfall'] >= 2,
471 'cancel' => $this->checker
->isGranted('ROLE_ADMIN') || in_array($this->security
->getUser()->getId(), explode("\n", $this->context
['session']['sau_id'])),
473 'modify' => $this->checker
->isGranted('ROLE_ADMIN') || !empty($this->context
['session']['application']['user']['id']) && $this->security
->getUser()->getId() == $this->context
['session']['application']['user']['id'] && $this->context
['session']['stop'] >= $now && $this->checker
->isGranted('ROLE_REGULAR'),
475 'move' => $this->checker
->isGranted('ROLE_ADMIN') || !empty($this->context
['session']['application']['user']['id']) && $this->security
->getUser()->getId() == $this->context
['session']['application']['user']['id'] && $this->context
['session']['stop'] >= $now && $this->checker
->isGranted('ROLE_SENIOR'),
477 'attribute' => $this->checker
->isGranted('ROLE_ADMIN') && $this->context
['session']['locked'] === null,
479 'session' => $this->context
['session']['id']
482 //Refill the fields in case of invalid form
483 $sessionForm->handleRequest($request);
485 //With submitted form
486 if ($sessionForm->isSubmitted() && $sessionForm->isValid()) {
488 $data = $sessionForm->getData();
491 $sessionObject = $this->doctrine
->getRepository(Session
::class)->findOneById($id);
494 $userObject = $this->security
->getUser();
496 //Replace with requested user for admin
497 if ($this->checker
->isGranted('ROLE_ADMIN') && !empty($data['user'])) {
498 $userObject = $this->doctrine
->getRepository(User
::class)->findOneById($data['user']);
502 $datetime = new \
DateTime('now');
504 //Set canceled time at start minus one day
505 $canceled = (clone $sessionObject->getStart())->sub(new \
DateInterval('P1D'));
509 'raincancel' => $sessionForm->has('raincancel') && $sessionForm->get('raincancel')->isClicked(),
510 'modify' => $sessionForm->has('modify') && $sessionForm->get('modify')->isClicked(),
511 'move' => $sessionForm->has('move') && $sessionForm->get('move')->isClicked(),
512 'cancel' => $sessionForm->has('cancel') && $sessionForm->get('cancel')->isClicked(),
513 'forcecancel' => $sessionForm->has('forcecancel') && $sessionForm->get('forcecancel')->isClicked(),
514 'attribute' => $sessionForm->has('attribute') && $sessionForm->get('attribute')->isClicked(),
515 'autoattribute' => $sessionForm->has('autoattribute') && $sessionForm->get('autoattribute')->isClicked(),
516 'lock' => $sessionForm->has('lock') && $sessionForm->get('lock')->isClicked(),
519 //With raincancel and application and (rainfall or admin)
520 if ($action['raincancel'] && ($application = $sessionObject->getApplication()) && ($sessionObject->getRainfall() >= 2 || $this->checker
->isGranted('ROLE_ADMIN'))) {
521 //Cancel application at start minus one day
522 $application->setCanceled($canceled);
525 $application->setUpdated($datetime);
527 //Insufficient rainfall
529 if ($sessionObject->getRainfall() < 2) {
531 //XXX: magic cheat score 42
532 $application->setScore(42);
535 //Queue application save
536 $this->manager
->persist($application);
538 //Add notice in flash message
539 $this->addFlash('notice', $this->translator
->trans('Application %id% updated', ['%id%' => $application->getId()]));
542 $sessionObject->setUpdated($datetime);
545 $this->manager
->persist($sessionObject);
547 //Add notice in flash message
548 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
550 } elseif ($action['modify']) {
552 if ($this->checker
->isGranted('ROLE_ADMIN')) {
554 $application = $this->doctrine
->getRepository(Application
::class)->findOneBySessionUser($sessionObject, $userObject);
557 $application->setDance($data['dance']);
560 $this->manager
->persist($application);
563 $sessionObject->setSlot($data['slot']);
566 $sessionObject->setDate($data['date']);
570 $sessionObject->setBegin($data['begin']);
573 $sessionObject->setLength($data['length']);
576 $sessionObject->setUpdated($datetime);
579 $this->manager
->persist($sessionObject);
581 //Add notice in flash message
582 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
584 } elseif ($action['move']) {
586 $sessionObject->setLocation($this->doctrine
->getRepository(Location
::class)->findOneById($data['location']));
589 $sessionObject->setUpdated($datetime);
592 $this->manager
->persist($sessionObject);
594 //Add notice in flash message
595 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
596 //With cancel or forcecancel
597 } elseif ($action['cancel'] || $action['forcecancel']) {
599 $application = $this->doctrine
->getRepository(Application
::class)->findOneBySessionUser($sessionObject, $userObject);
601 //Not already canceled
602 if ($application->getCanceled() === null) {
604 $application->setCanceled($datetime);
606 //Check if application is session application and (canceled 24h before start or forcecancel (as admin))
607 #if ($sessionObject->getApplication() == $application && ($datetime < $canceled || $action['forcecancel'])) {
608 if ($sessionObject->getApplication() == $application && $action['forcecancel']) {
610 //XXX: magic cheat score 42
611 $application->setScore(42);
613 //Unattribute session
614 $sessionObject->setApplication(null);
617 $sessionObject->setUpdated($datetime);
620 $this->manager
->persist($sessionObject);
622 //Add notice in flash message
623 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
627 //Uncancel application
628 $application->setCanceled(null);
632 $application->setUpdated($datetime);
634 //Queue application save
635 $this->manager
->persist($application);
637 //Add notice in flash message
638 $this->addFlash('notice', $this->translator
->trans('Application %id% updated', ['%id%' => $application->getId()]));
640 } elseif ($action['attribute']) {
642 $application = $this->doctrine
->getRepository(Application
::class)->findOneBySessionUser($sessionObject, $userObject);
645 if ($application->getCanceled() !== null) {
646 //Uncancel application
647 $application->setCanceled(null);
651 //XXX: magic cheat score 42
652 $application->setScore(42);
655 $application->setUpdated($datetime);
657 //Queue application save
658 $this->manager
->persist($application);
660 //Add notice in flash message
661 $this->addFlash('notice', $this->translator
->trans('Application %id% updated', ['%id%' => $application->getId()]));
663 //Unattribute session
664 $sessionObject->setApplication($application);
667 $sessionObject->setUpdated($datetime);
670 $this->manager
->persist($sessionObject);
672 //Add notice in flash message
673 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
675 } elseif ($action['autoattribute']) {
676 //Get best application
677 //XXX: best application may not issue result while grace time or bad behaviour
678 if (!empty($application = $this->doctrine
->getRepository(Session
::class)->findBestApplicationById($id))) {
680 $sessionObject->setApplication($application);
683 $sessionObject->setUpdated($datetime);
686 $this->manager
->persist($sessionObject);
688 //Add notice in flash message
689 $this->addFlash('notice', $this->translator
->trans('Session %id% auto attributed', ['%id%' => $id]));
692 //Add warning in flash message
693 $this->addFlash('warning', $this->translator
->trans('Session %id% not auto attributed', ['%id%' => $id]));
696 } elseif ($action['lock']) {
698 if ($sessionObject->getLocked() !== null) {
703 $sessionObject->setLocked(null);
707 if ($application = $sessionObject->getApplication()) {
709 //XXX: magic cheat score 42
710 $application->setScore(42);
713 $application->setUpdated($datetime);
715 //Queue application save
716 $this->manager
->persist($application);
718 //Add notice in flash message
719 $this->addFlash('notice', $this->translator
->trans('Application %id% updated', ['%id%' => $application->getId()]));
722 //Unattribute session
723 $sessionObject->setApplication(null);
726 $sessionObject->setLocked($datetime);
730 $sessionObject->setUpdated($datetime);
733 $this->manager
->persist($sessionObject);
735 //Add notice in flash message
736 $this->addFlash('notice', $this->translator
->trans('Session %id% updated', ['%id%' => $id]));
739 //Add warning in flash message
740 $this->addFlash('warning', $this->translator
->trans('Session %id% not updated', ['%id%' => $id]));
743 //Flush to get the ids
744 $this->manager
->flush();
746 //Redirect to cleanup the form
747 return $this->redirectToRoute('rapsys_air_session_view', ['id' => $id, 'location' => $this->context
['session']['location']['slug'], 'dance' => $this->context
['session']['application']['dance']['slug']??null, 'user' => $this->context
['session']['application']['user']['slug']??null]);
750 //Add form to context
751 $this->context
['forms']['session'] = $sessionForm->createView();
755 return $this->render('@RapsysAir/session/view.html.twig', $this->context
, $response);