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);