]> Raphaël G. Git Repositories - airbundle/blob - Controller/DanceController.php
List dance sessions
[airbundle] / Controller / DanceController.php
1 <?php declare(strict_types=1);
2
3 /*
4 * This file is part of the Rapsys AirBundle package.
5 *
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Rapsys\AirBundle\Controller;
13
14 use Symfony\Component\HttpFoundation\Request;
15 use Symfony\Component\HttpFoundation\Response;
16
17 use Rapsys\AirBundle\Entity\Dance;
18
19 class DanceController extends AbstractController {
20 public function index(Request $request): Response {
21 throw new \RuntimeException('TODO', 503);
22 header('Content-Type: text/plain');
23 var_dump('TODO');
24 #var_dump($name);
25 #var_dump($type);
26 #var_dump($slug);
27 exit;
28 }
29
30 /**
31 * Display dance by name
32 *
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
36 *
37 * @TODO: faire plutôt comme /ville/x/y/paris
38 *
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
43 */
44 public function name(Request $request, $name, $dance): Response {
45 throw new \RuntimeException('TODO', 503);
46
47 //Get name
48 $name = $this->slugger->unshort($sname = $name);
49
50 //With existing dance
51 if (empty($this->context['dances'] = $this->doctrine->getRepository(Dance::class)->findByName($name))) {
52 //Throw not found
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]));
55 }
56
57 header('Content-Type: text/plain');
58 var_dump('TODO');
59 #var_dump($name);
60 #var_dump($type);
61 #var_dump($slug);
62 exit;
63
64 //Get city
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]));
67 }
68
69 //Add calendar
70 $this->context['calendar'] = $this->doctrine->getRepository(Session::class)->findAllByPeriodAsCalendarArray($this->period, !$this->checker->isGranted('IS_AUTHENTICATED_REMEMBERED'), floatval($latitude), floatval($longitude));
71
72 //Set dances
73 $this->context['dances'] = [];
74
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'])) {
81 //Add dance
82 $this->context['dances'][$session['application']['dance']['id']] = $session['application']['dance'];
83 }
84 }
85 }
86
87 //Add locations
88 $this->context['locations'] = $this->doctrine->getRepository(Location::class)->findAllByLatitudeLongitudeAsArray(floatval($latitude), floatval($longitude), $this->period);
89
90 //Set modified
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']))));
93
94 //Create response
95 $response = new Response();
96
97 //With logged user
98 if ($this->checker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
99 //Set last modified
100 $response->setLastModified(new \DateTime('-1 year'));
101
102 //Set as private
103 $response->setPrivate();
104 //Without logged user
105 } else {
106 //Set etag
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']))));
109
110 //Set last modified
111 $response->setLastModified($this->modified);
112
113 //Set as public
114 $response->setPublic();
115
116 //Without role and modification
117 if ($response->isNotModified($request)) {
118 //Return 304 response
119 return $response;
120 }
121 }
122
123 //Add multi
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']));
126
127 //Set keywords
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')
134 ];
135
136 //With context dances
137 if (!empty($this->context['dances'])) {
138 //Set dances
139 $dances = array_map(function ($v) { return $v['name']; }, $this->context['dances']);
140
141 //Insert dances in keywords
142 array_splice($this->context['keywords'], 1, 0, $dances);
143
144 //Get textual dances
145 $dances = implode($this->translator->trans(' and '), array_filter(array_merge([implode(', ', array_slice($dances, 0, -1))], array_slice($dances, -1)), 'strlen'));
146
147 //Set title
148 $this->context['title'] = $this->translator->trans('%dances% %city%', ['%dances%' => $dances, '%city%' => $this->context['city']['in']]);
149
150 //Set description
151 $this->context['description'] = $this->translator->trans('%dances% indoor and outdoor calendar %city%', ['%dances%' => $dances, '%city%' => $this->context['city']['in']]);
152 } else {
153 //Set title
154 $this->context['title'] = $this->translator->trans('Dance %city%', ['%city%' => $this->context['city']['in']]);
155
156 //Set description
157 $this->context['description'] = $this->translator->trans('Indoor and outdoor dance calendar %city%', ['%city%' => $this->context['city']['in']]);
158 }
159
160 //Set locations description
161 $this->context['locations_description'] = $this->translator->trans('Libre Air location list %city%', ['%city%' => $this->context['city']['in']]);
162
163 //Render the view
164 return $this->render('@RapsysAir/dance/name.html.twig', $this->context, $response);
165 }
166
167 /**
168 * List all sessions for the dance
169 *
170 * Display all sessions for the dance with an application or login form
171 *
172 * @TODO: add dance edit form ???
173 *
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
178 *
179 * @return Response The rendered view
180 */
181 public function view(Request $request, int $id, string $name, string $type): Response {
182 //Without dance
183 if (empty($this->context['dance'] = $this->doctrine->getRepository(Dance::class)->findOneByIdAsArray($id))) {
184 //Throw 404
185 throw $this->createNotFoundException($this->translator->trans('Unable to find dance: %id%', ['%id%' => $id]));
186 }
187
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);
192 }
193
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);
198 }
199
200 throw new \RuntimeException('TODO', 503);
201 header('Content-Type: text/plain');
202 var_dump('TODO');
203 #var_dump($name);
204 #var_dump($type);
205 #var_dump($slug);
206 exit;
207
208 //Fetch calendar
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']);
210
211 //Set dances
212 $this->context['dances'] = [];
213
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'])) {
220 //Add dance
221 $this->context['dances'][$session['application']['dance']['id']] = $session['application']['dance'];
222 }
223 }
224 }
225
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);
228
229 //Set modified
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']))));
232
233 //Create response
234 $response = new Response();
235
236 //With logged user
237 if ($this->checker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
238 //Set last modified
239 $response->setLastModified(new \DateTime('-1 year'));
240
241 //Set as private
242 $response->setPrivate();
243 //Without logged user
244 } else {
245 //Set etag
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']))));
248
249 //Set last modified
250 $response->setLastModified($this->modified);
251
252 //Set as public
253 $response->setPublic();
254
255 //Without role and modification
256 if ($response->isNotModified($request)) {
257 //Return 304 response
258 return $response;
259 }
260 }
261
262 //Add multi map
263 $this->context['multimap'] = $this->map->getMultiMap($this->context['location']['multimap'], $this->modified->getTimestamp(), $this->context['locations']);
264
265 //Set keywords
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')
272 ];
273
274 //With dances
275 if (!empty($this->context['dances'])) {
276 //Set dances
277 $dances = array_map(function ($v) { return $v['name']; }, $this->context['dances']);
278
279 //Insert dances in keywords
280 array_splice($this->context['keywords'], 2, 0, $dances);
281
282 //Get textual dances
283 $dances = implode($this->translator->trans(' and '), array_filter(array_merge([implode(', ', array_slice($dances, 0, -1))], array_slice($dances, -1)), 'strlen'));
284
285 //Set title
286 $this->context['title']['page'] = $this->translator->trans('%dances% %location%', ['%dances%' => $dances, '%location%' => $this->context['location']['atin']]);
287
288 //Set description
289 $this->context['description'] = $this->translator->trans('%dances% indoor and outdoor calendar %location%', ['%dances%' => $dances, '%location%' => $this->context['location']['at']]);
290 //Without dances
291 } else {
292 //Set title
293 $this->context['title']['page'] = $this->translator->trans('Dance %location%', ['%location%' => $this->context['location']['atin']]);
294
295 //Set description
296 $this->context['description'] = $this->translator->trans('Indoor and outdoor dance calendar %location%', ['%location%' => $this->context['location']['at']]);
297 }
298
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']]);
301
302 //Set locations link
303 $this->context['locations_link'] = $this->context['location']['city']['link'];
304
305 //Set locations title
306 $this->context['locations_title'] = $this->context['location']['city']['title'].' ('.$this->context['location']['city']['id'].')';
307
308 //Set alternates
309 $this->context['alternates'] += $this->context['location']['alternates'];
310
311 //Render the view
312 return $this->render('@RapsysAir/location/view.html.twig', $this->context, $response);
313 }
314 }