From e61c9eb1dbe9b6d17c1b50498cd1dc86c797f2a8 Mon Sep 17 00:00:00 2001 From: vicchi Date: Mon, 12 Sep 2016 15:03:35 +0200 Subject: [PATCH 1/2] Fix bug where cached unit test responses aren't serialised --- tests/Geocoder/Tests/CachedResponseClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Geocoder/Tests/CachedResponseClient.php b/tests/Geocoder/Tests/CachedResponseClient.php index 97cc212fd..7f600baad 100644 --- a/tests/Geocoder/Tests/CachedResponseClient.php +++ b/tests/Geocoder/Tests/CachedResponseClient.php @@ -44,7 +44,7 @@ public function sendRequest(RequestInterface $request) $response = $this->delegate->sendRequest($request); if ($this->useCache) { - file_put_contents($file, $response->getBody()->getContents()); + file_put_contents($file, serialize($response->getBody()->getContents())); } return $response; From bf5d350212a7dac8b235bfdc3bf613c4850da572 Mon Sep 17 00:00:00 2001 From: vicchi Date: Mon, 12 Sep 2016 15:43:30 +0200 Subject: [PATCH 2/2] Add Mapzen provider support --- README.md | 10 +- phpunit.xml.dist | 1 + src/Geocoder/Provider/Mapzen.php | 223 +++++++++++++ .../00a3bd9f9306c9ae3b8aa7aa0c85d71d6d5de8fa | 1 + .../404ab562295927999aba94e1e615fca96186879e | 1 + .../56e8d5a5657a1015d32ab35096598c62df39852a | 1 + .../c04af40112605168a2260e602918c6ef37f235cd | 1 + .../e472c244bd0475c86ecc1803d7555f1209010733 | 1 + tests/Geocoder/Tests/Provider/MapzenTest.php | 300 ++++++++++++++++++ 9 files changed, 537 insertions(+), 2 deletions(-) create mode 100644 src/Geocoder/Provider/Mapzen.php create mode 100644 tests/.cached_responses/00a3bd9f9306c9ae3b8aa7aa0c85d71d6d5de8fa create mode 100644 tests/.cached_responses/404ab562295927999aba94e1e615fca96186879e create mode 100644 tests/.cached_responses/56e8d5a5657a1015d32ab35096598c62df39852a create mode 100644 tests/.cached_responses/c04af40112605168a2260e602918c6ef37f235cd create mode 100644 tests/.cached_responses/e472c244bd0475c86ecc1803d7555f1209010733 create mode 100644 tests/Geocoder/Tests/Provider/MapzenTest.php diff --git a/README.md b/README.md index f96bbff66..06abcb712 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ providing a powerful abstraction layer for geocoding manipulations. - [GeoIP2](#geoip2) - [GoogleMaps](#googlemaps) - [GoogleMapsBusiness](#googlemapsbusiness) + - [Mapzen](#mapzen) - [MaxMindBinary](#maxmindbinary) - [Nominatim](#nominatim) - [TomTom](#tomtom) @@ -239,7 +240,8 @@ Chain | `chain` | | | | | meta provider which iterates over a list of providers [Geonames](http://www.geonames.org/commercial-webservices.html) | `geonames` | yes |no | worldwide | yes | requires registration, no free tier [Google Maps](https://developers.google.com/maps/documentation/geocoding/) | `google_maps` | yes | supported | worldwide | yes | requires API key. Limit 2500 requests per day [Google Maps for Business](https://developers.google.com/maps/documentation/business/) | `google_maps_business` | yes | supported | worldwide | yes | requires API key. Limit 100,000 requests per day -[MapQuest](http://developer.mapquest.com/web/products/dev-services/geocoding-ws) | `map_quest` | yes | no | worldwide | yes | both open and [commercial service](http://platform.mapquest.com/geocoding/) require API key +[MapQuest](http://developer.mapquest.com/web/products/dev-services/geocoding-ws) | `map_quest` | yes | no | worldwide | yes | both open and [commercial service](http://platform.mapquest.com/geocoding/) requires API key +[Mapzen](https://mapzen.com/documentation/search/) | `mapzen` | yes | supported | worldwide | yes | requires API key; limited to 6 request/sec, 30,000 request/day [Nominatim](http://wiki.openstreetmap.org/wiki/Nominatim) | `nominatim` | yes | supported | worldwide | yes | requires a domain name (e.g. local installation) [OpenCage](http://geocoder.opencagedata.com/) | `opencage` | yes | supported | worldwide | yes | requires API key. 2500 requests/day free [OpenStreetMap](http://wiki.openstreetmap.org/wiki/Nominatim) | `openstreetmap` | yes | no | worldwide | yes | heavy users (>1q/s) get banned @@ -296,6 +298,10 @@ $geocoder = new \Geocoder\Provider\GoogleMaps( A valid `Client ID` is required. The private key is optional. This provider also supports SSL, and extends the `GoogleMaps` provider. +##### Mapzen + +A valid `API key` is required. This provider also supports SSL. + ##### MaxMindBinary This provider requires a data file, and the @@ -524,7 +530,7 @@ Version `3.x` is the current major stable version of Geocoder. Cookbook -------- -We have a small cookbook where you can find examples on common use cases: +We have a small cookbook where you can find examples on common use cases: * [Caching responses](/docs/cookbook/cache.md) * [Configuring the HTTP client](/docs/cookbook/http-client.md) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index fb448b4b5..a25e5b27f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -27,6 +27,7 @@ + diff --git a/src/Geocoder/Provider/Mapzen.php b/src/Geocoder/Provider/Mapzen.php new file mode 100644 index 000000000..2f1fe8e8e --- /dev/null +++ b/src/Geocoder/Provider/Mapzen.php @@ -0,0 +1,223 @@ + + */ +class Mapzen extends AbstractHttpProvider +{ + /** + * @var string + */ + const GEOCODE_ENDPOINT_URL = '%s://search.mapzen.com/v1/search?text=%s&key=%s&size=%d'; + + /** + * @var string + */ + const REVERSE_ENDPOINT_URL = '%s://search.mapzen.com/v1/reverse?point.lat=%f&point.lon=%f&key=%s&size=%d'; + + /** + * @var string + */ + private $scheme; + + /** + * @var string + */ + private $apiKey; + + /** + * @param HttpClient $client An HTTP adapter. + * @param string $apiKey An API key. + * @param bool $useSsl Whether to use an SSL connection (optional). + */ + public function __construct(HttpClient $client, $apiKey, $useSSL = true) + { + parent::__construct($client); + + $this->apiKey = $apiKey; + $this->scheme = $useSSL ? 'https' : 'http'; + } + + /** + * {@inheritdoc} + */ + public function geocode($address) + { + if (null === $this->apiKey) { + throw new InvalidCredentials('No API Key provided.'); + } + + // This API doesn't handle IPs + if (filter_var($address, FILTER_VALIDATE_IP)) { + throw new UnsupportedOperation('The Mapzen provider does not support IP addresses, only street addresses.'); + } + + $query = sprintf(self::GEOCODE_ENDPOINT_URL, $this->scheme, urlencode($address), $this->apiKey, $this->getLimit()); + + return $this->executeQuery($query); + } + + /** + * {@inheritdoc} + */ + public function reverse($latitude, $longitude) + { + if (null === $this->apiKey) { + throw new InvalidCredentials('No API Key provided.'); + } + + $query = sprintf(self::REVERSE_ENDPOINT_URL, $this->scheme, $latitude, $longitude, $this->apiKey, $this->getLimit()); + + return $this->executeQuery($query); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'mapzen'; + } + + /** + * @param $query + * @return \Geocoder\Model\AddressCollection + */ + private function executeQuery($query) + { + $request = $this->getMessageFactory()->createRequest('GET', $query); + $content = (string) $this->getHttpClient()->sendRequest($request)->getBody(); + + if (empty($content)) { + throw new NoResult(sprintf('Could not execute query "%s".', $query)); + } + + $json = json_decode($content, true); + + // See https://mapzen.com/documentation/search/api-keys-rate-limits/ + if (isset($json['meta'])) { + switch ($json['meta']['status_code']) { + case 403: + throw new InvalidCredentials('Invalid or missing api key.'); + case 429: + throw new QuotaExceeded('Valid request but quota exceeded.'); + } + } + + if (!isset($json['type']) || $json['type'] !== 'FeatureCollection' || !isset($json['features']) || count($json['features']) === 0) { + throw new NoResult(sprintf('Could not find results for query "%s".', $query)); + } + + $locations = $json['features']; + + if (empty($locations)) { + throw new NoResult(sprintf('Could not find results for query "%s".', $query)); + } + + $results = []; + foreach ($locations as $location) { + $bounds = []; + if (isset($location['bbox'])) { + $bounds = [ + 'south' => $location['bbox'][3], + 'west' => $location['bbox'][2], + 'north' => $location['bbox'][1], + 'east' => $location['bbox'][0], + ]; + } + + $props = $location['properties']; + + $adminLevels = []; + foreach (['region', 'locality', 'macroregion', 'country'] as $i => $component) { + if (isset($props[$component])) { + $adminLevels[] = ['name' => $props[$component], 'level' => $i + 1]; + } + } + + $results[] = array_merge($this->getDefaults(), array( + 'latitude' => $location['geometry']['coordinates'][1], + 'longitude' => $location['geometry']['coordinates'][0], + 'bounds' => $bounds ?: [], + 'streetNumber' => isset($props['housenumber']) ? $props['housenumber'] : null, + 'streetName' => isset($props['street']) ? $props['street'] : null, + 'subLocality' => isset($props['neighbourhood']) ? $props['neighbourhood'] : null, + 'locality' => isset($props['locality']) ? $props['locality'] : null, + 'postalCode' => isset($props['postalcode']) ? $props['postalcode'] : null, + 'adminLevels' => $adminLevels, + 'country' => isset($props['country']) ? $props['country'] : null, + 'countryCode' => isset($props['country_a']) ? strtoupper($props['country_a']) : null + )); + } + + return $this->returnResults($results); + } + + /** + * @param array $components + * + * @return null|string + */ + protected function guessLocality(array $components) + { + $localityKeys = array('city', 'town' , 'village', 'hamlet'); + + return $this->guessBestComponent($components, $localityKeys); + } + + /** + * @param array $components + * + * @return null|string + */ + protected function guessStreetName(array $components) + { + $streetNameKeys = array('road', 'street', 'street_name', 'residential'); + + return $this->guessBestComponent($components, $streetNameKeys); + } + + /** + * @param array $components + * + * @return null|string + */ + protected function guessSubLocality(array $components) + { + $subLocalityKeys = array('neighbourhood', 'city_district'); + + return $this->guessBestComponent($components, $subLocalityKeys); + } + + /** + * @param array $components + * @param array $keys + * + * @return null|string + */ + protected function guessBestComponent(array $components, array $keys) + { + foreach ($keys as $key) { + if (isset($components[$key]) && !empty($components[$key])) { + return $components[$key]; + } + } + + return null; + } +} diff --git a/tests/.cached_responses/00a3bd9f9306c9ae3b8aa7aa0c85d71d6d5de8fa b/tests/.cached_responses/00a3bd9f9306c9ae3b8aa7aa0c85d71d6d5de8fa new file mode 100644 index 000000000..2297d3097 --- /dev/null +++ b/tests/.cached_responses/00a3bd9f9306c9ae3b8aa7aa0c85d71d6d5de8fa @@ -0,0 +1 @@ +s:3418:"{"geocoding":{"version":"0.1","attribution":"https://search.mapzen.com/v1/attribution","query":{"text":"Hanover","size":5,"private":false,"querySize":10},"engine":{"name":"Pelias","author":"Mapzen","version":"1.0"},"timestamp":1473682048001},"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-88.204203,42.027323]},"properties":{"id":"404497623","gid":"whosonfirst:localadmin:404497623","layer":"localadmin","source":"whosonfirst","source_id":"404497623","name":"Hanover","confidence":0.951,"country":"United States","country_gid":"whosonfirst:country:85633793","country_a":"USA","region":"Illinois","region_gid":"whosonfirst:region:85688697","region_a":"IL","county":"Cook County","county_gid":"whosonfirst:county:102084317","localadmin":"Hanover","localadmin_gid":"whosonfirst:localadmin:404497623","label":"Hanover, IL, USA"},"bbox":[-88.263572,41.986227,-88.14458,42.067434]},{"type":"Feature","geometry":{"type":"Point","coordinates":[-78.122906,18.393428]},"properties":{"id":"85672563","gid":"whosonfirst:region:85672563","layer":"region","source":"whosonfirst","source_id":"85672563","name":"Hanover","confidence":0.944,"country":"Jamaica","country_gid":"whosonfirst:country:85632215","country_a":"JAM","region":"Hanover","region_gid":"whosonfirst:region:85672563","label":"Hanover, Jamaica"},"bbox":[-78.3460426069,18.2897883164,-77.9214139468,18.4554710959]},{"type":"Feature","geometry":{"type":"Point","coordinates":[-76.72414,39.19289]},"properties":{"id":"4357340","gid":"geonames:locality:4357340","layer":"locality","source":"geonames","source_id":"4357340","name":"Hanover","confidence":0.734,"country":"United States","country_gid":"whosonfirst:country:85633793","country_a":"USA","region":"Maryland","region_gid":"whosonfirst:region:85688501","region_a":"MD","county":"Howard County","county_gid":"whosonfirst:county:102084263","locality":"Hanover","locality_gid":"whosonfirst:locality:4357340","label":"Hanover, MD, USA"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-70.81199,42.11316]},"properties":{"id":"4938836","gid":"geonames:locality:4938836","layer":"locality","source":"geonames","source_id":"4938836","name":"Hanover","confidence":0.72,"country":"United States","country_gid":"whosonfirst:country:85633793","country_a":"USA","region":"Massachusetts","region_gid":"whosonfirst:region:85688645","region_a":"MA","county":"Plymouth County","county_gid":"whosonfirst:county:102084367","localadmin":"Hanover","localadmin_gid":"whosonfirst:localadmin:404476511","locality":"Hanover","locality_gid":"whosonfirst:locality:4938836","label":"Hanover, MA, USA"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-76.984032,39.81179]},"properties":{"id":"101717245","gid":"whosonfirst:locality:101717245","layer":"locality","source":"whosonfirst","source_id":"101717245","name":"Hanover","confidence":0.718,"country":"United States","country_gid":"whosonfirst:country:85633793","country_a":"USA","region":"Pennsylvania","region_gid":"whosonfirst:region:85688481","region_a":"PA","county":"York County","county_gid":"whosonfirst:county:102080953","localadmin":"Hanover","localadmin_gid":"whosonfirst:localadmin:404487771","locality":"Hanover","locality_gid":"whosonfirst:locality:101717245","label":"Hanover, PA, USA"},"bbox":[-76.999944,39.791156,-76.963061,39.831769]}],"bbox":[-88.263572,18.2897883164,-70.81199,42.11316]}"; \ No newline at end of file diff --git a/tests/.cached_responses/404ab562295927999aba94e1e615fca96186879e b/tests/.cached_responses/404ab562295927999aba94e1e615fca96186879e new file mode 100644 index 000000000..2c0d5f923 --- /dev/null +++ b/tests/.cached_responses/404ab562295927999aba94e1e615fca96186879e @@ -0,0 +1 @@ +s:4780:"{"geocoding":{"version":"0.1","attribution":"https://search.mapzen.com/v1/attribution","query":{"text":"242 Acklam Road, London, United Kingdom","parsed_text":{"name":"242 Acklam Road","number":"242","street":"Acklam Road","regions":["London","United Kingdom"],"admin_parts":"London, United Kingdom"},"size":5,"private":false,"querySize":10},"engine":{"name":"Pelias","author":"Mapzen","version":"1.0"},"timestamp":1473674363289},"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.203602,51.521124]},"properties":{"id":"node:3711723386","gid":"openstreetmap:address:node:3711723386","layer":"address","source":"openstreetmap","source_id":"node:3711723386","name":"240 Acklam Road","housenumber":"240","street":"Acklam Road","postalcode":"W10 5QT","confidence":0.866,"country":"United Kingdom","country_gid":"whosonfirst:country:85633159","country_a":"GBR","macroregion":"England","macroregion_gid":"whosonfirst:macroregion:404227469","region":"Kensington and Chelsea","region_gid":"whosonfirst:region:85683667","locality":"London","locality_gid":"whosonfirst:locality:101750367","neighbourhood":"Westbourne Green","neighbourhood_gid":"whosonfirst:neighbourhood:85864267","label":"240 Acklam Road, London, England, United Kingdom"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-1.282082,54.552668]},"properties":{"id":"node:1485615866","gid":"openstreetmap:address:node:1485615866","layer":"address","source":"openstreetmap","source_id":"node:1485615866","name":"Teesdale Park Acklam Road","housenumber":"Teesdale Park","street":"Acklam Road","postalcode":"TS17 7JU","confidence":0.866,"country":"United Kingdom","country_gid":"whosonfirst:country:85633159","country_a":"GBR","macroregion":"England","macroregion_gid":"whosonfirst:macroregion:404227469","region":"Stockton-on-Tees","region_gid":"whosonfirst:region:85683777","localadmin":"Thornaby","localadmin_gid":"whosonfirst:localadmin:404452219","neighbourhood":"Acklam","neighbourhood_gid":"whosonfirst:neighbourhood:85785205","label":"Teesdale Park Acklam Road, Thornaby, England, United Kingdom"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-70.568928,41.565854]},"properties":{"id":"us/ma/statewide:862559","gid":"openaddresses:address:us/ma/statewide:862559","layer":"address","source":"openaddresses","source_id":"us/ma/statewide:862559","name":"242 Acapesket Road","housenumber":"242","street":"Acapesket Road","postalcode":"02536","confidence":0.647,"country":"United States","country_gid":"whosonfirst:country:85633793","country_a":"USA","region":"Massachusetts","region_gid":"whosonfirst:region:85688645","region_a":"MA","county":"Barnstable County","county_gid":"whosonfirst:county:102084379","localadmin":"Falmouth","localadmin_gid":"whosonfirst:localadmin:404476181","locality":"East Falmouth","locality_gid":"whosonfirst:locality:85950545","neighbourhood":"Kingdom Hall","neighbourhood_gid":"whosonfirst:neighbourhood:85828363","label":"242 Acapesket Road, East Falmouth, MA, USA"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-72.492505,42.704231]},"properties":{"id":"us/ma/statewide:1436753","gid":"openaddresses:address:us/ma/statewide:1436753","layer":"address","source":"openaddresses","source_id":"us/ma/statewide:1436753","name":"242 Old Vernon Road","housenumber":"242","street":"Old Vernon Road","postalcode":"01360","confidence":0.647,"country":"United States","country_gid":"whosonfirst:country:85633793","country_a":"USA","region":"Massachusetts","region_gid":"whosonfirst:region:85688645","region_a":"MA","county":"Franklin County","county_gid":"whosonfirst:county:102084457","localadmin":"Northfield","localadmin_gid":"whosonfirst:localadmin:404475965","neighbourhood":"Satans Kingdom","neighbourhood_gid":"whosonfirst:neighbourhood:420523529","label":"242 Old Vernon Road, Northfield, MA, USA"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-70.528914,41.591705]},"properties":{"id":"us/ma/statewide:2148130","gid":"openaddresses:address:us/ma/statewide:2148130","layer":"address","source":"openaddresses","source_id":"us/ma/statewide:2148130","name":"242 Carriage Shop Road","housenumber":"242","street":"Carriage Shop Road","postalcode":"02536","confidence":0.647,"country":"United States","country_gid":"whosonfirst:country:85633793","country_a":"USA","region":"Massachusetts","region_gid":"whosonfirst:region:85688645","region_a":"MA","county":"Barnstable County","county_gid":"whosonfirst:county:102084379","localadmin":"Falmouth","localadmin_gid":"whosonfirst:localadmin:404476181","neighbourhood":"Kingdom Hall","neighbourhood_gid":"whosonfirst:neighbourhood:85828363","label":"242 Carriage Shop Road, Falmouth, MA, USA"}}],"bbox":[-72.492505,41.565854,-0.203602,54.552668]}"; \ No newline at end of file diff --git a/tests/.cached_responses/56e8d5a5657a1015d32ab35096598c62df39852a b/tests/.cached_responses/56e8d5a5657a1015d32ab35096598c62df39852a new file mode 100644 index 000000000..8f93673a4 --- /dev/null +++ b/tests/.cached_responses/56e8d5a5657a1015d32ab35096598c62df39852a @@ -0,0 +1 @@ +s:5120:"{"geocoding":{"version":"0.1","attribution":"https://search.mapzen.com/v1/attribution","query":{"text":"Kalbacher Hauptstraße 10, 60437 Frankfurt, Germany","parsed_text":{"name":"Kalbacher Hauptstraße 10","postalcode":"60437","regions":["Kalbacher Hauptstraße 10","Frankfurt","Germany"],"admin_parts":"60437 Frankfurt, Germany"},"size":5,"private":false,"querySize":10},"engine":{"name":"Pelias","author":"Mapzen","version":"1.0"},"timestamp":1473682507033},"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[8.636781,50.189017]},"properties":{"id":"de/he/city_of_frankfurtammain:72948","gid":"openaddresses:address:de/he/city_of_frankfurtammain:72948","layer":"address","source":"openaddresses","source_id":"de/he/city_of_frankfurtammain:72948","name":"Kalbacher Hauptstraße 10a","housenumber":"10a","street":"Kalbacher Hauptstraße","postalcode":"60437","confidence":0.88,"country":"Germany","country_gid":"whosonfirst:country:85633111","country_a":"DEU","region":"Hessen","region_gid":"whosonfirst:region:85682531","macrocounty":"Darmstadt","macrocounty_gid":"whosonfirst:macrocounty:404227581","county":"Frankfurt am Main","county_gid":"whosonfirst:county:102063589","locality":"Frankfurt am Main","locality_gid":"whosonfirst:locality:101913837","neighbourhood":"Römerstadt","neighbourhood_gid":"whosonfirst:neighbourhood:85796311","label":"Kalbacher Hauptstraße 10a, Frankfurt am Main, Germany"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[8.636575,50.189044]},"properties":{"id":"de/he/city_of_frankfurtammain:72883","gid":"openaddresses:address:de/he/city_of_frankfurtammain:72883","layer":"address","source":"openaddresses","source_id":"de/he/city_of_frankfurtammain:72883","name":"Kalbacher Hauptstraße 10","housenumber":"10","street":"Kalbacher Hauptstraße","postalcode":"60437","confidence":0.88,"country":"Germany","country_gid":"whosonfirst:country:85633111","country_a":"DEU","region":"Hessen","region_gid":"whosonfirst:region:85682531","macrocounty":"Darmstadt","macrocounty_gid":"whosonfirst:macrocounty:404227581","county":"Frankfurt am Main","county_gid":"whosonfirst:county:102063589","locality":"Frankfurt am Main","locality_gid":"whosonfirst:locality:101913837","neighbourhood":"Römerstadt","neighbourhood_gid":"whosonfirst:neighbourhood:85796311","label":"Kalbacher Hauptstraße 10, Frankfurt am Main, Germany"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[8.635608,50.188253]},"properties":{"id":"way:109149380","gid":"openstreetmap:address:way:109149380","layer":"address","source":"openstreetmap","source_id":"way:109149380","name":"Kalbacher Hauptstraße 5","housenumber":"5","street":"Kalbacher Hauptstraße","postalcode":"60437","confidence":0.655,"country":"Germany","country_gid":"whosonfirst:country:85633111","country_a":"DEU","region":"Hessen","region_gid":"whosonfirst:region:85682531","macrocounty":"Darmstadt","macrocounty_gid":"whosonfirst:macrocounty:404227581","county":"Frankfurt am Main","county_gid":"whosonfirst:county:102063589","locality":"Frankfurt am Main","locality_gid":"whosonfirst:locality:101913837","neighbourhood":"Römerstadt","neighbourhood_gid":"whosonfirst:neighbourhood:85796311","label":"Kalbacher Hauptstraße 5, Frankfurt am Main, Germany"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[8.646009,50.187199]},"properties":{"id":"way:109282050","gid":"openstreetmap:address:way:109282050","layer":"address","source":"openstreetmap","source_id":"way:109282050","name":"Kalbacher Hauptstraße 78","housenumber":"78","street":"Kalbacher Hauptstraße","postalcode":"60437","confidence":0.655,"country":"Germany","country_gid":"whosonfirst:country:85633111","country_a":"DEU","region":"Hessen","region_gid":"whosonfirst:region:85682531","macrocounty":"Darmstadt","macrocounty_gid":"whosonfirst:macrocounty:404227581","county":"Frankfurt am Main","county_gid":"whosonfirst:county:102063589","locality":"Frankfurt am Main","locality_gid":"whosonfirst:locality:101913837","neighbourhood":"Römerstadt","neighbourhood_gid":"whosonfirst:neighbourhood:85796311","label":"Kalbacher Hauptstraße 78, Frankfurt am Main, Germany"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[8.646989,50.18735]},"properties":{"id":"way:109282307","gid":"openstreetmap:address:way:109282307","layer":"address","source":"openstreetmap","source_id":"way:109282307","name":"Kalbacher Hauptstraße 115","housenumber":"115","street":"Kalbacher Hauptstraße","postalcode":"60437","confidence":0.655,"country":"Germany","country_gid":"whosonfirst:country:85633111","country_a":"DEU","region":"Hessen","region_gid":"whosonfirst:region:85682531","macrocounty":"Darmstadt","macrocounty_gid":"whosonfirst:macrocounty:404227581","county":"Frankfurt am Main","county_gid":"whosonfirst:county:102063589","locality":"Frankfurt am Main","locality_gid":"whosonfirst:locality:101913837","neighbourhood":"Römerstadt","neighbourhood_gid":"whosonfirst:neighbourhood:85796311","label":"Kalbacher Hauptstraße 115, Frankfurt am Main, Germany"}}],"bbox":[8.635608,50.187199,8.646989,50.189044]}"; \ No newline at end of file diff --git a/tests/.cached_responses/c04af40112605168a2260e602918c6ef37f235cd b/tests/.cached_responses/c04af40112605168a2260e602918c6ef37f235cd new file mode 100644 index 000000000..c4fa7d3f1 --- /dev/null +++ b/tests/.cached_responses/c04af40112605168a2260e602918c6ef37f235cd @@ -0,0 +1 @@ +s:3836:"{"geocoding":{"version":"0.1","attribution":"https://search.mapzen.com/v1/attribution","query":{"size":5,"private":false,"point.lat":54.048407,"point.lon":-2.799034,"boundary.circle.radius":1,"boundary.circle.lat":54.048407,"boundary.circle.lon":-2.799034,"querySize":10},"engine":{"name":"Pelias","author":"Mapzen","version":"1.0"},"timestamp":1473679050630},"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-2.798955,54.048412]},"properties":{"id":"node:3930594967","gid":"openstreetmap:venue:node:3930594967","layer":"venue","source":"openstreetmap","source_id":"node:3930594967","name":"Collegian W.M.C","street":"Gage Street","confidence":0.9,"distance":0.005,"country":"United Kingdom","country_gid":"whosonfirst:country:85633159","country_a":"GBR","macroregion":"England","macroregion_gid":"whosonfirst:macroregion:404227469","region":"Lancashire","region_gid":"whosonfirst:region:85683853","locality":"Lancaster","locality_gid":"whosonfirst:locality:101873271","label":"Collegian W.M.C, Lancaster, England, United Kingdom"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-2.79913,54.048378]},"properties":{"id":"node:3930587961","gid":"openstreetmap:venue:node:3930587961","layer":"venue","source":"openstreetmap","source_id":"node:3930587961","name":"Stable End Curio's","confidence":0.9,"distance":0.007,"country":"United Kingdom","country_gid":"whosonfirst:country:85633159","country_a":"GBR","macroregion":"England","macroregion_gid":"whosonfirst:macroregion:404227469","region":"Lancashire","region_gid":"whosonfirst:region:85683853","locality":"Lancaster","locality_gid":"whosonfirst:locality:101873271","label":"Stable End Curio's, Lancaster, England, United Kingdom"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-2.798922,54.04823]},"properties":{"id":"node:985894837","gid":"openstreetmap:venue:node:985894837","layer":"venue","source":"openstreetmap","source_id":"node:985894837","name":"The Tap House","confidence":0.8,"distance":0.021,"country":"United Kingdom","country_gid":"whosonfirst:country:85633159","country_a":"GBR","macroregion":"England","macroregion_gid":"whosonfirst:macroregion:404227469","region":"Lancashire","region_gid":"whosonfirst:region:85683853","locality":"Lancaster","locality_gid":"whosonfirst:locality:101873271","label":"The Tap House, Lancaster, England, United Kingdom"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-2.798828,54.04823]},"properties":{"id":"node:3930587962","gid":"openstreetmap:venue:node:3930587962","layer":"venue","source":"openstreetmap","source_id":"node:3930587962","name":"The Elles Gallery","street":"Gage Street","confidence":0.8,"distance":0.024,"country":"United Kingdom","country_gid":"whosonfirst:country:85633159","country_a":"GBR","macroregion":"England","macroregion_gid":"whosonfirst:macroregion:404227469","region":"Lancashire","region_gid":"whosonfirst:region:85683853","locality":"Lancaster","locality_gid":"whosonfirst:locality:101873271","label":"The Elles Gallery, Lancaster, England, United Kingdom"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-2.798939,54.04813]},"properties":{"id":"node:3930587255","gid":"openstreetmap:venue:node:3930587255","layer":"venue","source":"openstreetmap","source_id":"node:3930587255","name":"Nicholas Evans Printing","street":"Mary Street","confidence":0.8,"distance":0.031,"country":"United Kingdom","country_gid":"whosonfirst:country:85633159","country_a":"GBR","macroregion":"England","macroregion_gid":"whosonfirst:macroregion:404227469","region":"Lancashire","region_gid":"whosonfirst:region:85683853","locality":"Lancaster","locality_gid":"whosonfirst:locality:101873271","label":"Nicholas Evans Printing, Lancaster, England, United Kingdom"}}],"bbox":[-2.79913,54.04813,-2.798828,54.048412]}"; \ No newline at end of file diff --git a/tests/.cached_responses/e472c244bd0475c86ecc1803d7555f1209010733 b/tests/.cached_responses/e472c244bd0475c86ecc1803d7555f1209010733 new file mode 100644 index 000000000..21b7882bb --- /dev/null +++ b/tests/.cached_responses/e472c244bd0475c86ecc1803d7555f1209010733 @@ -0,0 +1 @@ +s:5153:"{"geocoding":{"version":"0.1","attribution":"https://search.mapzen.com/v1/attribution","query":{"size":5,"private":false,"point.lat":49.139092,"point.lon":1.657246,"boundary.circle.radius":1,"boundary.circle.lat":49.139092,"boundary.circle.lon":1.657246,"querySize":10},"engine":{"name":"Pelias","author":"Mapzen","version":"1.0"},"timestamp":1473681887087},"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[1.657246,49.139092]},"properties":{"id":"node:1564292039","gid":"openstreetmap:venue:node:1564292039","layer":"venue","source":"openstreetmap","source_id":"node:1564292039","name":"Les Jardins d'Épicure","confidence":1,"distance":0,"country":"France","country_gid":"whosonfirst:country:85633147","country_a":"FRA","macroregion":"Île-De-France","macroregion_gid":"whosonfirst:macroregion:404227465","region":"Val-d'Oise","region_gid":"whosonfirst:region:85683451","macrocounty":"Pontoise","macrocounty_gid":"whosonfirst:macrocounty:404228193","county":"Magny-En-Vexin","county_gid":"whosonfirst:county:102067333","localadmin":"Bray-Et-Lu","localadmin_gid":"whosonfirst:localadmin:404408311","locality":"Bus-Saint-Rémy","locality_gid":"whosonfirst:locality:101879825","label":"Les Jardins d'Épicure, Bus-Saint-Rémy, France"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[1.657036,49.139443]},"properties":{"id":"fr/val_doise:24453","gid":"openaddresses:address:fr/val_doise:24453","layer":"address","source":"openaddresses","source_id":"fr/val_doise:24453","name":"16 Grande Rue","housenumber":"16","street":"Grande Rue","postalcode":"95710","confidence":0.8,"distance":0.042,"country":"France","country_gid":"whosonfirst:country:85633147","country_a":"FRA","macroregion":"Île-De-France","macroregion_gid":"whosonfirst:macroregion:404227465","region":"Val-d'Oise","region_gid":"whosonfirst:region:85683451","macrocounty":"Pontoise","macrocounty_gid":"whosonfirst:macrocounty:404228193","county":"Magny-En-Vexin","county_gid":"whosonfirst:county:102067333","localadmin":"Bray-Et-Lu","localadmin_gid":"whosonfirst:localadmin:404408311","locality":"Bus-Saint-Rémy","locality_gid":"whosonfirst:locality:101879825","label":"16 Grande Rue, Bus-Saint-Rémy, France"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[1.657518,49.13963]},"properties":{"id":"fr/val_doise:173518","gid":"openaddresses:address:fr/val_doise:173518","layer":"address","source":"openaddresses","source_id":"fr/val_doise:173518","name":"23 Grande Rue","housenumber":"23","street":"Grande Rue","postalcode":"95710","confidence":0.8,"distance":0.063,"country":"France","country_gid":"whosonfirst:country:85633147","country_a":"FRA","macroregion":"Île-De-France","macroregion_gid":"whosonfirst:macroregion:404227465","region":"Val-d'Oise","region_gid":"whosonfirst:region:85683451","macrocounty":"Pontoise","macrocounty_gid":"whosonfirst:macrocounty:404228193","county":"Magny-En-Vexin","county_gid":"whosonfirst:county:102067333","localadmin":"Bray-Et-Lu","localadmin_gid":"whosonfirst:localadmin:404408311","locality":"Bus-Saint-Rémy","locality_gid":"whosonfirst:locality:101879825","label":"23 Grande Rue, Bus-Saint-Rémy, France"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[1.657782,49.139601]},"properties":{"id":"fr/val_doise:173511","gid":"openaddresses:address:fr/val_doise:173511","layer":"address","source":"openaddresses","source_id":"fr/val_doise:173511","name":"18 Grande Rue","housenumber":"18","street":"Grande Rue","postalcode":"95710","confidence":0.8,"distance":0.069,"country":"France","country_gid":"whosonfirst:country:85633147","country_a":"FRA","macroregion":"Île-De-France","macroregion_gid":"whosonfirst:macroregion:404227465","region":"Val-d'Oise","region_gid":"whosonfirst:region:85683451","macrocounty":"Pontoise","macrocounty_gid":"whosonfirst:macrocounty:404228193","county":"Magny-En-Vexin","county_gid":"whosonfirst:county:102067333","localadmin":"Bray-Et-Lu","localadmin_gid":"whosonfirst:localadmin:404408311","locality":"Bus-Saint-Rémy","locality_gid":"whosonfirst:locality:101879825","label":"18 Grande Rue, Bus-Saint-Rémy, France"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[1.658133,49.13903]},"properties":{"id":"fr/val_doise:170018","gid":"openaddresses:address:fr/val_doise:170018","layer":"address","source":"openaddresses","source_id":"fr/val_doise:170018","name":"2 Rue Des Prés","housenumber":"2","street":"Rue Des Prés","postalcode":"95710","confidence":0.8,"distance":0.065,"country":"France","country_gid":"whosonfirst:country:85633147","country_a":"FRA","macroregion":"Île-De-France","macroregion_gid":"whosonfirst:macroregion:404227465","region":"Val-d'Oise","region_gid":"whosonfirst:region:85683451","macrocounty":"Pontoise","macrocounty_gid":"whosonfirst:macrocounty:404228193","county":"Magny-En-Vexin","county_gid":"whosonfirst:county:102067333","localadmin":"Bray-Et-Lu","localadmin_gid":"whosonfirst:localadmin:404408311","locality":"Bus-Saint-Rémy","locality_gid":"whosonfirst:locality:101879825","label":"2 Rue Des Prés, Bus-Saint-Rémy, France"}}],"bbox":[1.657036,49.13903,1.658133,49.13963]}"; \ No newline at end of file diff --git a/tests/Geocoder/Tests/Provider/MapzenTest.php b/tests/Geocoder/Tests/Provider/MapzenTest.php new file mode 100644 index 000000000..6326e95ab --- /dev/null +++ b/tests/Geocoder/Tests/Provider/MapzenTest.php @@ -0,0 +1,300 @@ + + */ +class MapzenTest extends TestCase +{ + public function testGetName() + { + $provider = new Mapzen($this->getMockAdapter($this->never()), 'api_key'); + $this->assertEquals('mapzen', $provider->getName()); + } + + /** + * @expectedException \Geocoder\Exception\NoResult + * @expectedExceptionMessage Could not find results for query "https://search.mapzen.com/v1/search?text=foobar&key=api_key&size=5". + */ + public function testGeocode() + { + $provider = new Mapzen($this->getMockAdapterReturns('{}'), 'api_key'); + $provider->geocode('foobar'); + } + + /** + * @expectedException \Geocoder\Exception\NoResult + * @expectedExceptionMessage Could not find results for query "https://search.mapzen.com/v1/search?text=foobar&key=api_key&size=5". + */ + public function testSslSchema() + { + $provider = new Mapzen($this->getMockAdapterReturns('{}'), 'api_key', true); + $provider->geocode('foobar'); + } + + /** + * @expectedException \Geocoder\Exception\NoResult + * @expectedExceptionMessage Could not execute query "https://search.mapzen.com/v1/search?text=242+Acklam+Road%2C+London%2C+United+Kingdom&key=api_key&size=5". + */ + public function testGeocodeWithAddressGetsNullContent() + { + $provider = new Mapzen($this->getMockAdapterReturns(null), 'api_key'); + $provider->geocode('242 Acklam Road, London, United Kingdom'); + } + + public function testGeocodeWithRealAddress() + { + if (!isset($_SERVER['MAPZEN_API_KEY'])) { + $this->markTestSkipped('You need to configure the MAPZEN_API_KEY value in phpunit.xml'); + } + + $provider = new Mapzen($this->getAdapter($_SERVER['MAPZEN_API_KEY']), $_SERVER['MAPZEN_API_KEY']); + $results = $provider->geocode('242 Acklam Road, London, United Kingdom'); + + $this->assertInstanceOf('Geocoder\Model\AddressCollection', $results); + $this->assertCount(5, $results); + + /** @var \Geocoder\Model\Address $result */ + $result = $results->first(); + $this->assertInstanceOf('\Geocoder\Model\Address', $result); + $this->assertEquals(51.521124, $result->getLatitude(), '', 0.01); + $this->assertEquals(-0.20360200000000001, $result->getLongitude(), '', 0.01); + $this->assertEquals(240, $result->getStreetNumber()); + $this->assertEquals('Acklam Road', $result->getStreetName()); + $this->assertEquals('W10 5QT', $result->getPostalCode()); + $this->assertEquals('London', $result->getLocality()); + $this->assertCount(4, $result->getAdminLevels()); + $this->assertEquals('London', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('Kensington and Chelsea', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('United Kingdom', $result->getCountry()->getName()); + $this->assertEquals('GBR', $result->getCountry()->getCode()); + } + + /** + * @expectedException \Geocoder\Exception\NoResult + */ + public function testReverse() + { + if (!isset($_SERVER['MAPZEN_API_KEY'])) { + $this->markTestSkipped('You need to configure the MAPZEN_API_KEY value in phpunit.xml'); + } + + $provider = new Mapzen($this->getMockAdapter(), $_SERVER['MAPZEN_API_KEY']); + $provider->reverse(1, 2); + } + + public function testReverseWithRealCoordinates() + { + if (!isset($_SERVER['MAPZEN_API_KEY'])) { + $this->markTestSkipped('You need to configure the MAPZEN_API_KEY value in phpunit.xml'); + } + + $provider = new Mapzen($this->getAdapter($_SERVER['MAPZEN_API_KEY']), $_SERVER['MAPZEN_API_KEY']); + $results = $provider->reverse(54.0484068, -2.7990345); + + $this->assertInstanceOf('Geocoder\Model\AddressCollection', $results); + $this->assertCount(5, $results); + + /** @var \Geocoder\Model\Address $result */ + $result = $results->first(); + $this->assertInstanceOf('\Geocoder\Model\Address', $result); + $this->assertEquals(54.048411999999999, $result->getLatitude(), '', 0.001); + $this->assertEquals(-2.7989549999999999, $result->getLongitude(), '', 0.001); + $this->assertNull($result->getStreetNumber()); + $this->assertEquals('Gage Street', $result->getStreetName()); + $this->assertNull($result->getPostalCode()); + $this->assertEquals('Lancaster', $result->getLocality()); + $this->assertCount(4, $result->getAdminLevels()); + $this->assertEquals('Lancashire', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('England', $result->getAdminLevels()->get(3)->getName()); + $this->assertEquals('United Kingdom', $result->getCountry()->getName()); + $this->assertEquals('GBR', $result->getCountry()->getCode()); + } + + public function testReverseWithVillage() + { + if (!isset($_SERVER['MAPZEN_API_KEY'])) { + $this->markTestSkipped('You need to configure the MAPZEN_API_KEY value in phpunit.xml'); + } + + $provider = new Mapzen($this->getAdapter($_SERVER['MAPZEN_API_KEY']), $_SERVER['MAPZEN_API_KEY']); + $results = $provider->reverse(49.1390924, 1.6572462); + + $this->assertInstanceOf('Geocoder\Model\AddressCollection', $results); + $this->assertCount(5, $results); + + /** @var \Geocoder\Model\Address $result */ + $result = $results->first(); + $this->assertInstanceOf('\Geocoder\Model\Address', $result); + $this->assertEquals('Bus-Saint-Rémy', $result->getLocality()); + } + + public function testGeocodeWithCity() + { + if (!isset($_SERVER['MAPZEN_API_KEY'])) { + $this->markTestSkipped('You need to configure the MAPZEN_API_KEY value in phpunit.xml'); + } + + $provider = new Mapzen($this->getAdapter($_SERVER['MAPZEN_API_KEY']), $_SERVER['MAPZEN_API_KEY']); + $results = $provider->geocode('Hanover'); + + $this->assertInstanceOf('Geocoder\Model\AddressCollection', $results); + $this->assertCount(5, $results); + + /** @var \Geocoder\Model\Address $result */ + $result = $results->first(); + $this->assertInstanceOf('\Geocoder\Model\Address', $result); + $this->assertEquals(42.027323000000003, $result->getLatitude(), '', 0.01); + $this->assertEquals(-88.204203000000007, $result->getLongitude(), '', 0.01); + $this->assertNull($result->getLocality()); + $this->assertCount(2, $result->getAdminLevels()); + $this->assertEquals('United States', $result->getAdminLevels()->get(4)->getName()); + $this->assertEquals('Illinois', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('United States', $result->getCountry()->getName()); + + /** @var \Geocoder\Model\Address $result */ + $result = $results->get(1); + $this->assertInstanceOf('\Geocoder\Model\Address', $result); + $this->assertEquals(18.393428, $result->getLatitude(), '', 0.01); + $this->assertEquals(-78.122906, $result->getLongitude(), '', 0.01); + $this->assertNull($result->getLocality()); + $this->assertCount(2, $result->getAdminLevels()); + $this->assertEquals('Hanover', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('Jamaica', $result->getCountry()->getName()); + + /** @var \Geocoder\Model\Address $result */ + $result = $results->get(2); + $this->assertInstanceOf('\Geocoder\Model\Address', $result); + $this->assertEquals(39.192889999999998, $result->getLatitude(), '', 0.01); + $this->assertEquals(-76.724140000000006, $result->getLongitude(), '', 0.01); + $this->assertEquals('Hanover', $result->getLocality()); + $this->assertTrue( $result->getAdminLevels()->has(4)); + $this->assertEquals('Hanover', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('United States', $result->getCountry()->getName()); + } + + public function testGeocodeWithCityDistrict() + { + if (!isset($_SERVER['MAPZEN_API_KEY'])) { + $this->markTestSkipped('You need to configure the MAPZEN_API_KEY value in phpunit.xml'); + } + + $provider = new Mapzen($this->getAdapter($_SERVER['MAPZEN_API_KEY']), $_SERVER['MAPZEN_API_KEY']); + $results = $provider->geocode('Kalbacher Hauptstraße 10, 60437 Frankfurt, Germany'); + + $this->assertInstanceOf('Geocoder\Model\AddressCollection', $results); + $this->assertCount(5, $results); + + /** @var \Geocoder\Model\Address $result */ + $result = $results->first(); + $this->assertInstanceOf('\Geocoder\Model\Address', $result); + $this->assertEquals(50.189017, $result->getLatitude(), '', 0.01); + $this->assertEquals(8.6367809999999992, $result->getLongitude(), '', 0.01); + $this->assertEquals('10a', $result->getStreetNumber()); + $this->assertEquals('Kalbacher Hauptstraße', $result->getStreetName()); + $this->assertEquals(60437, $result->getPostalCode()); + $this->assertEquals('Frankfurt am Main', $result->getLocality()); + $this->assertCount(3, $result->getAdminLevels()); + $this->assertEquals('Frankfurt am Main', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('Hessen', $result->getAdminLevels()->get(1)->getName()); + $this->assertNull($result->getAdminLevels()->get(1)->getCode()); + $this->assertEquals('Germany', $result->getCountry()->getName()); + $this->assertEquals('DEU', $result->getCountry()->getCode()); + } + + /** + * @expectedException \Geocoder\Exception\QuotaExceeded + * @expectedExceptionMessage Valid request but quota exceeded. + */ + public function testGeocodeQuotaExceeded() + { + $provider = new Mapzen( + $this->getMockAdapterReturns( + '{ + "meta": { + "version": 1, + "status_code": 429 + }, + "results": { + "error": { + "type": "QpsExceededError", + "message": "Queries per second exceeded: Queries exceeded (6 allowed)." + } + } + }' + ), + 'api_key' + ); + $provider->geocode('New York'); + } + + /** + * @expectedException \Geocoder\Exception\InvalidCredentials + * @expectedExceptionMessage Invalid or missing api key. + */ + public function testGeocodeInvalidApiKey() + { + $provider = new Mapzen( + $this->getMockAdapterReturns( + '{ + "meta": { + "version": 1, + "status_code": 403 + }, + "results": { + "error": { + "type": "KeyError", + "message": "No api_key specified." + } + } + }' + ), + 'api_key' + ); + $provider->geocode('New York'); + } + + /** + * @expectedException \Geocoder\Exception\UnsupportedOperation + * @expectedExceptionMessage The Mapzen provider does not support IP addresses, only street addresses. + */ + public function testGeocodeWithLocalhostIPv4() + { + $provider = new Mapzen($this->getMockAdapter($this->never()), 'api_key'); + $provider->geocode('127.0.0.1'); + } + + /** + * @expectedException \Geocoder\Exception\UnsupportedOperation + * @expectedExceptionMessage The Mapzen provider does not support IP addresses, only street addresses. + */ + public function testGeocodeWithLocalhostIPv6() + { + $provider = new Mapzen($this->getMockAdapter($this->never()), 'api_key'); + $provider->geocode('::1'); + } + + /** + * @expectedException \Geocoder\Exception\UnsupportedOperation + * @expectedExceptionMessage The Mapzen provider does not support IP addresses, only street addresses. + */ + public function testGeocodeWithRealIPv4() + { + $provider = new Mapzen($this->getAdapter(), 'api_key'); + $provider->geocode('74.200.247.59'); + } + + /** + * @expectedException \Geocoder\Exception\UnsupportedOperation + * @expectedExceptionMessage The Mapzen provider does not support IP addresses, only street addresses. + */ + public function testGeocodeWithRealIPv6() + { + $provider = new Mapzen($this->getAdapter(), 'api_key'); + $provider->geocode('::ffff:74.200.247.59'); + } +}