From 11f4f833ffd015afd0b06e4d5f542a1f81b0a1c9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rapha=C3=ABl=20Gertz?= Date: Tue, 4 Oct 2022 07:09:52 +0200 Subject: [PATCH 1/1] Php strict Drop edit and add functions Replace location edit and add redirecting forms with named forms Handle form on location index Add cities index Add city view Use member doctrine and manager New index layout Cleanup --- Controller/LocationController.php | 672 +++++++++++++++++------------- 1 file changed, 390 insertions(+), 282 deletions(-) diff --git a/Controller/LocationController.php b/Controller/LocationController.php index ce73558..3631826 100644 --- a/Controller/LocationController.php +++ b/Controller/LocationController.php @@ -1,260 +1,233 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Rapsys\AirBundle\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Rapsys\AirBundle\Entity\Slot; -use Rapsys\AirBundle\Entity\Session; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RequestContext; + +use Rapsys\AirBundle\Entity\Dance; use Rapsys\AirBundle\Entity\Location; +use Rapsys\AirBundle\Entity\Session; +use Rapsys\AirBundle\Entity\Slot; +/** + * {@inheritdoc} + */ class LocationController extends DefaultController { /** - * Add location - * - * @desc Persist location in database + * List all cities * * @param Request $request The request instance - * - * @return Response The rendered view or redirection - * - * @throws \RuntimeException When user has not at least admin role + * @return Response The rendered view */ - public function add(Request $request) { - //Prevent non-guest to access here - $this->denyAccessUnlessGranted('ROLE_ADMIN', null, $this->translator->trans('Unable to access this page without role %role%!', ['%role%' => $this->translator->trans('Admin')])); - - //Create LocationType form - $form = $this->createForm('Rapsys\AirBundle\Form\LocationType', null, [ - //Set the action - 'action' => $this->generateUrl('rapsys_air_location_add'), - //Set the form attribute - 'attr' => [] - ]); - - //Refill the fields in case of invalid form - $form->handleRequest($request); - - //Handle invalid form - if (!$form->isSubmitted() || !$form->isValid()) { - //Set section - $section = $this->translator->trans('Location add'); - - //Set title - $title = $this->translator->trans($this->config['site']['title']).' - '.$section; + public function cities(Request $request): Response { + //Add cities + $this->context['cities'] = $this->doctrine->getRepository(Location::class)->findCitiesAsArray($this->period); - //Render the view - return $this->render('@RapsysAir/location/add.html.twig', ['title' => $title, 'section' => $section, 'form' => $form->createView()]+$this->context); - } - - //Get doctrine - $doctrine = $this->getDoctrine(); - - //Get manager - $manager = $doctrine->getManager(); - - //Get location - $location = $form->getData(); - - //Set created - $location->setCreated(new \DateTime('now')); - - //Set updated - $location->setUpdated(new \DateTime('now')); - - //Queue location save - $manager->persist($location); + //Add dances + $this->context['dances'] = $this->doctrine->getRepository(Dance::class)->findNamesAsArray(); - //Flush to get the ids - $manager->flush(); + //Create response + $response = new Response(); - //Add notice - $this->addFlash('notice', $this->translator->trans('Location %id% created', ['%id%' => $location->getId()])); + //Set modified + $this->modified = max(array_map(function ($v) { return $v['modified']; }, array_merge($this->context['cities'], $this->context['dances']))); - //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()); + //Add city multi + foreach($this->context['cities'] as $id => $city) { + //Add city multi + #$this->osm->getMultiImage($city['link'], $city['osm'], $this->modified->getTimestamp(), $city['latitude'], $city['longitude'], $city['locations'], $this->osm->getMultiZoom($city['latitude'], $city['longitude'], $city['locations'], 16)); + $this->context['cities'][$id]['multimap'] = $this->map->getMultiMap($city['multimap'], $this->modified->getTimestamp(), $city['latitude'], $city['longitude'], $city['locations'], $this->map->getMultiZoom($city['latitude'], $city['longitude'], $city['locations'])); + } - //Retrieve route matching path - $route = $this->router->match($path); + //With logged user + if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) { + //Set last modified + $response->setLastModified(new \DateTime('-1 year')); + + //Set as private + $response->setPrivate(); + //Without logged user + } else { + //Set etag + //XXX: only for public to force revalidation by last modified + $response->setEtag(md5(serialize(array_merge($this->context['cities'], $this->context['dances'])))); + + //Set last modified + $response->setLastModified($this->modified); + + //Set as public + $response->setPublic(); + + //Without role and modification + if ($response->isNotModified($request)) { + //Return 304 response + return $response; + } + } - //Reset context - $this->router->setContext($oldContext); + //Set section + $this->context['title'] = $this->translator->trans('Libre Air cities'); - //Clear old context - unset($oldContext); + //Set description + $this->context['description'] = $this->translator->trans('Libre Air city list'); - //Extract name - $name = $route['_route']; + //Set cities + $cities = array_map(function ($v) { return $v['in']; }, $this->context['cities']); - //Remove route and controller from route defaults - unset($route['_route'], $route['_controller']); + //Set dances + $dances = array_map(function ($v) { return $v['name']; }, $this->context['dances']); - //Check if location view route - if ($name == 'rapsys_air_location_view' && !empty($route['id'])) { - //Replace id - $route['id'] = $location->getId(); - //Other routes - } else { - //Set location - $route['location'] = $location->getId(); - } + //Set indoors + $indoors = array_reduce($this->context['cities'], function ($c, $v) { return array_merge($c, $v['indoors']); }, []); - //Generate url - return $this->redirectToRoute($name, $route); - //No route matched - } catch(MethodNotAllowedException|ResourceNotFoundException $e) { - //Unset referer to fallback to default route - unset($referer); - } - } + //Set keywords + $this->context['keywords'] = array_values( + array_merge( + [ + $this->translator->trans('Cities'), + $this->translator->trans('City list'), + $this->translator->trans('Listing'), + ], + $cities, + $indoors, + [ + $this->translator->trans('calendar'), + $this->translator->trans('Libre Air') + ] + ) + ); - //Redirect to cleanup the form - return $this->redirectToRoute('rapsys_air', ['location' => $location->getId()]); + //Render the view + return $this->render('@RapsysAir/location/cities.html.twig', $this->context, $response); } /** - * Edit location + * Display city * - * @desc Persist location in database + * @todo XXX: TODO: add + * @todo XXX: TODO: like described in: https://www.alsacreations.com/article/lire/1400-attribut-rel-relations.html#xnf-rel-attribute + * @todo XXX: TODO: or here: http://microformats.org/wiki/existing-rel-values#HTML5_link_type_extensions * * @param Request $request The request instance - * - * @return Response The rendered view or redirection - * - * @throws \RuntimeException When user has not at least guest role + * @param float $latitude The city latitude + * @param float $longitude The city longitude + * @return Response The rendered view */ - public function edit(Request $request, $id) { - //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')])); - - //Get doctrine - $doctrine = $this->getDoctrine(); - - //Get location - if (empty($location = $doctrine->getRepository(Location::class)->findOneById($id))) { - throw $this->createNotFoundException($this->translator->trans('Unable to find location: %id%', ['%id%' => $id])); + public function city(Request $request, float $latitude, float $longitude, string $city): Response { + //Get city + if (!($this->context['city'] = $this->doctrine->getRepository(Location::class)->findCityByLatitudeLongitudeAsArray(floatval($latitude), floatval($longitude)))) { + throw $this->createNotFoundException($this->translator->trans('Unable to find city: %latitude%,%longitude%', ['%latitude%' => $latitude, '%longitude%' => $longitude])); } - //Create LocationType form - $form = $this->createForm('Rapsys\AirBundle\Form\LocationType', $location, [ - //Set the action - 'action' => $this->generateUrl('rapsys_air_location_edit', ['id' => $id]), - //Set the form attribute - 'attr' => [] - ]); + //Add calendar + $this->context['calendar'] = $this->doctrine->getRepository(Session::class)->findAllByPeriodAsArray($this->period, $request->getLocale(), !$this->isGranted('IS_AUTHENTICATED_REMEMBERED'), floatval($latitude), floatval($longitude)); - //Refill the fields in case of invalid form - $form->handleRequest($request); + //Set dances + $this->context['dances'] = []; - //Handle invalid form - if (!$form->isSubmitted() || !$form->isValid()) { - //Set section - $section = $this->translator->trans('Location %id%', ['%id%' => $id]); - - //Set title - $title = $this->translator->trans($this->config['site']['title']).' - '.$section; - - //Render the view - return $this->render('@RapsysAir/location/edit.html.twig', ['id' => $id, 'title' => $title, 'section' => $section, 'form' => $form->createView()]+$this->context); + //Iterate on each calendar + foreach($this->context['calendar'] as $date => $calendar) { + //Iterate on each session + foreach($calendar['sessions'] as $sessionId => $session) { + //Session with application dance + if (!empty($session['application']['dance'])) { + //Add dance + $this->context['dances'][$session['application']['dance']['id']] = $session['application']['dance']; + } + } } - //Get manager - $manager = $doctrine->getManager(); + //Add locations + $this->context['locations'] = $this->doctrine->getRepository(Location::class)->findAllByLatitudeLongitudeAsArray(floatval($latitude), floatval($longitude), $this->period); - //Set updated - $location->setUpdated(new \DateTime('now')); + //Set modified + //XXX: dance modified is already computed inside calendar modified + $this->modified = max(array_merge([$this->context['city']['updated']], array_map(function ($v) { return $v['modified']; }, array_merge($this->context['calendar'], $this->context['locations'])))); - //Queue location save - $manager->persist($location); + //Create response + $response = new Response(); - //Flush to get the ids - $manager->flush(); + //With logged user + if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) { + //Set last modified + $response->setLastModified(new \DateTime('-1 year')); - //Add notice - $this->addFlash('notice', $this->translator->trans('Location %id% updated', ['%id%' => $id])); + //Set as private + $response->setPrivate(); + //Without logged user + } else { + //Set etag + //XXX: only for public to force revalidation by last modified + $response->setEtag(md5(serialize(array_merge($this->context['city'], $this->context['dances'], $this->context['calendar'], $this->context['locations'])))); - //Extract and process referer - if ($referer = $request->headers->get('referer')) { - //Create referer request instance - $req = Request::create($referer); + //Set last modified + $response->setLastModified($this->modified); - //Get referer path - $path = $req->getPathInfo(); + //Set as public + $response->setPublic(); - //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(); + //Without role and modification + if ($response->isNotModified($request)) { + //Return 304 response + return $response; + } + } - //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()); + //Add multi + $this->context['multimap'] = $this->map->getMultiMap($this->context['city']['multimap'], $this->modified->getTimestamp(), $latitude, $longitude, $this->context['locations'], $this->map->getMultiZoom($latitude, $longitude, $this->context['locations'])); - //Retrieve route matching path - $route = $this->router->match($path); + //Set keywords + $this->context['keywords'] = [ + $this->context['city']['city'], + $this->translator->trans('Indoor'), + $this->translator->trans('Outdoor'), + $this->translator->trans('Calendar'), + $this->translator->trans('Libre Air') + ]; - //Reset context - $this->router->setContext($oldContext); + //With context dances + if (!empty($this->context['dances'])) { + //Set dances + $dances = array_map(function ($v) { return $v['name']; }, $this->context['dances']); - //Clear old context - unset($oldContext); + //Insert dances in keywords + array_splice($this->context['keywords'], 1, 0, $dances); - //Extract name - $name = $route['_route']; + //Get textual dances + $dances = implode($this->translator->trans(' and '), array_filter(array_merge([implode(', ', array_slice($dances, 0, -1))], array_slice($dances, -1)), 'strlen')); - //Remove route and controller from route defaults - unset($route['_route'], $route['_controller']); + //Set title + $this->context['title'] = $this->translator->trans('%dances% %city%', ['%dances%' => $dances, '%city%' => $this->context['city']['in']]); - //Check if location view route - if ($name == 'rapsys_air_location_view' && !empty($route['id'])) { - //Replace id - $route['id'] = $location->getId(); - //Other routes - } else { - //Set location - $route['location'] = $location->getId(); - } + //Set description + $this->context['description'] = $this->translator->trans('%dances% indoor and outdoor calendar %city%', ['%dances%' => $dances, '%city%' => $this->context['city']['in']]); + } else { + //Set title + $this->context['title'] = $this->translator->trans('Dance %city%', ['%city%' => $this->context['city']['in']]); - //Generate url - return $this->redirectToRoute($name, $route); - //No route matched - } catch(MethodNotAllowedException|ResourceNotFoundException $e) { - //Unset referer to fallback to default route - unset($referer); - } + //Set description + $this->context['description'] = $this->translator->trans('Indoor and outdoor dance calendar %city%', ['%city%' => $this->context['city']['in']]); } - //Redirect to cleanup the form - return $this->redirectToRoute('rapsys_air', ['location' => $location->getId()]); + //Set locations description + $this->context['locations_description'] = $this->translator->trans('Libre Air location list %city%', ['%city%' => $this->context['city']['in']]); + + //Render the view + return $this->render('@RapsysAir/location/city.html.twig', $this->context, $response); } /** @@ -267,11 +240,58 @@ class LocationController extends DefaultController { * @return Response The rendered view */ public function index(Request $request): Response { - //Fetch doctrine - $doctrine = $this->getDoctrine(); + //Get locations + $this->context['locations'] = $this->doctrine->getRepository(Location::class)->findAllAsArray($this->period); + + //Set modified + $this->modified = max(array_map(function ($v) { return $v['updated']; }, $this->context['locations'])); + + //Create response + $response = new Response(); + + //With logged user + if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) { + //Set last modified + $response->setLastModified(new \DateTime('-1 year')); + + //Set as private + $response->setPrivate(); + //Without logged user + } else { + //Set etag + //XXX: only for public to force revalidation by last modified + $response->setEtag(md5(serialize($this->context['locations']))); + + //Set last modified + $response->setLastModified($this->modified); + + //Set as public + $response->setPublic(); + + //Without role and modification + if ($response->isNotModified($request)) { + //Return 304 response + return $response; + } + } - //Set section - $section = $this->translator->trans('Libre Air locations'); + //Set latitudes + $latitudes = array_map(function ($v) { return $v['latitude']; }, $this->context['locations']); + + //Set latitude + $latitude = round(array_sum($latitudes)/count($latitudes), 6); + + //Set longitudes + $longitudes = array_map(function ($v) { return $v['longitude']; }, $this->context['locations']); + + //Set longitude + $longitude = round(array_sum($longitudes)/count($longitudes), 6); + + //Add multi map + $this->context['multimap'] = $this->map->getMultiMap($this->translator->trans('Libre Air locations sector map'), $this->modified->getTimestamp(), $latitude, $longitude, $this->context['locations'], $this->map->getMultiZoom($latitude, $longitude, $this->context['locations'])); + + //Set title + $this->context['title'] = $this->translator->trans('Libre Air locations'); //Set description $this->context['description'] = $this->translator->trans('Libre Air location list'); @@ -284,126 +304,214 @@ class LocationController extends DefaultController { $this->translator->trans('Libre Air') ]; - //Set title - $title = $this->translator->trans($this->config['site']['title']).' - '.$section; - - //Compute period - $period = new \DatePeriod( - //Start from first monday of week - new \DateTime('Monday this week'), - //Iterate on each day - new \DateInterval('P1D'), - //End with next sunday and 4 weeks - new \DateTime( - $this->isGranted('IS_AUTHENTICATED_REMEMBERED')?'Monday this week + 3 week':'Monday this week + 2 week' - ) - ); - //Create location forms for role_admin if ($this->isGranted('ROLE_ADMIN')) { //Fetch all locations - $locations = $doctrine->getRepository(Location::class)->findAll(); - - //Rekey by id - $locations = array_reduce($locations, function($carry, $item){$carry[$item->getId()] = $item; return $carry;}, []); + $locations = $this->doctrine->getRepository(Location::class)->findAll(); //Init locations to context $this->context['forms']['locations'] = []; //Iterate on locations - foreach($locations as $locationId => $location) { + foreach($this->context['locations'] as $id => $location) { //Create LocationType form - $form = $this->createForm('Rapsys\AirBundle\Form\LocationType', $location, [ - //Set the action - 'action' => $this->generateUrl('rapsys_air_location_edit', ['id' => $location->getId()]), - //Set the form attribute - 'attr' => [], - //Set block prefix - //TODO: make this shit works to prevent label collision - //XXX: see https://stackoverflow.com/questions/8703016/adding-a-prefix-to-a-form-label-for-translation - 'label_prefix' => 'location_'.$locationId - ]); + $form = $this->factory->createNamed( + //Set form id + 'locations_'.$id, + //Set form type + 'Rapsys\AirBundle\Form\LocationType', + //Set form data + $locations[$location['id']], + //Set the form attributes + ['attr' => []] + ); + + //Refill the fields in case of invalid form + $form->handleRequest($request); + + //Handle valid form + if ($form->isSubmitted() && $form->isValid()) { + //Get data + $data = $form->getData(); + + //Set updated + $data->setUpdated(new \DateTime('now')); + + //Queue location save + $this->manager->persist($data); + + //Flush to get the ids + $this->manager->flush(); + + //Add notice + $this->addFlash('notice', $this->translator->trans('Location %id% updated', ['%id%' => $location['id']])); + + //Redirect to cleanup the form + return $this->redirectToRoute('rapsys_air_location', ['location' => $location['id']]); + } //Add form to context - $this->context['forms']['locations'][$locationId] = $form->createView(); + $this->context['forms']['locations'][$id] = $form->createView(); } //Create LocationType form - $form = $this->createForm('Rapsys\AirBundle\Form\LocationType', null, [ - //Set the action - 'action' => $this->generateUrl('rapsys_air_location_add'), - //Set the form attribute - 'attr' => [ 'class' => 'col' ] - ]); + $form = $this->factory->createNamed( + //Set form id + 'locations', + //Set form type + 'Rapsys\AirBundle\Form\LocationType', + //Set form data + new Location(), + //Set the form attributes + ['attr' => ['class' => 'col']] + ); + + //Refill the fields in case of invalid form + $form->handleRequest($request); + + //Handle valid form + if ($form->isSubmitted() && $form->isValid()) { + //Get data + $data = $form->getData(); + + //Queue location save + $this->manager->persist($data); + + //Flush to get the ids + $this->manager->flush(); + + //Add notice + $this->addFlash('notice', $this->translator->trans('Location created')); + + //Redirect to cleanup the form + return $this->redirectToRoute('rapsys_air_location', ['location' => $data->getId()]); + } //Add form to context $this->context['forms']['location'] = $form->createView(); } - //Fetch locations - //XXX: we want to display all active locations anyway - $locations = $doctrine->getRepository(Location::class)->findTranslatedSortedByPeriod($this->translator, $period); - //Render the view - return $this->render('@RapsysAir/location/index.html.twig', ['title' => $title, 'section' => $section, 'locations' => $locations]+$this->context); + return $this->render('@RapsysAir/location/index.html.twig', $this->context); } /** * List all sessions for the location * - * @desc Display all sessions for the location with an application or login form + * Display all sessions for the location with an application or login form + * + * @TODO: add location edit form ??? * * @param Request $request The request instance * @param int $id The location id * * @return Response The rendered view */ - public function view(Request $request, $id): Response { - //Fetch doctrine - $doctrine = $this->getDoctrine(); - - //Fetch location - if (empty($location = $doctrine->getRepository(Location::class)->findOneById($id))) { + public function view(Request $request, int $id): Response { + //Without location + if (empty($this->context['location'] = $this->doctrine->getRepository(Location::class)->findOneByIdAsArray($id, $this->locale))) { + //Throw 404 throw $this->createNotFoundException($this->translator->trans('Unable to find location: %id%', ['%id%' => $id])); } - //Set section - $section = $this->translator->trans('Argentine Tango at '.$location); + //Fetch calendar + $this->context['calendar'] = $this->doctrine->getRepository(Session::class)->findAllByPeriodAsArray($this->period, $this->locale, !$this->isGranted('IS_AUTHENTICATED_REMEMBERED'), $this->context['location']['latitude'], $this->context['location']['longitude']); + + //Set dances + $this->context['dances'] = []; + + //Iterate on each calendar + foreach($this->context['calendar'] as $date => $calendar) { + //Iterate on each session + foreach($calendar['sessions'] as $sessionId => $session) { + //Session with application dance + if (!empty($session['application']['dance'])) { + //Add dance + $this->context['dances'][$session['application']['dance']['id']] = $session['application']['dance']; + } + } + } - //Set description - $this->context['description'] = $this->translator->trans('Outdoor Argentine Tango session calendar %location%', [ '%location%' => $this->translator->trans('at '.$location) ]); + //Get locations at less than 2 km + $this->context['locations'] = $this->doctrine->getRepository(Location::class)->findAllByLatitudeLongitudeAsArray($this->context['location']['latitude'], $this->context['location']['longitude'], $this->period, 2); + + //Set modified + //XXX: dance modified is already computed inside calendar modified + $this->modified = max(array_merge([$this->context['location']['updated']], array_map(function ($v) { return $v['modified']; }, array_merge($this->context['calendar'], $this->context['locations'])))); + + //Create response + $response = new Response(); + + //With logged user + if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) { + //Set last modified + $response->setLastModified(new \DateTime('-1 year')); + + //Set as private + $response->setPrivate(); + //Without logged user + } else { + //Set etag + //XXX: only for public to force revalidation by last modified + $response->setEtag(md5(serialize(array_merge($this->context['location'], $this->context['calendar'], $this->context['locations'])))); + + //Set last modified + $response->setLastModified($this->modified); + + //Set as public + $response->setPublic(); + + //Without role and modification + if ($response->isNotModified($request)) { + //Return 304 response + return $response; + } + } + + //Add multi map + $this->context['multimap'] = $this->map->getMultiMap($this->context['location']['multimap'], $this->modified->getTimestamp(), $this->context['location']['latitude'], $this->context['location']['longitude'], $this->context['locations'], $this->map->getMultiZoom($this->context['location']['latitude'], $this->context['location']['longitude'], $this->context['locations'])); //Set keywords $this->context['keywords'] = [ - $this->translator->trans($location), - $this->translator->trans('outdoor'), - $this->translator->trans('Argentine Tango'), - $this->translator->trans('calendar') + $this->context['location']['title'], + $this->context['location']['city'], + $this->translator->trans($this->context['location']['indoor']?'Indoor':'Outdoor'), + $this->translator->trans('Calendar'), + $this->translator->trans('Libre Air') ]; - //Set title - $title = $this->translator->trans($this->config['site']['title']).' - '.$section; - - //Compute period - $period = new \DatePeriod( - //Start from first monday of week - new \DateTime('Monday this week'), - //Iterate on each day - new \DateInterval('P1D'), - //End with next sunday and 4 weeks - new \DateTime( - $this->isGranted('IS_AUTHENTICATED_REMEMBERED')?'Monday this week + 3 week':'Monday this week + 2 week' - ) - ); + //With dances + if (!empty($this->context['dances'])) { + //Set dances + $dances = array_map(function ($v) { return $v['name']; }, $this->context['dances']); - //Fetch calendar - $calendar = $doctrine->getRepository(Session::class)->fetchCalendarByDatePeriod($this->translator, $period, $id, $request->get('session'), !$this->isGranted('IS_AUTHENTICATED_REMEMBERED'), $request->getLocale()); + //Insert dances in keywords + array_splice($this->context['keywords'], 2, 0, $dances); + + //Get textual dances + $dances = implode($this->translator->trans(' and '), array_filter(array_merge([implode(', ', array_slice($dances, 0, -1))], array_slice($dances, -1)), 'strlen')); + + //Set title + $this->context['title'] = $this->translator->trans('%dances% %location%', ['%dances%' => $dances, '%location%' => $this->context['location']['atin']]); + + //Set description + $this->context['description'] = $this->translator->trans('%dances% indoor and outdoor calendar %location%', ['%dances%' => $dances, '%location%' => $this->context['location']['at']]); + //Without dances + } else { + //Set title + $this->context['title'] = $this->translator->trans('Dance %location%', ['%location%' => $this->context['location']['atin']]); + + //Set description + $this->context['description'] = $this->translator->trans('Indoor and outdoor dance calendar %location%', [ '%location%' => $this->context['location']['at'] ]); + } + + //Set locations description + $this->context['locations_description'] = $this->translator->trans('Libre Air location list %location%', ['%location%' => $this->context['location']['atin']]); - //Fetch locations - //XXX: we want to display all active locations anyway - $locations = $doctrine->getRepository(Location::class)->findTranslatedSortedByPeriod($this->translator, $period); + //Set alternates + $this->context['alternates'] += $this->context['location']['alternates']; //Render the view - return $this->render('@RapsysAir/location/view.html.twig', ['id' => $id, 'title' => $title, 'section' => $section, 'calendar' => $calendar, 'locations' => $locations]+$this->context); + return $this->render('@RapsysAir/location/view.html.twig', $this->context, $response); } } -- 2.41.1