You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
3.2 KiB

  1. <?php
  2. namespace p3k;
  3. class Geocoder {
  4. public static function adrFromLocation($lat, $lng) {
  5. $response = self::_reverse($lat, $lng);
  6. if(!$response)
  7. return false;
  8. if(!property_exists($response, 'address'))
  9. return false;
  10. $address = $response->address;
  11. $result = new geocode\Result;
  12. $result->latitude = $lat;
  13. $result->longitude = $lng;
  14. if(property_exists($address, 'Postal'))
  15. $result->postalCode = $address->Postal;
  16. if(property_exists($address, 'Region'))
  17. $result->regionName = $address->Region;
  18. if(property_exists($address, 'City'))
  19. $result->localityName = $address->City;
  20. elseif(property_exists($address, 'Subregion'))
  21. $result->localityName = $address->Subregion;
  22. elseif(property_exists($address, 'Neighborhood'))
  23. $result->localityName = $address->Neighborhood;
  24. if(property_exists($address, 'CountryCode'))
  25. $result->countryName = $address->CountryCode;
  26. return $result;
  27. }
  28. public static function geocode($input) {
  29. $response = self::_geocode($input);
  30. if(!$response || count($response->locations) == 0)
  31. return false;
  32. $location = $response->locations[0];
  33. $attributes = $location->feature->attributes;
  34. $geometry = $location->feature->geometry;
  35. $result = new geocode\Result;
  36. if($geometry) {
  37. $result->latitude = $geometry->y;
  38. $result->longitude = $geometry->x;
  39. }
  40. if($attributes->City)
  41. $result->localityName = $attributes->City;
  42. if($attributes->Region)
  43. $result->regionName = $attributes->Region;
  44. if($attributes->Country)
  45. $result->countryName = $attributes->Country;
  46. if($attributes->Postal) {
  47. $result->postalCode = $attributes->Postal;
  48. } else {
  49. // If no postal code is returned, but there was coordinates, then reverse geocode to find the postal code
  50. if($geometry) {
  51. $rev = self::_reverse($result->latitude, $result->longitude);
  52. if($rev && property_exists($rev->address, 'Postal')) {
  53. $result->postalCode = $rev->address->Postal;
  54. }
  55. }
  56. }
  57. if($location->name)
  58. $result->fullAddress = $location->name;
  59. return $result;
  60. }
  61. private static function _reverse($lat, $lng) {
  62. $ch = curl_init();
  63. curl_setopt($ch, CURLOPT_URL, 'http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode?location='.$lng.'%2C'.$lat.'&outSR=4326&f=json&distance=10000');
  64. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  65. // curl_setopt($ch, CURLOPT_USERAGENT, '');
  66. curl_setopt($ch, CURLOPT_TIMEOUT, 5);
  67. $result = curl_exec($ch);
  68. if($result == FALSE)
  69. return FALSE;
  70. return json_decode($result);
  71. }
  72. private static function _geocode($input) {
  73. $ch = curl_init();
  74. $params = [
  75. 'f' => 'json',
  76. 'outSR' => 4326,
  77. 'text' => $input,
  78. 'outFields' => 'City,Region,Country,Postal',
  79. ];
  80. curl_setopt($ch, CURLOPT_URL, 'http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find?' . http_build_query($params));
  81. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  82. // curl_setopt($ch, CURLOPT_USERAGENT, '');
  83. curl_setopt($ch, CURLOPT_TIMEOUT, 5);
  84. $result = curl_exec($ch);
  85. if($result == FALSE)
  86. return FALSE;
  87. return json_decode($result);
  88. }
  89. }