clientOpenStreetMap = $openstreetmap; } /** * Renvoie un tableau d'adresse existante correspondant à la recherche d'adresse demandée. * * @throws \JsonException * @throws ClientExceptionInterface * @throws RedirectionExceptionInterface * @throws ServerExceptionInterface * @throws TransportExceptionInterface * * @see GpsCoordinateUtilsTest::testSearchGpsCoordinates() */ public function searchGpsCoordinates(?string $street, ?string $cp, ?string $city, ?string $country): mixed { try { $url = sprintf('search?addressdetails=1&format=json&limit=10&%s', $this->prepareQuery($street, $cp, $city, $country)); $response = $this->clientOpenStreetMap->request('GET', $url)->getContent(); } catch (\Exception $e) { throw new NotFoundHttpException('no_reverse_gps_coordinate', $e, 404); } return json_decode($response, true, 512, JSON_THROW_ON_ERROR); } /** * Prépare la query pour l'api de recherche gps. */ public function prepareQuery(?string $street, ?string $cp, ?string $city, ?string $country): string { $query = [ $street ? sprintf('street=%s', $street) : null, $cp ? sprintf('postalcode=%s', $cp) : null, $city ? sprintf('city=%s', $city) : null, $country ? sprintf('country=%s', $country) : null, ]; return implode('&', array_filter($query)); } /** * Renvoi l'adresse correspondant à la latitude et longitude demandée. * * @throws ClientExceptionInterface * @throws RedirectionExceptionInterface * @throws ServerExceptionInterface * @throws TransportExceptionInterface * @throws \JsonException * * @see GpsCoordinateUtilsTest::testReverseGpsCoordinates() */ public function reverseGpsCoordinates(float $latitude, float $longitude): mixed { try { $url = sprintf('reverse?addressdetails=1&format=json&lat=%s&lon=%s', $latitude, $longitude); $response = $this->clientOpenStreetMap->request('GET', $url)->getContent(); } catch (\Exception $e) { throw new NotFoundHttpException('no_reverse_gps_coordinate', $e, 404); } return json_decode($response, true, 512, JSON_THROW_ON_ERROR); } /** * Transforme une réponse d'API en ressource GpsCoordinate. * * @param mixed[] $gpsApiResponse * * @see GpsCoordinateUtilsTest::testCreateGpsCoordinate() */ public function createGpsCoordinate(array $gpsApiResponse): GpsCoordinate { if (!isset($gpsApiResponse['address']) || !is_array($gpsApiResponse['address'])) { throw new NotFoundHttpException('No address found for the given GPS coordinates.', null, 404); } $address = $this->transformAddress($gpsApiResponse['address']); $gpsCoordinate = new GpsCoordinate(); $gpsCoordinate ->setLatitude((float) $gpsApiResponse['lat']) ->setLongitude((float) $gpsApiResponse['lon']) ->setCity($address['city'] ?? null) ->setCp($address['cp'] ?? null) ->setStreetAddress($address['streetAddress'] ?? null) ->setStreetAddressSecond($address['streetAddressSecond'] ?? null); return $gpsCoordinate; } /** * Permet de faire correspondre le bloc adresse renvoyé par l'API avec des éléments plus communs. * * @param list $address * * @return array */ public function transformAddress(array $address): array { $addressTransformed['streetAddress'] = array_key_exists('road', $address) ? $address['road'] : (array_key_exists('hamlet', $address) ? $address['hamlet'] : null); $addressTransformed['streetAddressSecond'] = array_key_exists('road', $address) && array_key_exists('hamlet', $address) ? $address['hamlet'] : null; $addressTransformed['city'] = array_key_exists('town', $address) ? $address['town'] : (array_key_exists('village', $address) ? $address['village'] : null); $addressTransformed['cp'] = array_key_exists('postcode', $address) ? $address['postcode'] : null; return $addressTransformed; } }