Commit | Line | Data |
---|---|---|
dec6d031 JB |
1 | <?php |
2 | namespace App\Controller; | |
3 | ||
4 | use App\Entity\Person; | |
3d47ccc8 JB |
5 | use App\Entity\Localisation; |
6 | use \Datetime; | |
1d9d8d51 | 7 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; |
f0640a52 | 8 | use FOS\RestBundle\Controller\FOSRestController; |
dec6d031 | 9 | use FOS\RestBundle\Controller\Annotations as Rest; |
5347d06b JB |
10 | use FOS\RestBundle\View\ViewHandler; |
11 | use FOS\RestBundle\View\View; | |
dec6d031 JB |
12 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; |
13 | use Symfony\Component\HttpFoundation\Request; | |
14 | use Symfony\Component\HttpFoundation\Response; | |
15 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | |
16 | ||
f0640a52 | 17 | class PersonController extends FOSRestController |
dec6d031 JB |
18 | { |
19 | /** | |
20 | * @Rest\Post( | |
f0640a52 | 21 | * path = "/api/person/register", |
dec6d031 JB |
22 | * name = "create_person" |
23 | * ) | |
24 | * @Rest\View(StatusCode = Response::HTTP_CREATED) | |
dec6d031 | 25 | */ |
f0640a52 | 26 | public function createPersonAction(Request $request) |
3d47ccc8 JB |
27 | { |
28 | $person = new Person(); | |
f0640a52 JB |
29 | $person->setFirstname($request->get('firstname')); |
30 | $person->setLastName($request->get('lastname')); | |
c4fba949 | 31 | //TODO: email creation should normally have a verification step |
f0640a52 JB |
32 | $person->setEmail($request->get('email')); |
33 | $person->setPassword($request->get('password')); | |
34 | $person->setOnline(false); | |
35 | ||
dec6d031 JB |
36 | $em = $this->getDoctrine()->getManager(); |
37 | ||
38 | $em->persist($person); | |
39 | $em->flush(); | |
40 | ||
41 | return $this->view($person, Response::HTTP_CREATED, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]); | |
42 | } | |
43 | ||
44 | /** | |
98f85207 | 45 | * @Rest\Delete("/api/person/{id}") |
dec6d031 JB |
46 | * @Rest\View(statusCode = Response::HTTP_NO_CONTENT) |
47 | */ | |
48 | public function removePersonAction(Request $request) | |
49 | { | |
3d47ccc8 | 50 | //TODO: check that the authenticated user have the same id |
dec6d031 | 51 | $em = $this->getDoctrine()->getManager(); |
282545e5 | 52 | $person = $em->getRepository('App:Person')->find($request->get('id')); |
3d47ccc8 JB |
53 | $friends = $em->getRepository('App:Friendship')->findBy(['person' => $request->get('id')]); |
54 | $friends_with_me = $em->getRepository('App:Friendship')->findBy(['friend' => $request->get('id')]); | |
55 | $localisations = $em->getRepository('App:Localisation')->findBy(['person' => $request->get('id')]); | |
dec6d031 | 56 | |
3d47ccc8 JB |
57 | if (!empty($localisations)) { |
58 | foreach ($localisations as $localisation) { | |
59 | $em->remove($localisation); | |
60 | } | |
61 | $em->flush(); | |
62 | } | |
63 | ||
64 | if (!empty($friends)) { | |
65 | foreach ($friends as $friend) { | |
66 | $em->remove($friend); | |
67 | } | |
68 | $em->flush(); | |
69 | } | |
70 | ||
71 | if (!empty($friends_with_me)) { | |
72 | foreach ($friends_with_me as $friend) { | |
73 | $em->remove($friend); | |
74 | } | |
dec6d031 JB |
75 | $em->flush(); |
76 | } | |
3d47ccc8 JB |
77 | |
78 | if (!empty($person)) { | |
79 | $em->remove($person); | |
80 | $em->flush(); | |
81 | } | |
dec6d031 JB |
82 | } |
83 | ||
84 | /** | |
85 | * @Rest\Put( | |
3d47ccc8 | 86 | * path = "/api/person/{id}", |
dec6d031 JB |
87 | * name = "update_person" |
88 | * ) | |
89 | * @Rest\View(StatusCode = Response::HTTP_CREATED) | |
90 | */ | |
91 | public function updatePersonAction(Request $request) | |
92 | { | |
3d47ccc8 | 93 | //TODO: check that the authenticated user have the same id |
dec6d031 | 94 | $em = $this->getDoctrine()->getManager(); |
282545e5 | 95 | $person = $em->getRepository('App:Person')->find($request->get('id')); |
dec6d031 | 96 | |
51963d7f | 97 | if (empty($person)) { |
1faa29dc | 98 | return $this->PersonNotFound(); |
dec6d031 JB |
99 | } |
100 | ||
101 | $person->setFirstName($request->get('firstname')); | |
102 | $person->setLastName($request->get('lastname')); | |
c4fba949 | 103 | //TODO: email update should normally have a verification step |
dec6d031 JB |
104 | $person->setEmail($request->get('email')); |
105 | ||
106 | $em->merge($person); | |
107 | $em->flush(); | |
108 | ||
109 | return $this->view($person, Response::HTTP_CREATED, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]); | |
110 | } | |
111 | ||
c4fba949 JB |
112 | /** |
113 | * @Rest\Post( | |
114 | * path = "/api/person/authenticate", | |
115 | * name = "authenticate_person" | |
116 | * ) | |
117 | * @Rest\View(StatusCode = Response::HTTP_ACCEPTED) | |
118 | */ | |
119 | public function authenticatePersonAction(Request $request) | |
120 | { | |
121 | $em = $this->getDoctrine()->getManager(); | |
122 | $person = $em->getRepository('App:Person')->findOneBy(['email' => $request->get('email')]); | |
123 | ||
124 | if (empty($person)) { | |
125 | return $this->PersonNotFound(); | |
126 | } | |
127 | ||
128 | if ($request->get('password') != $person->getPassword()) { | |
129 | return $this->PersonWrongPassword(); | |
130 | } else { | |
131 | return $this->view($person, Response::HTTP_ACCEPTED, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]); | |
132 | } | |
133 | } | |
134 | ||
dec6d031 | 135 | /** |
84fd6c7f JB |
136 | * @Rest\Get("/api/person/{id}/localisations") |
137 | * @Rest\View() | |
dec6d031 | 138 | */ |
84fd6c7f | 139 | public function getLocalisationsAction(Request $request) |
dec6d031 | 140 | { |
f0640a52 | 141 | //TODO: Check that the authenticated user is allowed to see the localisation |
84fd6c7f JB |
142 | $em = $this->getDoctrine()->getManager(); |
143 | $localisations = $em->getRepository('App:Localisation')->findBy(['person' => $request->get('id')]); | |
dec6d031 | 144 | |
84fd6c7f JB |
145 | if (empty($localisations)) { |
146 | return $this->PersonLocalisationsNotFound(); | |
147 | } | |
148 | ||
149 | return $localisations; | |
dec6d031 JB |
150 | } |
151 | ||
c4fba949 JB |
152 | /** |
153 | * @Rest\Get( | |
154 | * path = "/api/person/{id}/localisations/fuzzy/{distance}", | |
155 | * name = "person_localisations_fuzzy", | |
156 | * requirements = {"id"="\d+", "distance"="\d+"} | |
157 | * ) | |
158 | * @Rest\View() | |
159 | */ | |
160 | public function getLocalisationsFuzzyAction(Request $request) | |
161 | { | |
162 | //TODO: Check that the authenticated user is allowed to see the localisation | |
163 | $em = $this->getDoctrine()->getManager(); | |
164 | $localisations = $em->getRepository('App:Localisation')->findBy(['person' => $request->get('id')]); | |
165 | ||
166 | if (empty($localisations)) { | |
167 | return $this->PersonLocalisationsNotFound(); | |
168 | } | |
169 | ||
170 | if (!$this->chk_distance($request->get('distance'), 200, 500)) { | |
171 | return $this->PersonLocalisationFuzzyWrongDistance(); | |
172 | } | |
173 | ||
174 | $fuzzy_localisations = array_map(function($item) use ($request) { return $this->randomizeLocation($item, $request->get('distance'), 200, 500); }, $localisations); | |
175 | ||
176 | return $fuzzy_localisations; | |
177 | } | |
178 | ||
179 | private function getLastLocalisation($em, $id) { | |
180 | $query = $em->createQuery("SELECT l1 FROM App\Entity\Localisation l1 WHERE l1.person = :person and l1.timestamp = (SELECT MAX(l2.timestamp) FROM App\Entity\Localisation l2 WHERE l2.person = l1.person)"); | |
181 | $query->setParameter('person', $id); | |
19b09998 JB |
182 | $result = $query->getResult(); |
183 | if (!empty($result)) { | |
184 | return $result[0]; | |
185 | } | |
c4fba949 JB |
186 | } |
187 | ||
4c4feb3e | 188 | /** |
84fd6c7f JB |
189 | * @Rest\Get("/api/person/{id}/localisation") |
190 | * @Rest\View() | |
4c4feb3e | 191 | */ |
84fd6c7f | 192 | public function getLocalisationAction(Request $request) |
4c4feb3e | 193 | { |
f0640a52 | 194 | //TODO: Check that the authenticated user is allowed to see the localisation |
4c4feb3e | 195 | $em = $this->getDoctrine()->getManager(); |
787fc3b7 | 196 | |
c4fba949 | 197 | $localisation = $this->getLastLocalisation($em, $request->get('id')); |
4c4feb3e | 198 | |
f0640a52 | 199 | if (empty($localisation)) { |
84fd6c7f | 200 | return $this->PersonLocalisationNotFound(); |
4c4feb3e JB |
201 | } |
202 | ||
f0640a52 | 203 | return $localisation; |
4c4feb3e JB |
204 | } |
205 | ||
c4fba949 JB |
206 | private function chk_distance($distance, $min, $max) { |
207 | if ($distance >= $min && $distance <= $max) { | |
208 | return true; | |
209 | } else { | |
210 | return false; | |
211 | } | |
212 | } | |
213 | ||
214 | private function randomizeLocation($localisation, $distance, $min, $max) { | |
215 | // Generate random float in [0, 1[, [0, 1) | |
216 | $u = rand(0, getrandmax() - 1) / getrandmax(); | |
217 | $v = rand(0, getrandmax() - 1) / getrandmax(); | |
218 | ||
219 | if ($this->chk_distance($distance, $min, $max)) { | |
220 | $r = $distance / 111300; | |
221 | } else { | |
222 | return $this->PersonLocalisationFuzzyWrongDistance(); | |
223 | } | |
224 | ||
225 | $w = $r * sqrt($u); | |
226 | $t = 2 * pi() * $v; | |
227 | ||
228 | $x = $w * cos($t); | |
229 | $lng_off = $x / cos(deg2rad($localisation->getLatitude())); | |
230 | $lat_off = $w * sin($t); | |
231 | ||
232 | $fuzzy_localisation = new Localisation(); | |
233 | $fuzzy_localisation->setTimestamp($localisation->getTimestamp()); | |
234 | $fuzzy_localisation->setLatitude($localisation->getLatitude() + $lat_off); | |
235 | $fuzzy_localisation->setLongitude($localisation->getLongitude() + $lng_off); | |
236 | return $fuzzy_localisation; | |
237 | } | |
238 | ||
239 | /** | |
240 | * @Rest\Get( | |
241 | * path = "/api/person/{id}/localisation/fuzzy/{distance}", | |
242 | * name = "person_localisation_fuzzy", | |
243 | * requirements = {"id"="\d+", "distance"="\d+"} | |
244 | * ) | |
245 | * @Rest\View() | |
246 | */ | |
247 | public function getLocalisationFuzzyAction(Request $request) | |
248 | { | |
249 | //TODO: Check that the authenticated user is allowed to see the localisation | |
250 | $em = $this->getDoctrine()->getManager(); | |
251 | ||
252 | $localisation = $this->getLastLocalisation($em, $request->get('id')); | |
253 | ||
254 | if (empty($localisation)) { | |
255 | return $this->PersonLocalisationNotFound(); | |
256 | } | |
257 | ||
258 | return $this->randomizeLocation($localisation, $request->get('distance'), 200, 500); | |
259 | } | |
260 | ||
dec6d031 | 261 | /** |
98f85207 | 262 | * @Rest\Post("/api/person/{id}/localisation") |
43f58db4 | 263 | * @Rest\View(StatusCode = Response::HTTP_CREATED) |
dec6d031 JB |
264 | */ |
265 | public function updateLocalisationAction(Request $request) | |
266 | { | |
3d47ccc8 JB |
267 | //TODO: Check that the authenticated user is allowed to update the localisation |
268 | $em = $this->getDoctrine()->getManager(); | |
269 | ||
270 | $person = $em->getRepository('App:Person')->find($request->get('id')); | |
271 | ||
272 | if (empty($person)) { | |
273 | return $this->PersonNotFound(); | |
274 | } | |
275 | ||
276 | $datetime = new DateTime($request->get('timestamp')); | |
277 | ||
dec6d031 | 278 | $localisation = new Localisation(); |
3d47ccc8 JB |
279 | $localisation->setPerson($person); |
280 | $localisation->setTimestamp($datetime); | |
dec6d031 JB |
281 | $localisation->setLatitude($request->get('latitude')); |
282 | $localisation->setLongitude($request->get('longitude')); | |
283 | ||
dec6d031 JB |
284 | $em->persist($localisation); |
285 | $em->flush(); | |
286 | } | |
287 | ||
288 | /** | |
f0640a52 JB |
289 | * @Rest\Get( |
290 | * path = "/api/person/{id}", | |
291 | * name = "show_person", | |
292 | * requirements = {"id"="\d+"} | |
293 | * ) | |
294 | * @Rest\View() | |
295 | */ | |
296 | public function showPerson(Request $request) | |
297 | { | |
5347d06b JB |
298 | $em = $this->getDoctrine()->getManager(); |
299 | $person = $em->getRepository('App:Person')->find($request->get('id')); | |
51963d7f | 300 | |
5347d06b | 301 | if (empty($person)) { |
1faa29dc | 302 | return $this->PersonNotFound(); |
51963d7f JB |
303 | } |
304 | ||
1faa29dc | 305 | return $person; |
f0640a52 JB |
306 | } |
307 | ||
f0640a52 JB |
308 | /** |
309 | * @Rest\Get( | |
310 | * path = "/api/person/{id}/friends", | |
311 | * name = "show_person_friends", | |
312 | * requirements = {"id"="\d+"} | |
313 | * ) | |
314 | * @Rest\View() | |
315 | */ | |
316 | public function showPersonFriends(Request $request) | |
317 | { | |
5347d06b JB |
318 | $em = $this->getDoctrine()->getManager(); |
319 | $person = $em->getRepository('App:Person')->find($request->get('id')); | |
320 | ||
321 | if (empty($person)) { | |
1faa29dc | 322 | return $this->PersonNotFound(); |
5347d06b | 323 | } |
51963d7f | 324 | |
1faa29dc | 325 | return $person->getFriends(); |
f0640a52 JB |
326 | } |
327 | ||
c4fba949 JB |
328 | /** |
329 | * @Rest\Get( | |
330 | * path = "/api/person/{id}/friendswithme", | |
331 | * name = "show_person_friends_with_me", | |
332 | * requirements = {"id"="\d+"} | |
333 | * ) | |
334 | * @Rest\View() | |
335 | */ | |
336 | public function showPersonFriendsWithMe(Request $request) | |
337 | { | |
338 | $em = $this->getDoctrine()->getManager(); | |
339 | $person = $em->getRepository('App:Person')->find($request->get('id')); | |
340 | ||
341 | if (empty($person)) { | |
342 | return $this->PersonNotFound(); | |
343 | } | |
344 | ||
345 | return $person->getFriendsWithMe(); | |
346 | } | |
347 | ||
f0640a52 JB |
348 | /** |
349 | * @Rest\Get( | |
350 | * path = "/api/persons", | |
351 | * name = "show_persons" | |
352 | * ) | |
353 | * @Rest\View() | |
354 | */ | |
355 | public function showPersons(Request $request) | |
356 | { | |
357 | $em = $this->getDoctrine()->getManager(); | |
358 | $persons = $em->getRepository('App:Person')->findAll(); | |
359 | ||
360 | if (empty($persons)) { | |
84fd6c7f | 361 | return $this->PersonsNotFound(); |
f0640a52 JB |
362 | } |
363 | ||
364 | return $persons; | |
365 | } | |
366 | ||
8629835e JB |
367 | /** |
368 | * @Rest\Put( | |
369 | * path = "/api/person/{id}/online", | |
370 | * name = "set_person_online" | |
371 | * ) | |
372 | * @Rest\View(StatusCode = Response::HTTP_CREATED) | |
373 | */ | |
374 | public function onlinePersonAction(Request $request) | |
375 | { | |
376 | //TODO: check that the authenticated user have the same id | |
377 | $em = $this->getDoctrine()->getManager(); | |
378 | $person = $em->getRepository('App:Person')->find($request->get('id')); | |
379 | ||
380 | if (empty($person)) { | |
381 | return $this->PersonNotFound(); | |
382 | } | |
383 | ||
384 | $person->setOnline(true); | |
385 | ||
386 | $em->merge($person); | |
387 | $em->flush(); | |
388 | } | |
389 | ||
390 | /** | |
391 | * @Rest\Put( | |
392 | * path = "/api/person/{id}/offline", | |
393 | * name = "set_person_offline" | |
394 | * ) | |
395 | * @Rest\View(StatusCode = Response::HTTP_CREATED) | |
396 | */ | |
397 | public function offlinePersonAction(Request $request) | |
398 | { | |
399 | //TODO: check that the authenticated user have the same id | |
400 | $em = $this->getDoctrine()->getManager(); | |
401 | $person = $em->getRepository('App:Person')->find($request->get('id')); | |
402 | ||
403 | if (empty($person)) { | |
404 | return $this->PersonNotFound(); | |
405 | } | |
406 | ||
407 | $person->setOnline(false); | |
408 | ||
409 | $em->merge($person); | |
410 | $em->flush(); | |
411 | } | |
412 | ||
f0640a52 JB |
413 | private function PersonNotFound() { |
414 | return View::create(['message' => 'Person not found'], Response::HTTP_NOT_FOUND); | |
415 | } | |
b6077893 | 416 | |
f0640a52 JB |
417 | private function PersonsNotFound() { |
418 | return View::create(['message' => 'Persons not found'], Response::HTTP_NOT_FOUND); | |
419 | } | |
84fd6c7f | 420 | |
f0640a52 JB |
421 | private function PersonLocalisationNotFound() { |
422 | return View::create(['message' => 'Person localisation not found'], Response::HTTP_NOT_FOUND); | |
423 | } | |
84fd6c7f | 424 | |
f0640a52 JB |
425 | private function PersonLocalisationsNotFound() { |
426 | return View::create(['message' => 'Person localisations not found'], Response::HTTP_NOT_FOUND); | |
427 | } | |
b6077893 | 428 | |
c4fba949 JB |
429 | private function PersonWrongPassword() { |
430 | return View::create(['message' => 'Supplied password do not match'], Response::HTTP_UNAUTHORIZED); | |
431 | } | |
432 | private function PersonLocalisationFuzzyWrongDistance() { | |
433 | return View::create(['message' => 'Distance range do not match'], Response::HTTP_NOT_ACCEPTABLE); | |
434 | } | |
435 | ||
dec6d031 | 436 | } |