Last active
December 14, 2015 19:18
-
-
Save rtt/5135293 to your computer and use it in GitHub Desktop.
A Geocoder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| class ReportableHTTPGeocodingFailure extends Exception {} | |
| class HTTPGeocodingFailure extends Exception {} | |
| class GeoLocation { | |
| function __construct($lng, $lat) { | |
| $this->lng = $lng; | |
| $this->lat = $lat; | |
| } | |
| function __toString() { | |
| return sprintf('<GeoLocation(%s, %s)>', $this->lng, $this->lat); | |
| } | |
| } | |
| interface Geocoder { | |
| function _geocode($q, $country); | |
| } | |
| class HTTPGeocoder { | |
| private function normalise($q) { | |
| return trim(strtolower($q)); | |
| } | |
| final public function geocode($q, $country='GB') { | |
| $q = $this->normalise($q); | |
| $failed = array('geocoded' => false); | |
| try { | |
| $query = $this->_geocode($q, $country); | |
| } | |
| catch (ReportableHTTPGeocodingFailure $e) { | |
| return array_merge($failed, array('message' => $e->getMessage())); | |
| } | |
| catch (HTTPGeocodingFailure $e) { | |
| return array_merge($failed, array('message' => $e->getMessage())); | |
| } | |
| catch (Exception $e) { | |
| return array_merge( | |
| $failed, | |
| array('message' => sprintf('General error: %s', $e->getMessage())) | |
| ); | |
| } | |
| return array( | |
| 'geocoded' => true, | |
| 'geolocation' => $query, | |
| 'query' => $q | |
| ); | |
| } | |
| } | |
| class GoogleGeocoder extends HTTPGeocoder { | |
| private $endpoint = "http://maps.google.com/maps/api/geocode/json"; | |
| protected function _geocode($q, $country) { | |
| $params = array( | |
| "sensor" => "false", | |
| "region" => $country, | |
| "address" => $q | |
| ); | |
| $url = sprintf( | |
| "%s?%s", | |
| $this->endpoint, | |
| http_build_query($params) | |
| ); | |
| // make request | |
| $resp = @file_get_contents($url); | |
| if (false === $resp) { | |
| throw new Exception('HTTP Error [no response?]'); | |
| } | |
| // parse json | |
| $json = @json_decode($resp, true); | |
| if (null === $json) { | |
| throw new Exception('Response Decode Error'); | |
| } | |
| if ('ZERO_RESULTS' == $json['status']) { | |
| throw new HTTPGeocodingFailure($json['status']); | |
| } | |
| elseif ('OK' !== $json['status']) { | |
| throw new ReportableHTTPGeocodingFailure($json['status']); | |
| } | |
| $place = $json['results'][0]; | |
| return array( | |
| 'geolocation' => array( | |
| 'lng' => $place['geometry']['location']['lng'], | |
| 'lat' => $place['geometry']['location']['lat'] | |
| ) | |
| ); | |
| } | |
| } | |
| function error_response($msg, $and_exit=true) { | |
| echo json_encode(array('success' => false, 'msg' => $msg)); | |
| if ($and_exit) { | |
| exit(); | |
| } | |
| } | |
| function success_response($resp) { | |
| echo json_encode(array('success' =>$resp)); | |
| } | |
| // -- init -- | |
| header('Content-type: application/json'); | |
| // check backend specified | |
| if (!isset($_GET['backend'])) { | |
| error_response('Please specify a backend'); | |
| } | |
| $backend = $_GET['backend']; | |
| if (!class_exists($backend)) { | |
| error_response('Backend not found'); | |
| } | |
| if (!isset($_GET['q'])) { | |
| error_response('Please specify a query'); | |
| } | |
| // should be good to go | |
| $backend = new $backend(); | |
| $result = $backend->geocode($_GET['q']); | |
| success_response($result); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment