setFirstname($request->get('firstname')); $person->setLastName($request->get('lastname')); //TODO: email creation should normally have a verification step $person->setEmail($request->get('email')); $person->setPassword($request->get('password')); $person->setOnline(false); $em = $this->getDoctrine()->getManager(); $em->persist($person); $em->flush(); return $this->view($person, Response::HTTP_CREATED, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]); } /** * @Rest\Delete("/api/person/{id}") * @Rest\View(statusCode = Response::HTTP_NO_CONTENT) */ public function removePersonAction(Request $request) { //TODO: check that the authenticated user have the same id $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->find($request->get('id')); $friends = $em->getRepository('App:Friendship')->findBy(['person' => $request->get('id')]); $friends_with_me = $em->getRepository('App:Friendship')->findBy(['friend' => $request->get('id')]); $localisations = $em->getRepository('App:Localisation')->findBy(['person' => $request->get('id')]); if (!empty($localisations)) { foreach ($localisations as $localisation) { $em->remove($localisation); } $em->flush(); } if (!empty($friends)) { foreach ($friends as $friend) { $em->remove($friend); } $em->flush(); } if (!empty($friends_with_me)) { foreach ($friends_with_me as $friend) { $em->remove($friend); } $em->flush(); } if (!empty($person)) { $em->remove($person); $em->flush(); } } /** * @Rest\Put( * path = "/api/person/{id}", * name = "update_person" * ) * @Rest\View(StatusCode = Response::HTTP_CREATED) */ public function updatePersonAction(Request $request) { //TODO: check that the authenticated user have the same id $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->find($request->get('id')); if (empty($person)) { return $this->PersonNotFound(); } $person->setFirstName($request->get('firstname')); $person->setLastName($request->get('lastname')); //TODO: email update should normally have a verification step $person->setEmail($request->get('email')); $em->merge($person); $em->flush(); return $this->view($person, Response::HTTP_CREATED, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]); } /** * @Rest\Post( * path = "/api/person/authenticate", * name = "authenticate_person" * ) * @Rest\View(StatusCode = Response::HTTP_ACCEPTED) */ public function authenticatePersonAction(Request $request) { $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->findOneBy(['email' => $request->get('email')]); if (empty($person)) { return $this->PersonNotFound(); } if ($request->get('password') != $person->getPassword()) { return $this->PersonWrongPassword(); } else { return $this->view($person, Response::HTTP_ACCEPTED, ['Location' => $this->generateUrl('show_person', ['id' => $person->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]); } } /** * @Rest\Get("/api/person/{id}/localisations") * @Rest\View() */ public function getLocalisationsAction(Request $request) { //TODO: Check that the authenticated user is allowed to see the localisation $em = $this->getDoctrine()->getManager(); $localisations = $em->getRepository('App:Localisation')->findBy(['person' => $request->get('id')]); if (empty($localisations)) { return $this->PersonLocalisationsNotFound(); } return $localisations; } /** * @Rest\Get( * path = "/api/person/{id}/localisations/fuzzy/{distance}", * name = "person_localisations_fuzzy", * requirements = {"id"="\d+", "distance"="\d+"} * ) * @Rest\View() */ public function getLocalisationsFuzzyAction(Request $request) { //TODO: Check that the authenticated user is allowed to see the localisation $em = $this->getDoctrine()->getManager(); $localisations = $em->getRepository('App:Localisation')->findBy(['person' => $request->get('id')]); if (empty($localisations)) { return $this->PersonLocalisationsNotFound(); } if (!$this->chk_distance($request->get('distance'), 200, 500)) { return $this->PersonLocalisationFuzzyWrongDistance(); } $fuzzy_localisations = array_map(function($item) use ($request) { return $this->randomizeLocation($item, $request->get('distance'), 200, 500); }, $localisations); return $fuzzy_localisations; } private function getLastLocalisation($em, $id) { $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)"); $query->setParameter('person', $id); $result = $query->getResult(); if (!empty($result)) { return $result[0]; } } /** * @Rest\Get("/api/person/{id}/localisation") * @Rest\View() */ public function getLocalisationAction(Request $request) { //TODO: Check that the authenticated user is allowed to see the localisation $em = $this->getDoctrine()->getManager(); $localisation = $this->getLastLocalisation($em, $request->get('id')); if (empty($localisation)) { return $this->PersonLocalisationNotFound(); } return $localisation; } private function chk_distance($distance, $min, $max) { if ($distance >= $min && $distance <= $max) { return true; } else { return false; } } private function randomizeLocation($localisation, $distance, $min, $max) { // Generate random float in [0, 1[, [0, 1) $u = rand(0, getrandmax() - 1) / getrandmax(); $v = rand(0, getrandmax() - 1) / getrandmax(); if ($this->chk_distance($distance, $min, $max)) { $r = $distance / 111300; } else { return $this->PersonLocalisationFuzzyWrongDistance(); } $w = $r * sqrt($u); $t = 2 * pi() * $v; $x = $w * cos($t); $lng_off = $x / cos(deg2rad($localisation->getLatitude())); $lat_off = $w * sin($t); $fuzzy_localisation = new Localisation(); $fuzzy_localisation->setTimestamp($localisation->getTimestamp()); $fuzzy_localisation->setLatitude($localisation->getLatitude() + $lat_off); $fuzzy_localisation->setLongitude($localisation->getLongitude() + $lng_off); return $fuzzy_localisation; } /** * @Rest\Get( * path = "/api/person/{id}/localisation/fuzzy/{distance}", * name = "person_localisation_fuzzy", * requirements = {"id"="\d+", "distance"="\d+"} * ) * @Rest\View() */ public function getLocalisationFuzzyAction(Request $request) { //TODO: Check that the authenticated user is allowed to see the localisation $em = $this->getDoctrine()->getManager(); $localisation = $this->getLastLocalisation($em, $request->get('id')); if (empty($localisation)) { return $this->PersonLocalisationNotFound(); } return $this->randomizeLocation($localisation, $request->get('distance'), 200, 500); } /** * @Rest\Post("/api/person/{id}/localisation") * @Rest\View(StatusCode = Response::HTTP_CREATED) */ public function updateLocalisationAction(Request $request) { //TODO: Check that the authenticated user is allowed to update the localisation $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->find($request->get('id')); if (empty($person)) { return $this->PersonNotFound(); } $datetime = new DateTime($request->get('timestamp')); $localisation = new Localisation(); $localisation->setPerson($person); $localisation->setTimestamp($datetime); $localisation->setLatitude($request->get('latitude')); $localisation->setLongitude($request->get('longitude')); $em->persist($localisation); $em->flush(); } /** * @Rest\Get( * path = "/api/person/{id}", * name = "show_person", * requirements = {"id"="\d+"} * ) * @Rest\View() */ public function showPerson(Request $request) { $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->find($request->get('id')); if (empty($person)) { return $this->PersonNotFound(); } return $person; } /** * @Rest\Get( * path = "/api/person/{id}/friends", * name = "show_person_friends", * requirements = {"id"="\d+"} * ) * @Rest\View() */ public function showPersonFriends(Request $request) { $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->find($request->get('id')); if (empty($person)) { return $this->PersonNotFound(); } return $person->getFriends(); } /** * @Rest\Get( * path = "/api/person/{id}/friendswithme", * name = "show_person_friends_with_me", * requirements = {"id"="\d+"} * ) * @Rest\View() */ public function showPersonFriendsWithMe(Request $request) { $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->find($request->get('id')); if (empty($person)) { return $this->PersonNotFound(); } $friends_with_me = $person->getFriendsWithMe(); return $friends_with_me; } /** * @Rest\Get( * path = "/api/persons", * name = "show_persons" * ) * @Rest\View() */ public function showPersons(Request $request) { $em = $this->getDoctrine()->getManager(); $persons = $em->getRepository('App:Person')->findAll(); if (empty($persons)) { return $this->PersonsNotFound(); } return $persons; } /** * @Rest\Put( * path = "/api/person/{id}/online", * name = "set_person_online" * ) * @Rest\View(StatusCode = Response::HTTP_CREATED) */ public function onlinePersonAction(Request $request) { //TODO: check that the authenticated user have the same id $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->find($request->get('id')); if (empty($person)) { return $this->PersonNotFound(); } $person->setOnline(true); $em->merge($person); $em->flush(); } /** * @Rest\Put( * path = "/api/person/{id}/offline", * name = "set_person_offline" * ) * @Rest\View(StatusCode = Response::HTTP_CREATED) */ public function offlinePersonAction(Request $request) { //TODO: check that the authenticated user have the same id $em = $this->getDoctrine()->getManager(); $person = $em->getRepository('App:Person')->find($request->get('id')); if (empty($person)) { return $this->PersonNotFound(); } $person->setOnline(false); $em->merge($person); $em->flush(); } /** * @Rest\Get( * path = "/api/person/search", * name = "search_person" * ) * @Rest\QueryParam(name="keyword") * @Rest\View() */ public function searchPerson(ParamFetcherInterface $paramFetcher) { $em = $this->getDoctrine()->getManager(); $query = $em->createQuery("SELECT DISTINCT p FROM App\Entity\Person p WHERE p.firstname LIKE :keyword OR p.lastname LIKE :keyword OR p.email LIKE :keyword"); $query->setParameter('keyword', '%'.$paramFetcher->get('keyword').'%'); $persons = $query->getResult(); if (empty($persons)) { return $this->PersonsNotFound(); } return $persons; } private function PersonNotFound() { return View::create(['message' => 'Person not found'], Response::HTTP_NOT_FOUND); } private function PersonsNotFound() { return View::create(['message' => 'Persons not found'], Response::HTTP_NOT_FOUND); } private function PersonLocalisationNotFound() { return View::create(['message' => 'Person localisation not found'], Response::HTTP_NOT_FOUND); } private function PersonLocalisationsNotFound() { return View::create(['message' => 'Person localisations not found'], Response::HTTP_NOT_FOUND); } private function PersonWrongPassword() { return View::create(['message' => 'Supplied password do not match'], Response::HTTP_UNAUTHORIZED); } private function PersonLocalisationFuzzyWrongDistance() { return View::create(['message' => 'Distance range do not match'], Response::HTTP_NOT_ACCEPTABLE); } }