Code cleanups
[Project_proches_de_moi-server.git] / src / Controller / PersonController.php
CommitLineData
dec6d031
JB
1<?php
2namespace App\Controller;
3
4use App\Entity\Person;
3d47ccc8
JB
5use App\Entity\Localisation;
6use \Datetime;
1d9d8d51 7use Symfony\Bundle\FrameworkBundle\Controller\Controller;
f0640a52 8use FOS\RestBundle\Controller\FOSRestController;
dec6d031 9use FOS\RestBundle\Controller\Annotations as Rest;
5347d06b
JB
10use FOS\RestBundle\View\ViewHandler;
11use FOS\RestBundle\View\View;
199445c0 12use FOS\RestBundle\Request\ParamFetcherInterface;
dec6d031
JB
13use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
14use Symfony\Component\HttpFoundation\Request;
15use Symfony\Component\HttpFoundation\Response;
16use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
17
f0640a52 18class 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}