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