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