GeoMashup
[ class tree: GeoMashup ] [ index: GeoMashup ] [ all elements ]

Source for file geo-mashup-geocoders.php

Documentation is available at geo-mashup-geocoders.php

  1. <?php
  2. /**
  3.  * Geo Mashup Geocoder
  4.  *
  5.  * @since 1.4
  6.  * @package GeoMashup
  7.  * @subpackage Geocoder
  8.  */
  9.  
  10.  
  11. if class_exists'GeoMashupHttpGeocoder' ) ) {
  12. /**
  13.  * The Geo Mashup Http Geocoder base class.
  14.  *
  15.  * @since 1.4
  16.  */
  17. abstract class GeoMashupHttpGeocoder {
  18.     /**
  19.      * WP_Http instance
  20.      * @since 1.4
  21.      * @var float 
  22.      */
  23.     protected $http;
  24.     /**
  25.      * Parameters to use with http requests.
  26.      * @var array 
  27.      */
  28.     public $request_params;
  29.     /**
  30.      * Language code.
  31.      * @since 1.4
  32.      * @var string 
  33.      */
  34.     public $language;
  35.     /**
  36.      * Maximum number of results
  37.      * @var int 
  38.      */
  39.     public $max_results;
  40.  
  41.     /**
  42.      * Constructor
  43.      *
  44.      * @param string $args Optional array of arguments:
  45.      *          language - two digit language code, defaults to blog language
  46.      *          max_results - maximum number of results to fetch
  47.      *          default http params - array of WP_Http request parameters, including timeout
  48.      */
  49.     public function  __construct$args array() ) {
  50.         $defaults array(
  51.             'language' => get_locale(),
  52.             'max_results' => 10,
  53.             'request_params' => array'timeout' => 3.0 )
  54.         );
  55.         $args wp_parse_args$args$defaults );
  56.         extract$args );
  57.         $this->language = GeoMashupDB::primary_language_code$language );
  58.         $this->max_results = absint$max_results );
  59.         $this->request_params = $request_params;
  60.         if!class_exists'WP_Http' ) )
  61.             include_onceABSPATH WPINC'/class-http.php' );
  62.         $this->http = new WP_Http();
  63.     }
  64.  
  65.     /**
  66.      * Look up locations from a text query, like an address or place name.
  67.      *
  68.      * @since 1.4
  69.      *
  70.      * @param string $query Text query.
  71.      * @return array|WP_ErrorArray of search result locations.
  72.      */
  73.     abstract public function geocode$query );
  74.  
  75.     /**
  76.      * Look up additional location information from coordinates.
  77.      *
  78.      * Resulting locations have as much address information as
  79.      * possible filled in. Most services return the nearest match
  80.      * first, and some return only one.
  81.      *
  82.      * @since 1.4
  83.      *
  84.      * @param float $lat Latitude
  85.      * @param float $lng Longitude
  86.      * @return array|WP_ErrorArray of search result locations.
  87.      */
  88.     abstract public function reverse_geocode$lat$lng );
  89. }
  90.  
  91. /**
  92.  * HTTP geocoder using the geonames web services.
  93.  *
  94.  * Includes an additional method for looking up administrative area names.
  95.  *
  96.  * @since 1.4
  97.  */
  98.     /**
  99.      * The application username to include in geonames API requests.
  100.      * @var string 
  101.      */
  102.     private $geonames_username;
  103.  
  104.     public function  __construct$args array() ) {
  105.         global $geo_mashup_options;
  106.         parent::__construct$args );
  107.         $this->geonames_username $geo_mashup_options->get'overall''geonames_username' );
  108.     }
  109.  
  110.     public function geocode$query {
  111.         $url 'http://api.geonames.org/searchJSON?username=' $this->geonames_username .
  112.                 '&maxRows=' .  $this->max_results . '&q=' .  urlencodeutf8_encode$query ) ) .
  113.                 '&lang=' $this->language;
  114.  
  115.         $response $this->http->get$url$this->request_params );
  116.         if is_wp_error$response ) )
  117.             return $response;
  118.  
  119.         $status $response['response']['code'];
  120.         if '200' != $status 
  121.             return new WP_Error'geocoder_http_request_failed'$status ': ' $response['response']['message']$response );
  122.  
  123.         $data json_decode$response['body');
  124.         if empty$data or == $data->totalResultsCount 
  125.             return array();
  126.  
  127.         $locations array();
  128.         foreach$data->geonames as $geoname {
  129.             $location GeoMashupDB::blank_location();
  130.             $location->lat $geoname->lat;
  131.             $location->lng $geoname->lng;
  132.             if !empty$geoname->countryCode ) )
  133.                 $location->country_code $geoname->countryCode;
  134.             if !empty$geoname->adminCode1) )
  135.                 $location->admin_code $geoname->adminCode1;
  136.             if !empty$geoname->fcode and 'PPL' == substr$geoname->fcode0) )
  137.                 $location->locality_name $geoname->name;
  138.             $locations[$location;
  139.         }
  140.  
  141.         return $locations;
  142.     }
  143.  
  144.     public function reverse_geocode$lat$lng {
  145.         global $geo_mashup_options;
  146.  
  147.         if !is_numeric$lat or !is_numeric$lng ) ) // Bad Request
  148.             return new WP_Error'bad_reverse_geocode_request'__'Reverse geocoding requires numeric coordinates.''GeoMashup' ) );
  149.  
  150.         $status null;
  151.         $url 'http://api.geonames.org/countrySubdivisionJSON?style=FULL&username=' $this->geonames_username 
  152.                 '&lat=' urlencode$lat .  '&lng=' urlencode$lng );
  153.         $response $this->http->get$url$this->request_params );
  154.         if is_wp_error$response ) )
  155.             return $response;
  156.  
  157.         $status $response['response']['code'];
  158.         $data json_decode$response['body');
  159.         if empty$data or !empty$data->status ) )
  160.             return array();
  161.         $location GeoMashupDB::blank_location();
  162.         $location->lat $lat;
  163.         $location->lng $lng;
  164.         if !empty$data->countryCode ) )
  165.             $location->country_code $data->countryCode;
  166.         if !empty$data->adminCode1 ) )
  167.             $location->admin_code $data->adminCode1;
  168.         
  169.         // Look up more things, postal code, locality or address in US
  170.         if 'US' == $location->country_code and GeoMashupDB::are_any_location_fields_empty$locationarray'address''locality_name''postal_code' ) ) ) {
  171.             $url 'http://api.geonames.org/findNearestAddressJSON?style=FULL&username=' $this->geonames_username 
  172.                     '&lat=' urlencode$lat .  '&lng=' urlencode$lat );
  173.             $response $this->http->get$url$this->request_params );
  174.  
  175.             if !is_wp_error$response ) ) {
  176.                 $status $response['response']['code'];
  177.                 $data json_decode$response['body');
  178.                 if empty$data->address ) ) {
  179.                     $address_parts array();
  180.                     if empty$data->address->street ) ) {
  181.                         $address_parts[empty$data->address->streetNumber '' $data->address->streetNumber ' ' .
  182.                             $data->address->street;
  183.                     }
  184.                     if empty$data->address->adminName1 ) ) {
  185.                         $address_parts[$data->address->adminName1;
  186.                     }
  187.                     if empty$data->address->postalcode ) ) {
  188.                         $address_parts[$data->address->postalcode;
  189.                     }
  190.                     $address_parts[$data->address->countryCode;
  191.                     $location->address implode', '$address_parts );
  192.                     $location->locality_name $data->address->placename;
  193.                     $location->postal_code $data->address->postalcode;
  194.                 }
  195.             }
  196.         }
  197.         if (  GeoMashupDB::are_any_location_fields_empty$locationarray'address''locality_name''postal_code' ) ) ) {
  198.             // Just look for a postal code
  199.             $url 'http://api.geonames.org/findNearbyPostalCodesJSON?username=' $this->geonames_username 
  200.                     '&maxRows=1&lat=' urlencode$lat .  '&lng=' urlencode$lng );
  201.             $response $this->http->get$url$this->request_params );
  202.  
  203.             if !is_wp_error$response ) ) {
  204.                 $status $response['response']['code'];
  205.                 $data json_decode$response['body');
  206.                 if empty$data->postalCodes ) ) {
  207.                     $postal_code $data->postalCodes[0];
  208.                     $admin_name empty$postal_code->adminName1 '' $postal_code->adminName1 );
  209.                     $location->address $postal_code->placeName ', ' .
  210.                         $admin_name ', ' $postal_code->postalCode ', ' .
  211.                         $postal_code->countryCode;
  212.                     $location->locality_name $postal_code->placeName;
  213.                     $location->postal_code $postal_code->postalCode;
  214.                 }
  215.             }
  216.         }
  217.         return array$location );
  218.     }
  219.  
  220.     /**
  221.      * Use the Geonames web service to look up an administrative name.
  222.      *
  223.      * @since 1.4
  224.      *
  225.      * @param string $country_code 
  226.      * @param string $admin_code Admin area name to look up. If empty, look up the country name.
  227.      * @return string|WP_ErrorThe administrative name.
  228.      */
  229.     public function get_administrative_name$country_code$admin_code '' {
  230.  
  231.         if empty$admin_code ) ) {
  232.             // Look up a country name
  233.             $country_info_url 'http://api.geonames.org/countryInfoJSON?username=' $this->geonames_username .
  234.                     '&country=' urlencode$country_code .  '&lang=' urlencode$this->language );
  235.             $country_info_response $this->http->get$country_info_url$this->request_params );
  236.             if is_wp_error$country_info_response ) )
  237.                 return $country_info_response;
  238.             
  239.             $status $country_info_response['response']['code'];
  240.             if '200' != $status )
  241.                 return new WP_Error'geocoder_http_request_failed'$status ': ' $country_info_response['response']['message']$country_info_response );
  242.  
  243.             $data json_decode$country_info_response['body');
  244.             if empty$data->geonames ) )
  245.                 return '';
  246.             $country_name $data->geonames[0]->countryName;
  247.             $country_id $data->geonames[0]->geonameId;
  248.             if !empty$country_name ) ) 
  249.                 GeoMashupDB::cache_administrative_name$country_code''$this->language$country_name$country_id );
  250.             return $country_name;
  251.         else {
  252.             // Look up an admin name
  253.             $admin_search_url 'http://api.geonames.org/searchJSON?maxRows=1&style=SHORT&featureCode=ADM1&username=' $this->geonames_username 
  254.                     '&country=' .  urlencode$country_code '&adminCode1=' urlencode$admin_code );
  255.             $admin_search_response $this->http->get$admin_search_url$this->request_params );
  256.             if is_wp_error$admin_search_response ) )
  257.                 return $admin_search_response;
  258.  
  259.             $status $admin_search_response['response']['code'];
  260.             if '200' != $status )
  261.                 return new WP_Error'geocoder_http_request_failed'$status ': ' $admin_search_response['response']['message']$admin_search_response );
  262.  
  263.             $data json_decode$admin_search_response['body');
  264.             if empty$data or == $data->totalResultsCount )
  265.                 return '';
  266.             $admin_name $data->geonames[0]->name;
  267.             $admin_id $data->geonames[0]->geonameId;
  268.             if !empty$admin_name ) ) 
  269.                 GeoMashupDB::cache_administrative_name$country_code$admin_code$this->language$admin_name$admin_id );
  270.             return $admin_name;
  271.         }
  272.         return '';
  273.     }
  274. }
  275.  
  276. /**
  277.  * HTTP geocoder using the Google geocoding web service
  278.  *
  279.  * @since 1.4
  280.  */
  281.  
  282.     public function  __construct$args array() ) {
  283.         parent::__construct$args );
  284.     }
  285.  
  286.     /**
  287.      * Do regular or reverse geocoding
  288.      *
  289.      * @since 1.4
  290.      *
  291.      * @param string $query_type 'address' or 'latlng'
  292.      * @param string $query 
  293.      * @return array Locations.
  294.      */
  295.     private function query$query_type$query {
  296.         $google_geocode_url 'http://maps.google.com/maps/api/geocode/json?sensor=false&' $query_type '=' .
  297.             urlencodeutf8_encode$query ) ) '&language=' $this->language;
  298.  
  299.         $response $this->http->get$google_geocode_url$this->request_params );
  300.         if is_wp_error$response ) )
  301.             return $response;
  302.  
  303.         $status $response['response']['code'];
  304.         if '200' != $status )
  305.             return new WP_Error'geocoder_http_request_failed'$status ': ' $response['response']['message']$response );
  306.  
  307.         $data json_decode$response['body');
  308.         if 'ZERO_RESULTS' == $data->status )
  309.             return array();
  310.         if 'OK' != $data->status // status of OVER_QUERY_LIMIT, REQUEST_DENIED, INVALID_REQUEST, etc.
  311.             return new WP_Error'geocoder_request_failed'sprintf__'The geocoding request failed with status %s.''GeoMashup' )$status)$data );
  312.  
  313.         if count$data->results $this->max_results )
  314.             $data->results array_slice$data->results0$this->max_results );
  315.  
  316.         $locations array();
  317.         foreach$data->results as $result {
  318.             $location GeoMashupDB::blank_location();
  319.             $location->lat $result->geometry->location->lat;
  320.             $location->lng $result->geometry->location->lng;
  321.             $location->address $result->formatted_address;
  322.             if empty$result->address_components ) ) {
  323.                 foreach$result->address_components as $component {
  324.                     if in_array'country'$component->types ) )
  325.                         $location->country_code $component->short_name;
  326.                     if in_array'administrative_area_level_1'$component->types ) )
  327.                         $location->admin_code $component->short_name;
  328.                     if in_array'administrative_area_level_2'$component->types ) )
  329.                         $location->sub_admin_code $component->short_name;
  330.                     if in_array'postal_code'$component->types ) )
  331.                         $location->postal_code $component->short_name;
  332.                     if in_array'locality'$component->types ) )
  333.                         $location->locality_name $component->short_name;
  334.                 }
  335.             }
  336.             $locations[$location;
  337.         }
  338.         return $locations;
  339.  
  340.     }
  341.  
  342.     public function geocode$query {
  343.         return $this->query'address'$query );
  344.     }
  345.  
  346.     public function reverse_geocode$lat$lng {
  347.  
  348.         if !is_numeric$lat or !is_numeric$lng ) ) // Bad Request
  349.             return new WP_Error'bad_reverse_geocode_request'__'Reverse geocoding requires numeric coordinates.''GeoMashup' ) );
  350.  
  351.         return $this->query'latlng'$lat ',' $lng );
  352.     }
  353. }
  354.  
  355. /**
  356.  * HTTP geocoder using the nominatim web service.
  357.  *
  358.  * @since 1.4
  359.  */
  360.  
  361.     public function  __construct$args array() ) {
  362.         parent::__construct$args );
  363.     }
  364.  
  365.     public function geocode$query {
  366.  
  367.         $geocode_url 'http://nominatim.openstreetmap.org/search?format=json&polygon=0&addressdetails=1&q=' .
  368.             urlencodeutf8_encode$query ) ) '&accept-language=' $this->language .
  369.             '&email=' urlencodeget_option'admin_email' ) );
  370.  
  371.         $response $this->http->get$geocode_url$this->request_params );
  372.         if is_wp_error$response ) )
  373.             return $response;
  374.  
  375.         $status $response['response']['code'];
  376.         if '200' != $status )
  377.             return new WP_Error'geocoder_http_request_failed'$status ': ' $response['response']['message']$response );
  378.  
  379.         $data json_decode$response['body');
  380.         if empty$data ) )
  381.             return array();
  382.  
  383.         if count$data $this->max_results )
  384.             $data array_slice$data0$this->max_results );
  385.  
  386.         $locations array();
  387.         foreach$data as $result {
  388.             $location GeoMashupDB::blank_location();
  389.             $location->lat $result->lat;
  390.             $location->lng $result->lon;
  391.             $location->address $result->display_name;
  392.             if !empty$result->address ) ) {
  393.                 if !empty$first_result->address->country_code ) )
  394.                     $location->country_code strtoupper$first_result->address->country_code );
  395.                 // Returns admin name in address->state, but no code
  396.                 if !empty$first_result->address->county ) )
  397.                     $location->sub_admin_code $first_result->address->county;
  398.                 if !empty$first_result->address->postcode ) )
  399.                     $location->postal_code $first_result->address->postcode;
  400.                 if !empty$first_result->address->city ) )
  401.                     $location $first_result->address->city;
  402.             }
  403.             $locations[$location;
  404.         }
  405.         return $locations;
  406.     }
  407.  
  408.     public function reverse_geocode$lat$lng {
  409.  
  410.         if !is_numeric$lat or !is_numeric$lng ) ) // Bad Request
  411.             return new WP_Error'bad_reverse_geocode_request'__'Reverse geocoding requires numeric coordinates.''GeoMashup' ) );
  412.  
  413.         $geocode_url 'http://nominatim.openstreetmap.org/reverse?format=json&zoom=18&address_details=1&lat=' .
  414.             $lat '&lon=' $lng '&email=' urlencodeget_option'admin_email' ) );
  415.  
  416.         $response $this->http->get$geocode_url$this->request_params );
  417.         if is_wp_error$response ) )
  418.             return $response;
  419.  
  420.         $status $response['response']['code'];
  421.         if '200' != $status )
  422.             return new WP_Error'geocoder_http_request_failed'$status ': ' $response['response']['message']$response );
  423.  
  424.         $data json_decode$response['body');
  425.         if empty$data ) )
  426.             return array();
  427.  
  428.         $location GeoMashupDB::blank_location();
  429.         $location->lat $lat;
  430.         $location->lng $lng;
  431.         $location->address $data->display_name;
  432.         if !empty$data->address ) ) {
  433.             if !empty$data->address->country_code ) )
  434.                 $location->country_code strtoupper$data->address->country_code );
  435.             // Returns admin name in address->state, but no code
  436.             if !empty$data->address->county ) )
  437.                 $location->sub_admin_code $data->address->county;
  438.             if !empty$data->address->postcode ) )
  439.                 $location->postal_code $data->address->postcode;
  440.             if !empty$data->address->city ) )
  441.                 $location->locality_name $data->address->city;
  442.         }
  443.         return array$location );
  444.     }
  445. }
  446.  
  447. }

Documentation generated on Sat, 09 Jul 2011 21:54:42 -0700 by phpDocumentor 1.4.3