2 namespace App\Controller
;
5 use App\Entity\Localisation
;
8 use Symfony\Bundle\FrameworkBundle\Controller\Controller
;
9 use FOS\RestBundle\Controller\FOSRestController
;
10 use FOS\RestBundle\Controller\Annotations
as Rest
;
11 use FOS\RestBundle\View\ViewHandler
;
12 use FOS\RestBundle\View\View
;
13 use FOS\RestBundle\Request\ParamFetcherInterface
;
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
;
19 class PersonController
extends FOSRestController
23 * path = "/api/person/register",
24 * name = "create_person"
26 * @Rest\View(StatusCode = Response::HTTP_CREATED)
28 public function createPersonAction(Request
$request)
30 $person = new Person();
31 $person->setFirstname($request->get('firstname'));
32 $person->setLastName($request->get('lastname'));
33 //TODO: email creation should normally have a verification step
34 $person->setEmail($request->get('email'));
35 $person->setPassword($request->get('password'));
36 $person->setOnline(false);
38 $em = $this->getDoctrine()->getManager();
40 $em->persist($person);
43 return $this->view($person, Response
::HTTP_CREATED
,
44 ['Location' => $this->generateUrl('show_person',
45 ['id' => $person->getId(),
46 UrlGeneratorInterface
::ABSOLUTE_URL
])]);
50 * @Rest\Delete("/api/person/{id}")
51 * @Rest\View(statusCode = Response::HTTP_NO_CONTENT)
53 public function removePersonAction(Request
$request)
55 //TODO: check that the authenticated user have the same id
56 $em = $this->getDoctrine()->getManager();
57 $person = $em->getRepository('App:Person')->find($request->get('id'));
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')]);
62 if (!empty($localisations)) {
63 foreach ($localisations as $localisation) {
64 $em->remove($localisation);
69 if (!empty($friends)) {
70 foreach ($friends as $friend) {
76 if (!empty($friends_with_me)) {
77 foreach ($friends_with_me as $friend) {
83 if (!empty($person)) {
91 * path = "/api/person/{id}",
92 * name = "update_person"
94 * @Rest\View(StatusCode = Response::HTTP_CREATED)
96 public function updatePersonAction(Request
$request)
98 //TODO: check that the authenticated user have the same id
99 $em = $this->getDoctrine()->getManager();
100 $person = $em->getRepository('App:Person')->find($request->get('id'));
102 if (empty($person)) {
103 return $this->PersonNotFound();
106 $person->setFirstName($request->get('firstname'));
107 $person->setLastName($request->get('lastname'));
108 //TODO: email update should normally have a verification step
109 $person->setEmail($request->get('email'));
114 return $this->view($person, Response
::HTTP_CREATED
,
115 ['Location' => $this->generateUrl('show_person',
116 ['id' => $person->getId(),
117 UrlGeneratorInterface
::ABSOLUTE_URL
])]);
122 * path = "/api/person/authenticate",
123 * name = "authenticate_person"
125 * @Rest\View(StatusCode = Response::HTTP_ACCEPTED)
127 public function authenticatePersonAction(Request
$request)
129 $em = $this->getDoctrine()->getManager();
130 $person = $em->getRepository('App:Person')->findOneBy(['email' => $request->get('email')]);
132 if (empty($person)) {
133 return $this->PersonNotFound();
136 if ($request->get('password') != $person->getPassword()) {
137 return $this->PersonWrongPassword();
139 return $this->view($person, Response
::HTTP_ACCEPTED
,
140 ['Location' => $this->generateUrl('show_person',
141 ['id' => $person->getId(),
142 UrlGeneratorInterface
::ABSOLUTE_URL
])]);
147 * @Rest\Get("/api/person/{id}/localisations")
150 public function getLocalisationsAction(Request
$request)
152 //TODO: Check that the authenticated user is allowed to see the localisation
153 $em = $this->getDoctrine()->getManager();
154 $localisations = $em->getRepository('App:Localisation')->findBy(['person' => $request->get('id')]);
156 if (empty($localisations)) {
157 return $this->PersonLocalisationsNotFound();
160 return $localisations;
165 * path = "/api/person/{id}/localisations/fuzzy/{distance}",
166 * name = "person_localisations_fuzzy",
167 * requirements = {"id"="\d+", "distance"="\d+"}
171 public function getLocalisationsFuzzyAction(Request
$request)
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')]);
177 if (empty($localisations)) {
178 return $this->PersonLocalisationsNotFound();
181 if (!$this->chk_distance($request->get('distance'), 200, 500)) {
182 return $this->PersonLocalisationFuzzyWrongDistance();
185 $fuzzy_localisations = array_map(function($item) use ($request) { return $this->randomizeLocation($item, $request->get('distance'), 200, 500); }, $localisations);
187 return $fuzzy_localisations;
190 private function getLastLocalisation($em, $id) {
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)");
195 $query->setParameter('person', $id);
196 $result = $query->getResult();
197 if (!empty($result)) {
203 * @Rest\Get("/api/person/{id}/localisation")
206 public function getLocalisationAction(Request
$request)
208 //TODO: Check that the authenticated user is allowed to see the localisation
209 $em = $this->getDoctrine()->getManager();
211 $localisation = $this->getLastLocalisation($em, $request->get('id'));
213 if (empty($localisation)) {
214 return $this->PersonLocalisationNotFound();
217 return $localisation;
220 private function chk_distance($distance, $min, $max) {
221 if ($distance >= $min && $distance <= $max) {
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();
233 if ($this->chk_distance($distance, $min, $max)) {
234 $r = $distance / 111300;
236 return $this->PersonLocalisationFuzzyWrongDistance();
243 $lng_off = $x / cos(deg2rad($localisation->getLatitude()));
244 $lat_off = $w * sin($t);
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;
255 * path = "/api/person/{id}/localisation/fuzzy/{distance}",
256 * name = "person_localisation_fuzzy",
257 * requirements = {"id"="\d+", "distance"="\d+"}
261 public function getLocalisationFuzzyAction(Request
$request)
263 //TODO: Check that the authenticated user is allowed to see the localisation
264 $em = $this->getDoctrine()->getManager();
266 $localisation = $this->getLastLocalisation($em, $request->get('id'));
268 if (empty($localisation)) {
269 return $this->PersonLocalisationNotFound();
272 return $this->randomizeLocation($localisation, $request->get('distance'), 200, 500);
276 * @Rest\Post("/api/person/{id}/localisation")
277 * @Rest\View(StatusCode = Response::HTTP_CREATED)
279 public function updateLocalisationAction(Request
$request)
281 //TODO: Check that the authenticated user is allowed to update the localisation
282 $em = $this->getDoctrine()->getManager();
284 $person = $em->getRepository('App:Person')->find($request->get('id'));
286 if (empty($person)) {
287 return $this->PersonNotFound();
290 $datetime = new DateTime($request->get('timestamp'));
292 $localisation = new Localisation();
293 $localisation->setPerson($person);
294 $localisation->setTimestamp($datetime);
295 $localisation->setLatitude($request->get('latitude'));
296 $localisation->setLongitude($request->get('longitude'));
298 $em->persist($localisation);
304 * path = "/api/person/{id}",
305 * name = "show_person",
306 * requirements = {"id"="\d+"}
310 public function showPerson(Request
$request)
312 $em = $this->getDoctrine()->getManager();
313 $person = $em->getRepository('App:Person')->find($request->get('id'));
315 if (empty($person)) {
316 return $this->PersonNotFound();
324 * path = "/api/person/{id}/friends",
325 * name = "show_person_friends",
326 * requirements = {"id"="\d+"}
330 public function showPersonFriends(Request
$request)
332 $em = $this->getDoctrine()->getManager();
333 $person = $em->getRepository('App:Person')->find($request->get('id'));
335 if (empty($person)) {
336 return $this->PersonNotFound();
339 return $person->getFriends();
344 * path = "/api/person/{id}/friendswithme",
345 * name = "show_person_friends_with_me",
346 * requirements = {"id"="\d+"}
350 public function showPersonFriendsWithMe(Request
$request)
352 $em = $this->getDoctrine()->getManager();
353 $person = $em->getRepository('App:Person')->find($request->get('id'));
355 if (empty($person)) {
356 return $this->PersonNotFound();
359 $friends_with_me = $person->getFriendsWithMe();
361 return $friends_with_me;
366 * path = "/api/persons",
367 * name = "show_persons"
371 public function showPersons(Request
$request)
373 $em = $this->getDoctrine()->getManager();
374 $persons = $em->getRepository('App:Person')->findAll();
376 if (empty($persons)) {
377 return $this->PersonsNotFound();
385 * path = "/api/person/{id}/online",
386 * name = "set_person_online"
388 * @Rest\View(StatusCode = Response::HTTP_CREATED)
390 public function onlinePersonAction(Request
$request)
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'));
396 if (empty($person)) {
397 return $this->PersonNotFound();
400 $person->setOnline(true);
408 * path = "/api/person/{id}/offline",
409 * name = "set_person_offline"
411 * @Rest\View(StatusCode = Response::HTTP_CREATED)
413 public function offlinePersonAction(Request
$request)
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'));
419 if (empty($person)) {
420 return $this->PersonNotFound();
423 $person->setOnline(false);
431 * path = "/api/person/search",
432 * name = "search_person"
434 * @Rest\QueryParam(name="keyword")
437 public function searchPerson(ParamFetcherInterface
$paramFetcher)
439 $em = $this->getDoctrine()->getManager();
440 $query = $em->createQuery("SELECT DISTINCT p FROM App\Entity\Person p WHERE
441 p.firstname LIKE :keyword OR
442 p.lastname LIKE :keyword OR
443 p.email LIKE :keyword");
444 $query->setParameter('keyword', '%'.$paramFetcher->get('keyword').'%');
445 $persons = $query->getResult();
447 if (empty($persons)) {
448 return $this->PersonsNotFound();
454 private function PersonNotFound() {
455 return View
::create(['message' => 'Person not found'], Response
::HTTP_NOT_FOUND
);
458 private function PersonsNotFound() {
459 return View
::create(['message' => 'Persons not found'], Response
::HTTP_NOT_FOUND
);
462 private function PersonLocalisationNotFound() {
463 return View
::create(['message' => 'Person localisation not found'], Response
::HTTP_NOT_FOUND
);
466 private function PersonLocalisationsNotFound() {
467 return View
::create(['message' => 'Person localisations not found'], Response
::HTTP_NOT_FOUND
);
470 private function PersonWrongPassword() {
471 return View
::create(['message' => 'Supplied password do not match'], Response
::HTTP_UNAUTHORIZED
);
473 private function PersonLocalisationFuzzyWrongDistance() {
474 return View
::create(['message' => 'Distance range do not match'], Response
::HTTP_NOT_ACCEPTABLE
);