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\HttpFoundation\Request
;
15 use Symfony\Component\HttpFoundation\Response
;
17 use Rapsys\AirBundle\Entity\Dance
;
19 class DanceController
extends AbstractController
{
20 public function index(Request
$request): Response
{
21 throw new \
RuntimeException('TODO', 503);
22 header('Content-Type: text/plain');
31 * Display dance by name
33 * @todo XXX: TODO: add <link rel="prev|next" for dances ? />
34 * @todo XXX: TODO: like described in: https://www.alsacreations.com/article/lire/1400-attribut-rel-relations.html#xnf-rel-attribute
35 * @todo XXX: TODO: or here: http://microformats.org/wiki/existing-rel-values#HTML5_link_type_extensions
37 * @TODO: faire plutôt comme /ville/x/y/paris
39 * @param Request $request The request instance
40 * @param string $name The shorted dance name
41 * @param string $dance The translated dance name
42 * @return Response The rendered view
44 public function name(Request
$request, $name, $dance): Response
{
45 throw new \
RuntimeException('TODO', 503);
48 $name = $this->slugger
->unshort($sname = $name);
51 if (empty($this->context
['dances'] = $this->doctrine
->getRepository(Dance
::class)->findByName($name))) {
53 //XXX: prevent slugger reverse engineering by not displaying decoded name
54 throw $this->createNotFoundException($this->translator
->trans('Unable to find dance %name%', ['%name%' => $sname]));
57 header('Content-Type: text/plain');
65 if (!($this->context
['city'] = $this->doctrine
->getRepository(Location
::class)->findCityByLatitudeLongitudeAsArray(floatval($latitude), floatval($longitude)))) {
66 throw $this->createNotFoundException($this->translator
->trans('Unable to find city: %latitude%,%longitude%', ['%latitude%' => $latitude, '%longitude%' => $longitude]));
70 $this->context
['calendar'] = $this->doctrine
->getRepository(Session
::class)->findAllByPeriodAsCalendarArray($this->period
, !$this->checker
->isGranted('IS_AUTHENTICATED_REMEMBERED'), floatval($latitude), floatval($longitude));
73 $this->context
['dances'] = [];
75 //Iterate on each calendar
76 foreach($this->context
['calendar'] as $date => $calendar) {
77 //Iterate on each session
78 foreach($calendar['sessions'] as $sessionId => $session) {
79 //Session with application dance
80 if (!empty($session['application']['dance'])) {
82 $this->context
['dances'][$session['application']['dance']['id']] = $session['application']['dance'];
88 $this->context
['locations'] = $this->doctrine
->getRepository(Location
::class)->findAllByLatitudeLongitudeAsArray(floatval($latitude), floatval($longitude), $this->period
);
91 //XXX: dance modified is already computed inside calendar modified
92 $this->modified
= max(array_merge([$this->context
['city']['updated']], array_map(function ($v) { return $v
['modified']; }, array_merge($this->context
['calendar'], $this->context
['locations']))));
95 $response = new Response();
98 if ($this->checker
->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
100 $response->setLastModified(new \
DateTime('-1 year'));
103 $response->setPrivate();
104 //Without logged user
107 //XXX: only for public to force revalidation by last modified
108 $response->setEtag(md5(serialize(array_merge($this->context
['city'], $this->context
['dances'], $this->context
['calendar'], $this->context
['locations']))));
111 $response->setLastModified($this->modified
);
114 $response->setPublic();
116 //Without role and modification
117 if ($response->isNotModified($request)) {
118 //Return 304 response
124 #$this->context['osm'] = $this->osm->getMultiImage($this->context['city']['link'], $this->context['city']['osm'], $this->modified->getTimestamp(), $latitude, $longitude, $this->context['locations'], $this->osm->getMultiZoom($latitude, $longitude, $this->context['locations'], 16));
125 $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']));
128 $this->context
['keywords'] = [
129 $this->context
['city']['city'],
130 $this->translator
->trans('Indoor'),
131 $this->translator
->trans('Outdoor'),
132 $this->translator
->trans('Calendar'),
133 $this->translator
->trans('Libre Air')
136 //With context dances
137 if (!empty($this->context
['dances'])) {
139 $dances = array_map(function ($v) { return $v
['name']; }, $this->context
['dances']);
141 //Insert dances in keywords
142 array_splice($this->context
['keywords'], 1, 0, $dances);
145 $dances = implode($this->translator
->trans(' and '), array_filter(array_merge([implode(', ', array_slice($dances, 0, -1))], array_slice($dances, -1)), 'strlen'));
148 $this->context
['title'] = $this->translator
->trans('%dances% %city%', ['%dances%' => $dances, '%city%' => $this->context
['city']['in']]);
151 $this->context
['description'] = $this->translator
->trans('%dances% indoor and outdoor calendar %city%', ['%dances%' => $dances, '%city%' => $this->context
['city']['in']]);
154 $this->context
['title'] = $this->translator
->trans('Dance %city%', ['%city%' => $this->context
['city']['in']]);
157 $this->context
['description'] = $this->translator
->trans('Indoor and outdoor dance calendar %city%', ['%city%' => $this->context
['city']['in']]);
160 //Set locations description
161 $this->context
['locations_description'] = $this->translator
->trans('Libre Air location list %city%', ['%city%' => $this->context
['city']['in']]);
164 return $this->render('@RapsysAir/dance/name.html.twig', $this->context
, $response);
168 * List all sessions for the dance
170 * Display all sessions for the dance with an application or login form
172 * @TODO: add dance edit form ???
174 * @param Request $request The request instance
175 * @param int $id The dance id
176 * @param ?string $name The dance name
177 * @param ?string $type The dance type
179 * @return Response The rendered view
181 public function view(Request
$request, int $id, string $name, string $type): Response
{
183 if (empty($this->context
['dance'] = $this->doctrine
->getRepository(Dance
::class)->findOneByIdAsArray($id))) {
185 throw $this->createNotFoundException($this->translator
->trans('Unable to find dance: %id%', ['%id%' => $id]));
188 //With invalid name slug
189 if ($name !== $this->context
['dance']['slug']['name']) {
190 //Redirect on correctly spelled location
191 return $this->redirect($this->context
['dance']['link'], Response
::HTTP_MOVED_PERMANENTLY
);
194 //With invalid type slug
195 if ($type !== $this->context
['dance']['slug']['type']) {
196 //Redirect on correctly spelled location
197 return $this->redirect($this->context
['dance']['link'], Response
::HTTP_MOVED_PERMANENTLY
);
200 throw new \
RuntimeException('TODO', 503);
201 header('Content-Type: text/plain');
209 $this->context
['calendar'] = $this->doctrine
->getRepository(Session
::class)->findAllByPeriodAsCalendarArray($this->period
, !$this->checker
->isGranted('IS_AUTHENTICATED_REMEMBERED'), $this->context
['location']['latitude'], $this->context
['location']['longitude']);
212 $this->context
['dances'] = [];
214 //Iterate on each calendar
215 foreach($this->context
['calendar'] as $date => $calendar) {
216 //Iterate on each session
217 foreach($calendar['sessions'] as $sessionId => $session) {
218 //Session with application dance
219 if (!empty($session['application']['dance'])) {
221 $this->context
['dances'][$session['application']['dance']['id']] = $session['application']['dance'];
226 //Get locations at less than 2 km
227 $this->context
['locations'] = $this->doctrine
->getRepository(Location
::class)->findAllByLatitudeLongitudeAsArray($this->context
['location']['latitude'], $this->context
['location']['longitude'], $this->period
, 2);
230 //XXX: dance modified is already computed inside calendar modified
231 $this->modified
= max(array_merge([$this->context
['location']['modified']], array_map(function ($v) { return $v
['modified']; }, array_merge($this->context
['calendar'], $this->context
['locations']))));
234 $response = new Response();
237 if ($this->checker
->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
239 $response->setLastModified(new \
DateTime('-1 year'));
242 $response->setPrivate();
243 //Without logged user
246 //XXX: only for public to force revalidation by last modified
247 $response->setEtag(md5(serialize(array_merge($this->context
['location'], $this->context
['calendar'], $this->context
['locations']))));
250 $response->setLastModified($this->modified
);
253 $response->setPublic();
255 //Without role and modification
256 if ($response->isNotModified($request)) {
257 //Return 304 response
263 $this->context
['multimap'] = $this->map
->getMultiMap($this->context
['location']['multimap'], $this->modified
->getTimestamp(), $this->context
['locations']);
266 $this->context
['keywords'] = [
267 $this->context
['location']['title'],
268 $this->context
['location']['city']['title'],
269 $this->translator
->trans($this->context
['location']['indoor']?'Indoor':'Outdoor'),
270 $this->translator
->trans('Calendar'),
271 $this->translator
->trans('Libre Air')
275 if (!empty($this->context
['dances'])) {
277 $dances = array_map(function ($v) { return $v
['name']; }, $this->context
['dances']);
279 //Insert dances in keywords
280 array_splice($this->context
['keywords'], 2, 0, $dances);
283 $dances = implode($this->translator
->trans(' and '), array_filter(array_merge([implode(', ', array_slice($dances, 0, -1))], array_slice($dances, -1)), 'strlen'));
286 $this->context
['title']['page'] = $this->translator
->trans('%dances% %location%', ['%dances%' => $dances, '%location%' => $this->context
['location']['atin']]);
289 $this->context
['description'] = $this->translator
->trans('%dances% indoor and outdoor calendar %location%', ['%dances%' => $dances, '%location%' => $this->context
['location']['at']]);
293 $this->context
['title']['page'] = $this->translator
->trans('Dance %location%', ['%location%' => $this->context
['location']['atin']]);
296 $this->context
['description'] = $this->translator
->trans('Indoor and outdoor dance calendar %location%', ['%location%' => $this->context
['location']['at']]);
299 //Set locations description
300 $this->context
['locations_description'] = $this->translator
->trans('Libre Air location list %location% %city%', ['%location%' => $this->context
['location']['around'], '%city%' => $this->context
['location']['city']['in']]);
303 $this->context
['locations_link'] = $this->context
['location']['city']['link'];
305 //Set locations title
306 $this->context
['locations_title'] = $this->context
['location']['city']['title'].' ('.$this->context
['location']['city']['id'].')';
309 $this->context
['alternates'] +
= $this->context
['location']['alternates'];
312 return $this->render('@RapsysAir/location/view.html.twig', $this->context
, $response);