GpsCoordinateUtils.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Service\Utils;
  4. use App\ApiResources\Utils\GpsCoordinate;
  5. use App\Tests\Service\Utils\GpsCoordinateUtilsTest;
  6. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  7. use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
  8. use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
  9. use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
  10. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  11. use Symfony\Contracts\HttpClient\HttpClientInterface;
  12. /**
  13. * Class GpsCoordinateSearching : service aidant à la manipulation de l'API OpenStreetMap.
  14. */
  15. class GpsCoordinateUtils
  16. {
  17. private HttpClientInterface $clientOpenStreetMap;
  18. public function __construct(
  19. HttpClientInterface $openstreetmap,
  20. ) {
  21. $this->clientOpenStreetMap = $openstreetmap;
  22. }
  23. /**
  24. * Renvoie un tableau d'adresse existante correspondant à la recherche d'adresse demandée.
  25. *
  26. * @throws \JsonException
  27. * @throws ClientExceptionInterface
  28. * @throws RedirectionExceptionInterface
  29. * @throws ServerExceptionInterface
  30. * @throws TransportExceptionInterface
  31. *
  32. * @see GpsCoordinateUtilsTest::testSearchGpsCoordinates()
  33. */
  34. public function searchGpsCoordinates(?string $street, ?string $cp, ?string $city, ?string $country): mixed
  35. {
  36. try {
  37. $url = sprintf('search?addressdetails=1&format=json&limit=10&%s', $this->prepareQuery($street, $cp, $city, $country));
  38. $response = $this->clientOpenStreetMap->request('GET', $url)->getContent();
  39. } catch (\Exception $e) {
  40. throw new NotFoundHttpException('no_reverse_gps_coordinate', $e, 404);
  41. }
  42. return json_decode($response, true, 512, JSON_THROW_ON_ERROR);
  43. }
  44. /**
  45. * Prépare la query pour l'api de recherche gps.
  46. */
  47. public function prepareQuery(?string $street, ?string $cp, ?string $city, ?string $country): string
  48. {
  49. $query = [
  50. $street ? sprintf('street=%s', $street) : null,
  51. $cp ? sprintf('postalcode=%s', $cp) : null,
  52. $city ? sprintf('city=%s', $city) : null,
  53. $country ? sprintf('country=%s', $country) : null,
  54. ];
  55. return implode('&', array_filter($query));
  56. }
  57. /**
  58. * Renvoi l'adresse correspondant à la latitude et longitude demandée.
  59. *
  60. * @throws ClientExceptionInterface
  61. * @throws RedirectionExceptionInterface
  62. * @throws ServerExceptionInterface
  63. * @throws TransportExceptionInterface
  64. * @throws \JsonException
  65. *
  66. * @see GpsCoordinateUtilsTest::testReverseGpsCoordinates()
  67. */
  68. public function reverseGpsCoordinates(float $latitude, float $longitude): mixed
  69. {
  70. try {
  71. $url = sprintf('reverse?addressdetails=1&format=json&lat=%s&lon=%s', $latitude, $longitude);
  72. $response = $this->clientOpenStreetMap->request('GET', $url)->getContent();
  73. } catch (\Exception $e) {
  74. throw new NotFoundHttpException('no_reverse_gps_coordinate', $e, 404);
  75. }
  76. return json_decode($response, true, 512, JSON_THROW_ON_ERROR);
  77. }
  78. /**
  79. * Transforme une réponse d'API en ressource GpsCoordinate.
  80. *
  81. * @param mixed[] $gpsApiResponse
  82. *
  83. * @see GpsCoordinateUtilsTest::testCreateGpsCoordinate()
  84. */
  85. public function createGpsCoordinate(array $gpsApiResponse): GpsCoordinate
  86. {
  87. if (!isset($gpsApiResponse['address']) || !is_array($gpsApiResponse['address'])) {
  88. throw new NotFoundHttpException('No address found for the given GPS coordinates.', null, 404);
  89. }
  90. $address = $this->transformAddress($gpsApiResponse['address']);
  91. $gpsCoordinate = new GpsCoordinate();
  92. $gpsCoordinate
  93. ->setLatitude((float) $gpsApiResponse['lat'])
  94. ->setLongitude((float) $gpsApiResponse['lon'])
  95. ->setCity($address['city'] ?? null)
  96. ->setCp($address['cp'] ?? null)
  97. ->setStreetAddress($address['streetAddress'] ?? null)
  98. ->setStreetAddressSecond($address['streetAddressSecond'] ?? null);
  99. return $gpsCoordinate;
  100. }
  101. /**
  102. * Permet de faire correspondre le bloc adresse renvoyé par l'API avec des éléments plus communs.
  103. *
  104. * @param list<string> $address
  105. *
  106. * @return array<string, string|null>
  107. */
  108. public function transformAddress(array $address): array
  109. {
  110. $addressTransformed['streetAddress'] = array_key_exists('road', $address) ? $address['road'] : (array_key_exists('hamlet', $address) ? $address['hamlet'] : null);
  111. $addressTransformed['streetAddressSecond'] = array_key_exists('road', $address) && array_key_exists('hamlet', $address) ? $address['hamlet'] : null;
  112. $addressTransformed['city'] = array_key_exists('town', $address) ? $address['town'] : (array_key_exists('village', $address) ? $address['village'] : null);
  113. $addressTransformed['cp'] = array_key_exists('postcode', $address) ? $address['postcode'] : null;
  114. return $addressTransformed;
  115. }
  116. }