2 namespace App\Controller
;
5 use App\Entity\Localisation
;
7 use Symfony\Bundle\FrameworkBundle\Controller\Controller
;
8 use FOS\RestBundle\Controller\FOSRestController
;
9 use FOS\RestBundle\Controller\Annotations
as Rest
;
10 use FOS\RestBundle\View\ViewHandler
;
11 use FOS\RestBundle\View\View
;
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
;
17 class PersonController
extends FOSRestController
21 * path = "/api/person/register",
22 * name = "create_person"
24 * @Rest\View(StatusCode = Response::HTTP_CREATED)
26 public function createPersonAction(Request
$request)
28 $person = new Person();
29 $person->setFirstname($request->get('firstname'));
30 $person->setLastName($request->get('lastname'));
31 //TODO: email creation should normally have a verification step
32 $person->setEmail($request->get('email'));
33 $person->setPassword($request->get('password'));
34 $person->setOnline(false);
36 $em = $this->getDoctrine()->getManager();
38 $em->persist($person);
41 return $this->view($person, Response
::HTTP_CREATED
, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface
::ABSOLUTE_URL
])]);
45 * @Rest\Delete("/api/person/{id}")
46 * @Rest\View(statusCode = Response::HTTP_NO_CONTENT)
48 public function removePersonAction(Request
$request)
50 //TODO: check that the authenticated user have the same id
51 $em = $this->getDoctrine()->getManager();
52 $person = $em->getRepository('App:Person')->find($request->get('id'));
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')]);
57 if (!empty($localisations)) {
58 foreach ($localisations as $localisation) {
59 $em->remove($localisation);
64 if (!empty($friends)) {
65 foreach ($friends as $friend) {
71 if (!empty($friends_with_me)) {
72 foreach ($friends_with_me as $friend) {
78 if (!empty($person)) {
86 * path = "/api/person/{id}",
87 * name = "update_person"
89 * @Rest\View(StatusCode = Response::HTTP_CREATED)
91 public function updatePersonAction(Request
$request)
93 //TODO: check that the authenticated user have the same id
94 $em = $this->getDoctrine()->getManager();
95 $person = $em->getRepository('App:Person')->find($request->get('id'));
98 return $this->PersonNotFound();
101 $person->setFirstName($request->get('firstname'));
102 $person->setLastName($request->get('lastname'));
103 //TODO: email update should normally have a verification step
104 $person->setEmail($request->get('email'));
109 return $this->view($person, Response
::HTTP_CREATED
, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface
::ABSOLUTE_URL
])]);
114 * path = "/api/person/authenticate",
115 * name = "authenticate_person"
117 * @Rest\View(StatusCode = Response::HTTP_ACCEPTED)
119 public function authenticatePersonAction(Request
$request)
121 $em = $this->getDoctrine()->getManager();
122 $person = $em->getRepository('App:Person')->findOneBy(['email' => $request->get('email')]);
124 if (empty($person)) {
125 return $this->PersonNotFound();
128 if ($request->get('password') != $person->getPassword()) {
129 return $this->PersonWrongPassword();
131 return $this->view($person, Response
::HTTP_ACCEPTED
, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface
::ABSOLUTE_URL
])]);
136 * @Rest\Get("/api/person/{id}/localisations")
139 public function getLocalisationsAction(Request
$request)
141 //TODO: Check that the authenticated user is allowed to see the localisation
142 $em = $this->getDoctrine()->getManager();
143 $localisations = $em->getRepository('App:Localisation')->findBy(['person' => $request->get('id')]);
145 if (empty($localisations)) {
146 return $this->PersonLocalisationsNotFound();
149 return $localisations;
154 * path = "/api/person/{id}/localisations/fuzzy/{distance}",
155 * name = "person_localisations_fuzzy",
156 * requirements = {"id"="\d+", "distance"="\d+"}
160 public function getLocalisationsFuzzyAction(Request
$request)
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')]);
166 if (empty($localisations)) {
167 return $this->PersonLocalisationsNotFound();
170 if (!$this->chk_distance($request->get('distance'), 200, 500)) {
171 return $this->PersonLocalisationFuzzyWrongDistance();
174 $fuzzy_localisations = array_map(function($item) use ($request) { return $this->randomizeLocation($item, $request->get('distance'), 200, 500); }, $localisations);
176 return $fuzzy_localisations;
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);
182 $result = $query->getResult();
183 if (!empty($result)) {
189 * @Rest\Get("/api/person/{id}/localisation")
192 public function getLocalisationAction(Request
$request)
194 //TODO: Check that the authenticated user is allowed to see the localisation
195 $em = $this->getDoctrine()->getManager();
197 $localisation = $this->getLastLocalisation($em, $request->get('id'));
199 if (empty($localisation)) {
200 return $this->PersonLocalisationNotFound();
203 return $localisation;
206 private function chk_distance($distance, $min, $max) {
207 if ($distance >= $min && $distance <= $max) {
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();
219 if ($this->chk_distance($distance, $min, $max)) {
220 $r = $distance / 111300;
222 return $this->PersonLocalisationFuzzyWrongDistance();
229 $lng_off = $x / cos(deg2rad($localisation->getLatitude()));
230 $lat_off = $w * sin($t);
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;
241 * path = "/api/person/{id}/localisation/fuzzy/{distance}",
242 * name = "person_localisation_fuzzy",
243 * requirements = {"id"="\d+", "distance"="\d+"}
247 public function getLocalisationFuzzyAction(Request
$request)
249 //TODO: Check that the authenticated user is allowed to see the localisation
250 $em = $this->getDoctrine()->getManager();
252 $localisation = $this->getLastLocalisation($em, $request->get('id'));
254 if (empty($localisation)) {
255 return $this->PersonLocalisationNotFound();
258 return $this->randomizeLocation($localisation, $request->get('distance'), 200, 500);
262 * @Rest\Post("/api/person/{id}/localisation")
263 * @Rest\View(StatusCode = Response::HTTP_CREATED)
265 public function updateLocalisationAction(Request
$request)
267 //TODO: Check that the authenticated user is allowed to update the localisation
268 $em = $this->getDoctrine()->getManager();
270 $person = $em->getRepository('App:Person')->find($request->get('id'));
272 if (empty($person)) {
273 return $this->PersonNotFound();
276 $datetime = new DateTime($request->get('timestamp'));
278 $localisation = new Localisation();
279 $localisation->setPerson($person);
280 $localisation->setTimestamp($datetime);
281 $localisation->setLatitude($request->get('latitude'));
282 $localisation->setLongitude($request->get('longitude'));
284 $em->persist($localisation);
290 * path = "/api/person/{id}",
291 * name = "show_person",
292 * requirements = {"id"="\d+"}
296 public function showPerson(Request
$request)
298 $em = $this->getDoctrine()->getManager();
299 $person = $em->getRepository('App:Person')->find($request->get('id'));
301 if (empty($person)) {
302 return $this->PersonNotFound();
310 * path = "/api/person/{id}/friends",
311 * name = "show_person_friends",
312 * requirements = {"id"="\d+"}
316 public function showPersonFriends(Request
$request)
318 $em = $this->getDoctrine()->getManager();
319 $person = $em->getRepository('App:Person')->find($request->get('id'));
321 if (empty($person)) {
322 return $this->PersonNotFound();
325 return $person->getFriends();
330 * path = "/api/person/{id}/friendswithme",
331 * name = "show_person_friends_with_me",
332 * requirements = {"id"="\d+"}
336 public function showPersonFriendsWithMe(Request
$request)
338 $em = $this->getDoctrine()->getManager();
339 $person = $em->getRepository('App:Person')->find($request->get('id'));
341 if (empty($person)) {
342 return $this->PersonNotFound();
345 $friends_with_me = $person->getFriendsWithMe();
347 return $friends_with_me;
352 * path = "/api/persons",
353 * name = "show_persons"
357 public function showPersons(Request
$request)
359 $em = $this->getDoctrine()->getManager();
360 $persons = $em->getRepository('App:Person')->findAll();
362 if (empty($persons)) {
363 return $this->PersonsNotFound();
371 * path = "/api/person/{id}/online",
372 * name = "set_person_online"
374 * @Rest\View(StatusCode = Response::HTTP_CREATED)
376 public function onlinePersonAction(Request
$request)
378 //TODO: check that the authenticated user have the same id
379 $em = $this->getDoctrine()->getManager();
380 $person = $em->getRepository('App:Person')->find($request->get('id'));
382 if (empty($person)) {
383 return $this->PersonNotFound();
386 $person->setOnline(true);
394 * path = "/api/person/{id}/offline",
395 * name = "set_person_offline"
397 * @Rest\View(StatusCode = Response::HTTP_CREATED)
399 public function offlinePersonAction(Request
$request)
401 //TODO: check that the authenticated user have the same id
402 $em = $this->getDoctrine()->getManager();
403 $person = $em->getRepository('App:Person')->find($request->get('id'));
405 if (empty($person)) {
406 return $this->PersonNotFound();
409 $person->setOnline(false);
417 * path = "/api/person/search",
418 * name = "search_person"
422 public function searchPerson(Request
$request)
424 $em = $this->getDoctrine()->getManager();
425 $query = $em->createQuery("SELECT DISTINCT p FROM App\Entity\Person p WHERE
426 p.firstname LIKE :keyword or
427 p.lastname LIKE :keyword or
428 p.email LIKE :keyword");
429 $query->setParameter('keyword', '%'.$request->get('keyword').'%');
430 $persons = $query->getResult();
432 if (empty($persons)) {
433 return $this->PersonNotFound();
439 private function PersonNotFound() {
440 return View
::create(['message' => 'Person not found'], Response
::HTTP_NOT_FOUND
);
443 private function PersonsNotFound() {
444 return View
::create(['message' => 'Persons not found'], Response
::HTTP_NOT_FOUND
);
447 private function PersonLocalisationNotFound() {
448 return View
::create(['message' => 'Person localisation not found'], Response
::HTTP_NOT_FOUND
);
451 private function PersonLocalisationsNotFound() {
452 return View
::create(['message' => 'Person localisations not found'], Response
::HTTP_NOT_FOUND
);
455 private function PersonWrongPassword() {
456 return View
::create(['message' => 'Supplied password do not match'], Response
::HTTP_UNAUTHORIZED
);
458 private function PersonLocalisationFuzzyWrongDistance() {
459 return View
::create(['message' => 'Distance range do not match'], Response
::HTTP_NOT_ACCEPTABLE
);