diff --git a/README.md b/README.md index 31b250196..45f1f47b5 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Provider | Package | Features | Stats [GraphHopper](https://github.com/geocoder-php/graphhopper-provider) | `geocoder-php/graphhopper-provider` | address, reverse
[Website](https://docs.graphhopper.com/#tag/Geocoding-API) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/graphhopper-provider/v/stable)](https://packagist.org/packages/geocoder-php/graphhopper-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/graphhopper-provider/downloads)](https://packagist.org/packages/geocoder-php/graphhopper-provider) [Here](https://github.com/geocoder-php/here-provider) | `geocoder-php/here-provider` | address, reverse
[Website](https://developer.here.com/documentation/geocoder/topics/quick-start-geocode.html) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/here-provider/v/stable)](https://packagist.org/packages/geocoder-php/here-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/here-provider/downloads)](https://packagist.org/packages/geocoder-php/here-provider) [LocationIQ](https://github.com/geocoder-php/locationiq-provider) | `geocoder-php/locationiq-provider` | address, reverse
[Website](https://locationiq.org/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/locationiq-provider/v/stable)](https://packagist.org/packages/geocoder-php/locationiq-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/locationiq-provider/downloads)](https://packagist.org/packages/geocoder-php/locationiq-provider) -[Mapbox](https://github.com/geocoder-php/mapbox-provider) | `geocoder-php/mapbox-provider` | address, reverse
[Website](https://www.mapbox.com/geocoding/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/mapbox-provider/v/stable)](https://packagist.org/packages/geocoder-php/mapbox-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/mapbox-provider/downloads)](https://packagist.org/packages/geocoder-php/mapbox-provider) +[Mapbox](https://github.com/geocoder-php/mapbox-provider) | `geocoder-php/mapbox-provider` | address, reverse
[Website](https://docs.mapbox.com/api/search/geocoding/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/mapbox-provider/v/stable)](https://packagist.org/packages/geocoder-php/mapbox-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/mapbox-provider/downloads)](https://packagist.org/packages/geocoder-php/mapbox-provider) [MapQuest](https://github.com/geocoder-php/mapquest-provider) | `geocoder-php/mapquest-provider` | address, reverse
[Website](http://developer.mapquest.com/web/products/dev-services/geocoding-ws) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/mapquest-provider/v/stable)](https://packagist.org/packages/geocoder-php/mapquest-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/mapquest-provider/downloads)](https://packagist.org/packages/geocoder-php/mapquest-provider) [MapTiler](https://github.com/geocoder-php/maptiler-provider) | `geocoder-php/maptiler-provider` | address, reverse
[Website](https://www.maptiler.com/cloud/geocoding/) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/maptiler-provider/v/stable)](https://packagist.org/packages/geocoder-php/maptiler-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/maptiler-provider/downloads)](https://packagist.org/packages/geocoder-php/maptiler-provider) [Nominatim](https://github.com/geocoder-php/nominatim-provider)
(OpenStreetMap) | `geocoder-php/nominatim-provider` | address, reverse
[Website](http://wiki.openstreetmap.org/wiki/Nominatim) | [![Latest Stable Version](https://poser.pugx.org/geocoder-php/nominatim-provider/v/stable)](https://packagist.org/packages/geocoder-php/nominatim-provider)
[![Total Downloads](https://poser.pugx.org/geocoder-php/nominatim-provider/downloads)](https://packagist.org/packages/geocoder-php/nominatim-provider) diff --git a/src/Provider/IP2Location/IP2Location.php b/src/Provider/IP2Location/IP2Location.php index 111401003..28972ce1c 100644 --- a/src/Provider/IP2Location/IP2Location.php +++ b/src/Provider/IP2Location/IP2Location.php @@ -102,9 +102,8 @@ private function executeQuery(string $url): AddressCollection throw new InvalidCredentials('Insufficient credits to use IP2Location service.'); } elseif (preg_match('/invalid ip address/i', $data['response'])) { throw new UnsupportedOperation('Invalid IP address.'); - } else { - throw new UnsupportedOperation(sprintf('Unexpected error: %s.', $data['response'])); } + throw new UnsupportedOperation(sprintf('Unexpected error: %s.', $data['response'])); } if (isset($data['region_name'])) { diff --git a/src/Provider/MapQuest/MapQuest.php b/src/Provider/MapQuest/MapQuest.php index 4c433467e..d3dae33db 100644 --- a/src/Provider/MapQuest/MapQuest.php +++ b/src/Provider/MapQuest/MapQuest.php @@ -157,11 +157,10 @@ public function geocodeQuery(GeocodeQuery $query): Collection $params = $this->addOptionsForGetQuery($params, $options); return $this->executeGetQuery(static::GEOCODE_ENDPOINT, $params); - } else { - $params = $this->addOptionsForPostQuery($params, $options); - - return $this->executePostQuery(static::GEOCODE_ENDPOINT, $params); } + $params = $this->addOptionsForPostQuery($params, $options); + + return $this->executePostQuery(static::GEOCODE_ENDPOINT, $params); } public function reverseQuery(ReverseQuery $query): Collection diff --git a/src/Provider/Mapbox/CHANGELOG.md b/src/Provider/Mapbox/CHANGELOG.md index 214529e6a..dd0fbf7ce 100644 --- a/src/Provider/Mapbox/CHANGELOG.md +++ b/src/Provider/Mapbox/CHANGELOG.md @@ -2,6 +2,42 @@ The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release. +## 2.0.0 + +### Added + +- Support for the Mapbox Geocoding API v6 (`/search/geocode/v6/forward` and `/search/geocode/v6/reverse`) +- v6 Structured Input: forward queries built from typed address fields via query data — `address_line1`, `address_number`, `street`, `block`, `place`, `region`, `postcode`, `locality`, `neighborhood`. When any of these is present, the query text is not sent. +- `Mapbox::TYPE_STREET` (new v6 type, added to `Mapbox::TYPES`) +- `Mapbox::TYPE_BLOCK` (Japan) and `Mapbox::TYPE_SECONDARY_ADDRESS` (US) constants (not part of `TYPES`: the API only accepts them in the corresponding regional context) +- `Mapbox::STRUCTURED_INPUT_FIELDS` constant +- Query data support: `autocomplete` (replaces `fuzzy_match`), `proximity` (`"lon,lat"` or `"ip"`), `worldview` +- New 4th constructor argument `bool $permanent` (v6 `permanent=true` result storage) +- `MapboxAddress::getMatchCode()` / `withMatchCode()` — v6 Smart Address Match object +- `MapboxAddress::getMatchConfidence()` / `withMatchConfidence()` — `exact`, `high`, `medium` or `low` +- `MapboxAddress::getAccuracy()` / `withAccuracy()` — `rooftop`, `parcel`, `point`, `interpolated`, `approximate` or `intersection` + +### Removed + +- Support for the Mapbox Geocoding API v5 (`/geocoding/v5/...`) — pin to `geocoder-php/mapbox-provider:^1.5` to stay on v5 +- `Mapbox::GEOCODE_ENDPOINT_URL_SSL` and `Mapbox::REVERSE_ENDPOINT_URL_SSL` constants (replaced by `Mapbox::FORWARD_ENDPOINT_URL` / `Mapbox::REVERSE_ENDPOINT_URL`) +- `Mapbox::GEOCODING_MODE_PLACES`, `Mapbox::GEOCODING_MODE_PLACES_PERMANENT` and `Mapbox::GEOCODING_MODES` constants (v6 has no geocoding modes; use the `permanent` constructor argument) +- `Mapbox::TYPE_POI` and `Mapbox::TYPE_POI_LANDMARK` constants (v6 does not geocode POIs; passing them as `location_type` now yields a 422 error from the API) +- `fuzzy_match` query data (v6 has no fuzzy/typo matching; use `autocomplete` for prefix-style matching) + +### Changed + +- The 4th constructor argument is now `bool $permanent = false` (was `string $geocodingMode`); passing a mode string changes behavior or errors +- `Mapbox::TYPES` no longer contains the POI types and now contains `street` +- Forward requests send the search text as the `q` query parameter instead of in the URL path +- Reverse requests send `longitude` / `latitude` query parameters (was `{lon},{lat}` in the path) +- `MapboxAddress::getId()` returns the v6 `mapbox_id` value (format changed, e.g. `dXJu...` instead of `address.123`) +- `MapboxAddress::getResultType()` values follow the v6 `feature_type` vocabulary (`street` added, `poi`/`poi.landmark` gone) +- Reverse geocoding with a `limit` greater than 1 requires a single `location_type` value (v6 API constraint: multiple types + limit returns a 422 error) +- Forward `limit` is capped at 10 by the v6 API (higher values are silently clamped) +- Invalid access tokens are now answered with HTTP 401 by the API (v5 used 403); both map to `Geocoder\Exception\InvalidCredentials` +- Geocoded data reflects the v6 dataset: coordinates, results and admin-level codes may differ from v5 + ## 1.5.0 ### Added diff --git a/src/Provider/Mapbox/Mapbox.php b/src/Provider/Mapbox/Mapbox.php index 8d78d7da5..2b8a34221 100644 --- a/src/Provider/Mapbox/Mapbox.php +++ b/src/Provider/Mapbox/Mapbox.php @@ -13,7 +13,6 @@ namespace Geocoder\Provider\Mapbox; use Geocoder\Collection; -use Geocoder\Exception\InvalidArgument; use Geocoder\Exception\InvalidServerResponse; use Geocoder\Exception\UnsupportedOperation; use Geocoder\Http\Provider\AbstractHttpProvider; @@ -30,30 +29,12 @@ final class Mapbox extends AbstractHttpProvider implements Provider /** * @var string */ - public const GEOCODE_ENDPOINT_URL_SSL = 'https://api.mapbox.com/geocoding/v5/%s/%s.json'; + public const FORWARD_ENDPOINT_URL = 'https://api.mapbox.com/search/geocode/v6/forward'; /** * @var string */ - public const REVERSE_ENDPOINT_URL_SSL = 'https://api.mapbox.com/geocoding/v5/%s/%F,%F.json'; - - /** - * @var string - */ - public const GEOCODING_MODE_PLACES = 'mapbox.places'; - - /** - * @var string - */ - public const GEOCODING_MODE_PLACES_PERMANENT = 'mapbox.places-permanent'; - - /** - * @var string[] - */ - public const GEOCODING_MODES = [ - self::GEOCODING_MODE_PLACES, - self::GEOCODING_MODE_PLACES_PERMANENT, - ]; + public const REVERSE_ENDPOINT_URL = 'https://api.mapbox.com/search/geocode/v6/reverse'; /** * @var string @@ -98,12 +79,23 @@ final class Mapbox extends AbstractHttpProvider implements Provider /** * @var string */ - public const TYPE_POI = 'poi'; + public const TYPE_STREET = 'street'; /** + * Japanese addresses only. The API accepts this type only for Japan-context requests + * (e.g. with country=jp and language=ja), so it is intentionally not part of TYPES. + * * @var string */ - public const TYPE_POI_LANDMARK = 'poi.landmark'; + public const TYPE_BLOCK = 'block'; + + /** + * Sub-unit, suite, or lot within a parent address (US only). The API accepts this type + * only for US-context requests, so it is intentionally not part of TYPES. + * + * @var string + */ + public const TYPE_SECONDARY_ADDRESS = 'secondary_address'; /** * @var string[] @@ -116,9 +108,25 @@ final class Mapbox extends AbstractHttpProvider implements Provider self::TYPE_PLACE, self::TYPE_LOCALITY, self::TYPE_NEIGHBORHOOD, + self::TYPE_STREET, self::TYPE_ADDRESS, - self::TYPE_POI, - self::TYPE_POI_LANDMARK, + ]; + + /** + * Query data keys that trigger the v6 Structured Input mode (the query text is not sent). + * + * @var string[] + */ + public const STRUCTURED_INPUT_FIELDS = [ + 'address_line1', + 'address_number', + 'street', + 'block', + 'place', + 'region', + 'postcode', + 'locality', + 'neighborhood', ]; /** @@ -137,91 +145,143 @@ final class Mapbox extends AbstractHttpProvider implements Provider private $country; /** - * @var string + * @var bool */ - private $geocodingMode; + private $permanent; /** * @param ClientInterface $client An HTTP adapter * @param string $accessToken Your Mapbox access token + * @param string|null $country Restrict results to one or more ISO 3166 alpha-2 countries (comma separated) + * @param bool $permanent Store results permanently (v6 `permanent` parameter) */ public function __construct( ClientInterface $client, string $accessToken, ?string $country = null, - string $geocodingMode = self::GEOCODING_MODE_PLACES, + bool $permanent = false, ) { parent::__construct($client); - if (!in_array($geocodingMode, self::GEOCODING_MODES)) { - throw new InvalidArgument('The Mapbox geocoding mode should be either mapbox.places or mapbox.places-permanent.'); - } - $this->accessToken = $accessToken; $this->country = $country; - $this->geocodingMode = $geocodingMode; + $this->permanent = $permanent; } public function geocodeQuery(GeocodeQuery $query): Collection { - // Mapbox API returns invalid data if IP address given - // This API doesn't handle IPs + // The Mapbox API does not geocode raw IP addresses if (filter_var($query->getText(), FILTER_VALIDATE_IP)) { throw new UnsupportedOperation('The Mapbox provider does not support IP addresses, only street addresses.'); } - $url = sprintf(self::GEOCODE_ENDPOINT_URL_SSL, $this->geocodingMode, rawurlencode($query->getText())); + $parameters = []; + + // v6 Structured Input: typed fields replace the `q` search text + $structured = $this->structuredInputFields($query); + if ([] !== $structured) { + foreach (self::STRUCTURED_INPUT_FIELDS as $field) { + if (isset($structured[$field])) { + $parameters[$field] = $structured[$field]; + } + } + } else { + $parameters['q'] = $query->getText(); + } - $urlParameters = []; if ($query->getBounds()) { // Format is "minLon,minLat,maxLon,maxLat" - $urlParameters['bbox'] = sprintf( + $parameters['bbox'] = sprintf( '%s,%s,%s,%s', - $query->getBounds()->getWest(), - $query->getBounds()->getSouth(), - $query->getBounds()->getEast(), - $query->getBounds()->getNorth() + $this->formatCoordinate($query->getBounds()->getWest()), + $this->formatCoordinate($query->getBounds()->getSouth()), + $this->formatCoordinate($query->getBounds()->getEast()), + $this->formatCoordinate($query->getBounds()->getNorth()) ); } - if (null !== $locationType = $query->getData('location_type')) { - $urlParameters['types'] = is_array($locationType) ? implode(',', $locationType) : $locationType; - } else { - $urlParameters['types'] = self::DEFAULT_TYPE; + $parameters['types'] = $this->locationTypes($query); + + if (null !== $autocomplete = $query->getData('autocomplete')) { + $parameters['autocomplete'] = $autocomplete ? 'true' : 'false'; + } elseif ([] !== $structured) { + // Mapbox recommends autocomplete=false for structured input + $parameters['autocomplete'] = 'false'; } - if (null !== $fuzzyMatch = $query->getData('fuzzy_match')) { - $urlParameters['fuzzyMatch'] = $fuzzyMatch ? 'true' : 'false'; + if (null !== $proximity = $query->getData('proximity')) { + $parameters['proximity'] = $proximity; } - if (count($urlParameters) > 0) { - $url .= '?'.http_build_query($urlParameters); + if (null !== $worldview = $query->getData('worldview')) { + $parameters['worldview'] = $worldview; } - return $this->fetchUrl($url, $query->getLimit(), $query->getLocale(), $query->getData('country', $this->country)); + return $this->fetchUrl( + self::FORWARD_ENDPOINT_URL, + $query->getLimit(), + $query->getLocale(), + $query->getData('country', $this->country), + $parameters + ); } public function reverseQuery(ReverseQuery $query): Collection { $coordinate = $query->getCoordinates(); - $url = sprintf( - self::REVERSE_ENDPOINT_URL_SSL, - $this->geocodingMode, - $coordinate->getLongitude(), - $coordinate->getLatitude() + $parameters = [ + 'longitude' => $this->formatCoordinate($coordinate->getLongitude()), + 'latitude' => $this->formatCoordinate($coordinate->getLatitude()), + ]; + + $parameters['types'] = $this->locationTypes($query); + + return $this->fetchUrl( + self::REVERSE_ENDPOINT_URL, + $query->getLimit(), + $query->getLocale(), + $query->getData('country', $this->country), + $parameters ); + } - if (null !== $locationType = $query->getData('location_type')) { - $urlParameters['types'] = is_array($locationType) ? implode(',', $locationType) : $locationType; - } else { - $urlParameters['types'] = self::DEFAULT_TYPE; + /** + * @return array + */ + private function structuredInputFields(GeocodeQuery $query): array + { + $fields = []; + + foreach (self::STRUCTURED_INPUT_FIELDS as $field) { + $value = $query->getData($field); + if (null !== $value && '' !== $value) { + $fields[$field] = $value; + } } - if (count($urlParameters) > 0) { - $url .= '?'.http_build_query($urlParameters); + return $fields; + } + + /** + * @param GeocodeQuery|ReverseQuery $query + */ + private function locationTypes($query): string + { + if (null !== $locationType = $query->getData('location_type')) { + return is_array($locationType) ? implode(',', $locationType) : $locationType; } - return $this->fetchUrl($url, $query->getLimit(), $query->getLocale(), $query->getData('country', $this->country)); + return self::DEFAULT_TYPE; + } + + /** + * Format a coordinate with the shortest decimal representation that round-trips the + * value exactly (a plain (string) cast truncates to the 14 significant digits of the + * default `precision` ini setting, which would change the request URL). + */ + private function formatCoordinate(float $value): string + { + return (string) json_encode($value); } public function getName(): string @@ -230,25 +290,35 @@ public function getName(): string } /** - * @return string query with extra params + * @param array $parameters */ - private function buildQuery(string $url, int $limit, ?string $locale = null, ?string $country = null): string + private function buildQuery(string $url, int $limit, ?string $locale, ?string $country, array $parameters): string { - $parameters = array_filter([ - 'country' => $country, - 'language' => $locale, - 'limit' => $limit, - 'access_token' => $this->accessToken, - ]); + if (null !== $country) { + $parameters['country'] = $country; + } - $separator = parse_url($url, PHP_URL_QUERY) ? '&' : '?'; + if (null !== $locale) { + $parameters['language'] = $locale; + } + + $parameters['limit'] = $limit; + + if ($this->permanent) { + $parameters['permanent'] = 'true'; + } + + $parameters['access_token'] = $this->accessToken; - return $url.$separator.http_build_query($parameters); + return $url.'?'.http_build_query($parameters); } - private function fetchUrl(string $url, int $limit, ?string $locale = null, ?string $country = null): AddressCollection + /** + * @param array $parameters + */ + private function fetchUrl(string $url, int $limit, ?string $locale, ?string $country, array $parameters): AddressCollection { - $url = $this->buildQuery($url, $limit, $locale, $country); + $url = $this->buildQuery($url, $limit, $locale, $country, $parameters); $content = $this->getUrlContents($url); $json = $this->validateResponse($url, $content); @@ -259,103 +329,126 @@ private function fetchUrl(string $url, int $limit, ?string $locale = null, ?stri $results = []; foreach ($json['features'] as $result) { - if (!array_key_exists('context', $result)) { + $results[] = $this->parseFeature($result); + + if (count($results) >= $limit) { break; } + } - $builder = new AddressBuilder($this->getName()); - $this->parseCoordinates($builder, $result); + return new AddressCollection($results); + } - // set official Mapbox place id - if (isset($result['id'])) { - $builder->setValue('id', $result['id']); - } + /** + * @param array $result + */ + private function parseFeature(array $result): MapboxAddress + { + $properties = $result['properties'] ?? []; + $context = $properties['context'] ?? []; - // set official Mapbox place id - if (isset($result['text'])) { - $builder->setValue('street_name', $result['text']); - } + $builder = new AddressBuilder($this->getName()); + $this->parseCoordinates($builder, $result); - // update address components - foreach ($result['context'] as $component) { - $this->updateAddressComponent($builder, $component['id'], $component); + // update address components (context is an object keyed by feature type in v6) + foreach ($context as $type => $component) { + if (is_array($component)) { + $this->updateAddressComponent($builder, (string) $type, $component); } + } - /** @var MapboxAddress $address */ - $address = $builder->build(MapboxAddress::class); - $address = $address->withId($builder->getValue('id')); - if (isset($result['address'])) { - $address = $address->withStreetNumber($result['address']); - } - if (isset($result['place_type'])) { - $address = $address->withResultType($result['place_type']); - } - if (isset($result['place_name'])) { - $address = $address->withFormattedAddress($result['place_name']); - } - $address = $address->withStreetName($builder->getValue('street_name')); - $address = $address->withNeighborhood($builder->getValue('neighborhood')); - $results[] = $address; + /** @var MapboxAddress $address */ + $address = $builder->build(MapboxAddress::class); - if (count($results) >= $limit) { - break; + if (isset($properties['mapbox_id'])) { + $address = $address->withId((string) $properties['mapbox_id']); + } elseif (isset($result['id'])) { + $address = $address->withId((string) $result['id']); + } + + // street name without the house number (v5 semantics) + $streetName = $context['address']['street_name'] ?? $context['street']['name'] ?? $properties['name'] ?? null; + if (null !== $streetName) { + $address = $address->withStreetName((string) $streetName); + } + + $streetNumber = $context['address']['address_number'] ?? null; + if (null !== $streetNumber) { + $address = $address->withStreetNumber((string) $streetNumber); + } + + if (isset($properties['feature_type'])) { + $address = $address->withResultType([(string) $properties['feature_type']]); + } + + if (isset($properties['full_address'])) { + $address = $address->withFormattedAddress((string) $properties['full_address']); + } + + $neighborhood = $context['neighborhood']['name'] ?? null; + if (null !== $neighborhood && '' !== $neighborhood) { + $address = $address->withNeighborhood((string) $neighborhood); + } + + if (isset($properties['match_code']) && is_array($properties['match_code'])) { + $address = $address->withMatchCode($properties['match_code']); + $confidence = $properties['match_code']['confidence'] ?? null; + if (null !== $confidence) { + $address = $address->withMatchConfidence((string) $confidence); } } - return new AddressCollection($results); + if (isset($properties['coordinates']['accuracy'])) { + $address = $address->withAccuracy((string) $properties['coordinates']['accuracy']); + } + + return $address; } /** * Update current resultSet with given key/value. * - * @param string $type Component type - * @param array $value Component value + * @param array $component */ - private function updateAddressComponent(AddressBuilder $builder, string $type, array $value): void + private function updateAddressComponent(AddressBuilder $builder, string $type, array $component): void { - $typeParts = explode('.', $type); - $type = reset($typeParts); + if (!isset($component['name']) || '' === $component['name']) { + return; + } switch ($type) { case 'postcode': - $builder->setPostalCode($value['text']); + $builder->setPostalCode($component['name']); break; case 'locality': - $builder->setLocality($value['text']); + $builder->setLocality($component['name']); break; case 'country': - $builder->setCountry($value['text']); - if (isset($value['short_code'])) { - $builder->setCountryCode(strtoupper($value['short_code'])); + $builder->setCountry($component['name']); + if (isset($component['country_code'])) { + $builder->setCountryCode(strtoupper((string) $component['country_code'])); } break; - case 'neighborhood': - $builder->setValue($type, $value['text']); - - break; - case 'place': - $builder->addAdminLevel(1, $value['text']); - $builder->setLocality($value['text']); + $builder->addAdminLevel(1, $component['name']); + $builder->setLocality($component['name']); break; case 'region': - $code = null; - if (!empty($value['short_code']) && preg_match('/[A-z]{2}-/', $value['short_code'])) { - $code = preg_replace('/[A-z]{2}-/', '', $value['short_code']); - } - $builder->addAdminLevel(2, $value['text'], $code); + $code = isset($component['region_code']) ? (string) $component['region_code'] : null; + $builder->addAdminLevel(2, $component['name'], $code); break; default: + // address, street, district, neighborhood: handled (or intentionally ignored) elsewhere } } diff --git a/src/Provider/Mapbox/Model/MapboxAddress.php b/src/Provider/Mapbox/Model/MapboxAddress.php index b767f3249..cfb51ad08 100644 --- a/src/Provider/Mapbox/Model/MapboxAddress.php +++ b/src/Provider/Mapbox/Model/MapboxAddress.php @@ -46,6 +46,21 @@ final class MapboxAddress extends Address */ private $neighborhood; + /** + * @var array|null + */ + private $matchCode; + + /** + * @var string|null + */ + private $matchConfidence; + + /** + * @var string|null + */ + private $accuracy; + public function withId(?string $id = null): self { $new = clone $this; @@ -132,4 +147,49 @@ public function withNeighborhood(?string $neighborhood = null): self return $new; } + + /** + * @return array|null + */ + public function getMatchCode(): ?array + { + return $this->matchCode; + } + + /** + * @param array|null $matchCode + */ + public function withMatchCode(?array $matchCode = null): self + { + $new = clone $this; + $new->matchCode = $matchCode; + + return $new; + } + + public function getMatchConfidence(): ?string + { + return $this->matchConfidence; + } + + public function withMatchConfidence(?string $matchConfidence = null): self + { + $new = clone $this; + $new->matchConfidence = $matchConfidence; + + return $new; + } + + public function getAccuracy(): ?string + { + return $this->accuracy; + } + + public function withAccuracy(?string $accuracy = null): self + { + $new = clone $this; + $new->accuracy = $accuracy; + + return $new; + } } diff --git a/src/Provider/Mapbox/Readme.md b/src/Provider/Mapbox/Readme.md index ebfbe29e6..d9815823d 100644 --- a/src/Provider/Mapbox/Readme.md +++ b/src/Provider/Mapbox/Readme.md @@ -20,6 +20,46 @@ composer require geocoder-php/mapbox-provider A valid `Access Token` is required for Mapbox. +### Usage + +This provider targets the **Mapbox Geocoding API v6**. If you rely on the v5 API, pin +`geocoder-php/mapbox-provider` to `^1.5`. + +```php +$provider = new Mapbox($client, $accessToken); +// optional: country filter (ISO 3166 alpha-2) and permanent result storage +$provider = new Mapbox($client, $accessToken, 'US', true); + +// Forward geocoding +$provider->geocodeQuery(GeocodeQuery::create('149 9th St, San Francisco, CA 94103')); + +// Forward geocoding with options (query data) +$query = GeocodeQuery::create('washi') + ->withData('autocomplete', true) // prefix-style matching (on by default) + ->withData('location_type', Mapbox::TYPE_STREET) // or an array of Mapbox::TYPE_* constants + ->withData('proximity', '-120.09,47.60') // or 'ip' + ->withData('worldview', 'us') + ->withData('country', 'US'); + +// v6 Structured Input: typed fields replace the free-text query (the text is not sent) +$query = GeocodeQuery::create('2595 Lucky John Dr, Park City, UT 84060') + ->withData('address_number', '2595') + ->withData('street', 'Lucky John Dr') + ->withData('place', 'Park City') + ->withData('region', 'UT') + ->withData('postcode', '84060'); +// Any of address_line1, address_number, street, block, place, region, postcode, +// locality, neighborhood triggers Structured Input; autocomplete defaults to false. + +// Reverse geocoding +$provider->reverseQuery(ReverseQuery::fromCoordinates(48.8631507, 2.388911)); +``` + +Results are `Geocoder\Provider\Mapbox\Model\MapboxAddress` instances. Besides the regular +address data they expose `getId()`, `getStreetName()`, `getStreetNumber()`, +`getResultType()`, `getFormattedAddress()`, `getNeighborhood()`, +`getMatchCode()` / `getMatchConfidence()` (v6 Smart Address Match) and `getAccuracy()`. + ### Contribute Contributions are very welcome! Send a pull request to the [main repository](https://github.com/geocoder-php/Geocoder) or diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_06551ee827f3b9635793737514ec6b9d368075c4 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_06551ee827f3b9635793737514ec6b9d368075c4 new file mode 100644 index 000000000..64d3405cb --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_06551ee827f3b9635793737514ec6b9d368075c4 @@ -0,0 +1 @@ +s:2020:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"dXJuOm1ieGFkcjozOGY3OTg1OC1jNzY0LTQ4ZGUtYTFmMC04NjJjOTM1ZWViMjc","geometry":{"type":"Point","coordinates":[-111.507008,40.6716]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjozOGY3OTg1OC1jNzY0LTQ4ZGUtYTFmMC04NjJjOTM1ZWViMjc","feature_type":"address","full_address":"2595 Lucky John Drive, Park City, Utah 84060, United States","name":"2595 Lucky John Drive","name_preferred":"2595 Lucky John Drive","coordinates":{"longitude":-111.507008,"latitude":40.6716,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":40.6716,"longitude":-111.506529}]},"place_formatted":"Park City, Utah 84060, United States","match_code":{"address_number":"matched","street":"matched","postcode":"matched","place":"matched","region":"matched","locality":"not_applicable","country":"inferred","confidence":"exact"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjozOGY3OTg1OC1jNzY0LTQ4ZGUtYTFmMC04NjJjOTM1ZWViMjc","address_number":"2595","street_name":"Lucky John Drive","name":"2595 Lucky John Drive"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6MzhmNzk4NTgtYzc2NC00OGRlLWExZjAtODYyYzkzNWVlYjI3","name":"Lucky John Drive"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpITktzN0E","name":"Park Meadows"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFUjNPN0E","name":"84060"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpEdjlvN0E","name":"Park City","wikidata_id":"Q482993"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpBVlRHN0E","name":"Summit County","wikidata_id":"Q484563"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCa1Rz","name":"Utah","wikidata_id":"Q829","region_code":"UT","region_code_full":"US-UT"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_20d856dd6d6ae671b181193de4e52f7fb651fd97 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_20d856dd6d6ae671b181193de4e52f7fb651fd97 deleted file mode 100644 index 8a7277674..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_20d856dd6d6ae671b181193de4e52f7fb651fd97 +++ /dev/null @@ -1 +0,0 @@ -s:967:"{"type":"FeatureCollection","query":["princ"],"features":[{"id":"place.4899176537126140","type":"Feature","place_type":["place"],"relevance":1,"properties":{"wikidata":"Q235"},"text_it":"Principato di Monaco","language_it":"it","place_name_it":"Principato di Monaco, Principato di Monaco","text":"Principato di Monaco","language":"it","place_name":"Principato di Monaco, Principato di Monaco","bbox":[7.408977,43.724643,7.440014,43.751895],"center":[7.41974,43.73125],"geometry":{"type":"Point","coordinates":[7.41974,43.73125]},"context":[{"id":"country.3435803554126140","wikidata":"Q235","text_it":"Principato di Monaco","language_it":"it","text":"Principato di Monaco","language":"it"}]}],"attribution":"NOTICE: © 2020 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_27f7da637a8e576c59a3128575847a7abc2d13ba b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_27f7da637a8e576c59a3128575847a7abc2d13ba new file mode 100644 index 000000000..867689ad1 --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_27f7da637a8e576c59a3128575847a7abc2d13ba @@ -0,0 +1 @@ +s:285:"{"type":"FeatureCollection","features":[],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_338a05e2ceeb9a75e55774746945065683127870 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_338a05e2ceeb9a75e55774746945065683127870 new file mode 100644 index 000000000..4f1aed58f --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_338a05e2ceeb9a75e55774746945065683127870 @@ -0,0 +1 @@ +s:5571:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"dXJuOm1ieHBsYzpBUVRz","geometry":{"type":"Point","coordinates":[-120.094293,48.025005]},"properties":{"mapbox_id":"dXJuOm1ieHBsYzpBUVRz","feature_type":"region","full_address":"Washington, United States","name":"Washington","name_preferred":"Washington","coordinates":{"longitude":-120.094293,"latitude":48.025005},"place_formatted":"United States","bbox":[-124.861672,45.543637,-116.916072,49.002595],"context":{"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpBUVRz","name":"Washington","region_code":"WA","region_code_full":"US-WA","wikidata_id":"Q1223"}}}},{"type":"Feature","id":"dXJuOm1ieHBsYzpLU3RzN0E","geometry":{"type":"Point","coordinates":[-120.482925,46.59803]},"properties":{"mapbox_id":"dXJuOm1ieHBsYzpLU3RzN0E","feature_type":"neighborhood","full_address":"Washington Park, Yakima, Washington, United States","name":"Washington Park","name_preferred":"Washington Park","coordinates":{"longitude":-120.482925,"latitude":46.59803},"place_formatted":"Yakima, Washington, United States","bbox":[-120.494858,46.592164,-120.481383,46.601423],"context":{"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFN1B1N0E","name":"98901"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpGZE1JN0E","name":"Yakima","wikidata_id":"Q499203","alternate":{"mapbox_id":"dXJuOm1ieHBsYzpFKy9vN0E","name":"Union Gap"}},"district":{"mapbox_id":"dXJuOm1ieHBsYzpBWVdHN0E","name":"Yakima County","wikidata_id":"Q156629"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpBUVRz","name":"Washington","wikidata_id":"Q1223","region_code":"WA","region_code_full":"US-WA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpLU3RzN0E","name":"Washington Park"}}}},{"type":"Feature","id":"dXJuOm1ieHBsYzpMcDhzN0E","geometry":{"type":"Point","coordinates":[-123.04517,48.07898]},"properties":{"mapbox_id":"dXJuOm1ieHBsYzpMcDhzN0E","feature_type":"neighborhood","full_address":"Washington Harbor, Sequim, Washington, United States","name":"Washington Harbor","name_preferred":"Washington Harbor","coordinates":{"longitude":-123.04517,"latitude":48.07898},"place_formatted":"Sequim, Washington, United States","bbox":[-123.051913,48.07448,-123.038438,48.083482],"context":{"place":{"mapbox_id":"dXJuOm1ieHBsYzpFY2RJN0E","name":"Sequim","wikidata_id":"Q1514115"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpRTWJz","name":"Clallam County","wikidata_id":"Q156306"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpBUVRz","name":"Washington","wikidata_id":"Q1223","region_code":"WA","region_code_full":"US-WA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpMcDhzN0E","name":"Washington Harbor"}}}},{"type":"Feature","id":"dXJuOm1ieGFkci1zdHI6ZGNjNjFmZjctZDkwZi00N2U5LTg2OGMtNTMyMWFlZWYyZmY5","geometry":{"type":"Point","coordinates":[-123.381214,48.444226]},"properties":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6ZGNjNjFmZjctZDkwZi00N2U5LTg2OGMtNTMyMWFlZWYyZmY5","feature_type":"street","full_address":"Washington Avenue, Victoria, British Columbia V9A 1P7, Canada","name":"Washington Avenue","name_preferred":"Washington Avenue","coordinates":{"longitude":-123.381214,"latitude":48.444226},"place_formatted":"Victoria, British Columbia V9A 1P7, Canada","context":{"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6ZGNjNjFmZjctZDkwZi00N2U5LTg2OGMtNTMyMWFlZWYyZmY5","name":"Washington Avenue"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpNQ3du","name":"Burnside"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpBYVlQYmlj","name":"V9A 1P7"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpCMTVJSnc","name":"Victoria","wikidata_id":"Q2132"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpBcVlu","name":"Capital Regional District","wikidata_id":"Q550219"},"region":{"mapbox_id":"dXJuOm1ieHBsYzo1Q2M","name":"British Columbia","wikidata_id":"Q1973","region_code":"BC","region_code_full":"CA-BC"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJaWM","name":"Canada","wikidata_id":"Q16","country_code":"CA","country_code_alpha_3":"CAN"}}}},{"type":"Feature","id":"address.7607992201284362","geometry":{"type":"Point","coordinates":[-117.039767,46.930253]},"properties":{"mapbox_id":"address.7607992201284362","feature_type":"street","full_address":"Washington Highway 6, Palouse, Washington 99161, United States","name":"Washington Highway 6","name_preferred":"Washington Highway 6","coordinates":{"longitude":-117.039767,"latitude":46.930253},"place_formatted":"Palouse, Washington 99161, United States","context":{"street":{"mapbox_id":"address.7607992201284362","name":"Washington Highway 6"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFOEtPN0E","name":"99161"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpEdkVvN0E","name":"Palouse"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpBWHpHN0E","name":"Whitman County","wikidata_id":"Q484153"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpBUVRz","name":"Washington","wikidata_id":"Q1223","region_code":"WA","region_code_full":"US-WA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_436e84f1a3531213304e67e5bca76e7550349a2a b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_436e84f1a3531213304e67e5bca76e7550349a2a deleted file mode 100644 index 46df4575c..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_436e84f1a3531213304e67e5bca76e7550349a2a +++ /dev/null @@ -1 +0,0 @@ -s:331:"{"type":"FeatureCollection","query":["jsajhgsdkfjhsfkjhaldkadjaslgldasd"],"features":[],"attribution":"NOTICE: © 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5c71bf49f4586edeacc48e9b5d1ab218054d423d b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5c71bf49f4586edeacc48e9b5d1ab218054d423d new file mode 100644 index 000000000..86e710744 --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5c71bf49f4586edeacc48e9b5d1ab218054d423d @@ -0,0 +1 @@ +s:10311:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"dXJuOm1ieGFkcjo2YjE5MDRmMi1lYjBkLTRjZDQtODViZC1mNmUzZmI1ZTNiZWE","geometry":{"type":"Point","coordinates":[-0.12767,51.50354]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjo2YjE5MDRmMi1lYjBkLTRjZDQtODViZC1mNmUzZmI1ZTNiZWE","feature_type":"address","full_address":"10 Downing Street, City of Westminster, London, SW1A 2AA, United Kingdom","name":"10 Downing Street","name_preferred":"10 Downing Street","coordinates":{"longitude":-0.12767,"latitude":51.50354,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":51.503257,"longitude":-0.12772}]},"place_formatted":"City of Westminster, London, SW1A 2AA, United Kingdom","match_code":{"address_number":"matched","street":"matched","postcode":"unmatched","place":"matched","region":"not_applicable","locality":"unmatched","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjo2YjE5MDRmMi1lYjBkLTRjZDQtODViZC1mNmUzZmI1ZTNiZWE","address_number":"10","street_name":"Downing Street","name":"10 Downing Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6NmIxOTA0ZjItZWIwZC00Y2Q0LTg1YmQtZjZlM2ZiNWUzYmVh","name":"Downing Street"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpBeFlNVHc","name":"Whitehall","translations":{"en":{"language":"en","name":"Whitehall"}}},"postcode":{"mapbox_id":"postcode.8654501461090586","name":"SW1A 2AA"},"locality":{"mapbox_id":"dXJuOm1ieHBsYzpDM3RLVHc","name":"City of Westminster","wikidata_id":"Q179351","translations":{"en":{"language":"en","name":"City of Westminster"}}},"place":{"mapbox_id":"dXJuOm1ieHBsYzphaWhQ","name":"London","wikidata_id":"Q84","translations":{"en":{"language":"en","name":"London"}}},"district":{"mapbox_id":"dXJuOm1ieHBsYzpDUVpQ","name":"Greater London","wikidata_id":"Q23306","translations":{"en":{"language":"en","name":"Greater London"}}},"region":{"mapbox_id":"dXJuOm1ieHBsYzpKRTg","name":"England","wikidata_id":"Q21","region_code":"ENG","region_code_full":"GB-ENG","translations":{"en":{"language":"en","name":"England"}}},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazg","name":"United Kingdom","wikidata_id":"Q145","country_code":"GB","country_code_alpha_3":"GBR","translations":{"en":{"language":"en","name":"United Kingdom"}}}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjpjZDYxNzhjMS02NDhhLTQ4OWItYTA2ZS1mYTkzZTExZmU2NDA","geometry":{"type":"Point","coordinates":[0.066,51.51288]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjpjZDYxNzhjMS02NDhhLTQ4OWItYTA2ZS1mYTkzZTExZmU2NDA","feature_type":"address","full_address":"10 Downings, London Borough of Newham, London, E6 6WP, United Kingdom","name":"10 Downings","name_preferred":"10 Downings","coordinates":{"longitude":0.066,"latitude":51.51288,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":51.512731,"longitude":0.065978}]},"place_formatted":"London Borough of Newham, London, E6 6WP, United Kingdom","match_code":{"address_number":"matched","street":"matched","postcode":"unmatched","place":"matched","region":"not_applicable","locality":"unmatched","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjpjZDYxNzhjMS02NDhhLTQ4OWItYTA2ZS1mYTkzZTExZmU2NDA","address_number":"10","street_name":"Downings","name":"10 Downings"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6Y2Q2MTc4YzEtNjQ4YS00ODliLWEwNmUtZmE5M2UxMWZlNjQw","name":"Downings"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzoyRXhQ","name":"East Ham","translations":{"en":{"language":"en","name":"East Ham"}}},"postcode":{"mapbox_id":"postcode.5087212628037556","name":"E6 6WP"},"locality":{"mapbox_id":"dXJuOm1ieHBsYzpCN1JxVHc","name":"London Borough of Newham","wikidata_id":"Q208139","translations":{"en":{"language":"en","name":"London Borough of Newham"}}},"place":{"mapbox_id":"dXJuOm1ieHBsYzphaWhQ","name":"London","wikidata_id":"Q84","translations":{"en":{"language":"en","name":"London"}}},"district":{"mapbox_id":"dXJuOm1ieHBsYzpDUVpQ","name":"Greater London","wikidata_id":"Q23306","translations":{"en":{"language":"en","name":"Greater London"}}},"region":{"mapbox_id":"dXJuOm1ieHBsYzpKRTg","name":"England","wikidata_id":"Q21","region_code":"ENG","region_code_full":"GB-ENG","translations":{"en":{"language":"en","name":"England"}}},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazg","name":"United Kingdom","wikidata_id":"Q145","country_code":"GB","country_code_alpha_3":"GBR","translations":{"en":{"language":"en","name":"United Kingdom"}}}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjo2MWJmMDJlMC04Yzk5LTRjMjItYjAwYS1jOTYxMWNmYmRmNmE","geometry":{"type":"Point","coordinates":[0.12269,52.20363]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjo2MWJmMDJlMC04Yzk5LTRjMjItYjAwYS1jOTYxMWNmYmRmNmE","feature_type":"address","full_address":"10 Downing Street, Cambridge, CB2 3DS, United Kingdom","name":"10 Downing Street","name_preferred":"10 Downing Street","coordinates":{"longitude":0.12269,"latitude":52.20363,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":52.203383,"longitude":0.122846}]},"place_formatted":"Cambridge, CB2 3DS, United Kingdom","match_code":{"address_number":"matched","street":"matched","postcode":"unmatched","place":"unmatched","region":"not_applicable","locality":"not_applicable","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjo2MWJmMDJlMC04Yzk5LTRjMjItYjAwYS1jOTYxMWNmYmRmNmE","address_number":"10","street_name":"Downing Street","name":"10 Downing Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6NjFiZjAyZTAtOGM5OS00YzIyLWIwMGEtYzk2MTFjZmJkZjZh","name":"Downing Street"},"postcode":{"mapbox_id":"postcode.5786147553339014","name":"CB2 3DS"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpJZ2hQ","name":"Cambridge","wikidata_id":"Q350","translations":{"en":{"language":"en","name":"Cambridge"}}},"district":{"mapbox_id":"dXJuOm1ieHBsYzpBd1pQ","name":"Cambridgeshire","wikidata_id":"Q23112","translations":{"en":{"language":"en","name":"Cambridgeshire"}}},"region":{"mapbox_id":"dXJuOm1ieHBsYzpKRTg","name":"England","wikidata_id":"Q21","region_code":"ENG","region_code_full":"GB-ENG","translations":{"en":{"language":"en","name":"England"}}},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazg","name":"United Kingdom","wikidata_id":"Q145","country_code":"GB","country_code_alpha_3":"GBR","translations":{"en":{"language":"en","name":"United Kingdom"}}}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjo5MTRjM2RjMy04M2E2LTQzNTgtYjg0YS0xYzk4YWRlNGQ2NGU","geometry":{"type":"Point","coordinates":[-0.79926,51.21331]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjo5MTRjM2RjMy04M2E2LTQzNTgtYjg0YS0xYzk4YWRlNGQ2NGU","feature_type":"address","full_address":"10 Downing Street, Farnham, GU9 7PB, United Kingdom","name":"10 Downing Street","name_preferred":"10 Downing Street","coordinates":{"longitude":-0.79926,"latitude":51.21331,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":51.213331,"longitude":-0.79914}]},"place_formatted":"Farnham, GU9 7PB, United Kingdom","match_code":{"address_number":"matched","street":"matched","postcode":"unmatched","place":"unmatched","region":"not_applicable","locality":"not_applicable","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjo5MTRjM2RjMy04M2E2LTQzNTgtYjg0YS0xYzk4YWRlNGQ2NGU","address_number":"10","street_name":"Downing Street","name":"10 Downing Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6OTE0YzNkYzMtODNhNi00MzU4LWI4NGEtMWM5OGFkZTRkNjRl","name":"Downing Street"},"postcode":{"mapbox_id":"postcode.5586436697038858","name":"GU9 7PB"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpQc2hQ","name":"Farnham","wikidata_id":"Q643160","translations":{"en":{"language":"en","name":"Farnham"}}},"district":{"mapbox_id":"dXJuOm1ieHBsYzpFcVpQ","name":"Surrey","wikidata_id":"Q23276","translations":{"en":{"language":"en","name":"Surrey"}}},"region":{"mapbox_id":"dXJuOm1ieHBsYzpKRTg","name":"England","wikidata_id":"Q21","region_code":"ENG","region_code_full":"GB-ENG","translations":{"en":{"language":"en","name":"England"}}},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazg","name":"United Kingdom","wikidata_id":"Q145","country_code":"GB","country_code_alpha_3":"GBR","translations":{"en":{"language":"en","name":"United Kingdom"}}}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjphYjdkZjY0MC03OTA5LTRjZTktOWEyOC01NGQ3MjIwN2IxMWE","geometry":{"type":"Point","coordinates":[-1.20259,53.00619]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjphYjdkZjY0MC03OTA5LTRjZTktOWEyOC01NGQ3MjIwN2IxMWE","feature_type":"address","full_address":"10 Downing Street, Nottingham, NG6 8JU, United Kingdom","name":"10 Downing Street","name_preferred":"10 Downing Street","coordinates":{"longitude":-1.20259,"latitude":53.00619,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":53.0062,"longitude":-1.202407}]},"place_formatted":"Nottingham, NG6 8JU, United Kingdom","match_code":{"address_number":"matched","street":"matched","postcode":"unmatched","place":"unmatched","region":"not_applicable","locality":"not_applicable","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjphYjdkZjY0MC03OTA5LTRjZTktOWEyOC01NGQ3MjIwN2IxMWE","address_number":"10","street_name":"Downing Street","name":"10 Downing Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6YWI3ZGY2NDAtNzkwOS00Y2U5LTlhMjgtNTRkNzIyMDdiMTFh","name":"Downing Street"},"postcode":{"mapbox_id":"postcode.5551195545198608","name":"NG6 8JU"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpmVWhQ","name":"Nottingham","wikidata_id":"Q41262","translations":{"en":{"language":"en","name":"Nottingham"}}},"district":{"mapbox_id":"dXJuOm1ieHBsYzpCS1pQ","name":"City of Nottingham","wikidata_id":"Q21885994","translations":{"en":{"language":"en","name":"City of Nottingham"}}},"region":{"mapbox_id":"dXJuOm1ieHBsYzpKRTg","name":"England","wikidata_id":"Q21","region_code":"ENG","region_code_full":"GB-ENG","translations":{"en":{"language":"en","name":"England"}}},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazg","name":"United Kingdom","wikidata_id":"Q145","country_code":"GB","country_code_alpha_3":"GBR","translations":{"en":{"language":"en","name":"United Kingdom"}}}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5e373c440fdae88e9ec714d42d85489c9986ab7c b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5e373c440fdae88e9ec714d42d85489c9986ab7c deleted file mode 100644 index 0bcf04c1b..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5e373c440fdae88e9ec714d42d85489c9986ab7c +++ /dev/null @@ -1 +0,0 @@ -s:4034:"{"type":"FeatureCollection","query":["wahsington"],"features":[{"id":"address.3196918775570688","type":"Feature","place_type":["address"],"relevance":0.95,"properties":{"accuracy":"street"},"text":"Washington Street","place_name":"Washington Street, Sumas, Washington 98295, United States","center":[-122.2718746,49.0017164],"geometry":{"type":"Point","coordinates":[-122.2718746,49.0017164]},"context":[{"id":"postcode.1103001428069280","text":"98295"},{"id":"place.10997180196070370","wikidata":"Q1510124","text":"Sumas"},{"id":"region.9713796497246050","wikidata":"Q1223","short_code":"US-WA","text":"Washington"},{"id":"country.19678805456372290","wikidata":"Q30","short_code":"us","text":"United States"}]},{"id":"address.1946746068053092","type":"Feature","place_type":["address"],"relevance":0.95,"properties":{"accuracy":"street"},"text":"Washington Avenue","place_name":"Washington Avenue, Victoria, British Columbia V9A 1L5, Canada","matching_text":"Washington Ave E","matching_place_name":"Washington Ave E, Victoria, British Columbia V9A 1L5, Canada","center":[-123.380986,48.4440317],"geometry":{"type":"Point","coordinates":[-123.380986,48.4440317]},"context":[{"id":"neighborhood.11535041776736560","text":"Burnside"},{"id":"postcode.7635888694089700","text":"V9A 1L5"},{"id":"place.7877779600899450","wikidata":"Q2132","text":"Victoria"},{"id":"region.9984400673322020","wikidata":"Q1974","short_code":"CA-BC","text":"British Columbia"},{"id":"country.10278600750587150","wikidata":"Q16","short_code":"ca","text":"Canada"}]},{"id":"address.499813899464900","type":"Feature","place_type":["address"],"relevance":0.95,"properties":{"accuracy":"street"},"text":"Washington Highway 6","place_name":"Washington Highway 6, Palouse, Washington 99161, United States","center":[-117.0397671,46.9302529],"geometry":{"type":"Point","coordinates":[-117.0397671,46.9302529]},"context":[{"id":"postcode.12946567993911350","text":"99161"},{"id":"place.13856508424544360","text":"Palouse"},{"id":"region.9713796497246050","wikidata":"Q1223","short_code":"US-WA","text":"Washington"},{"id":"country.19678805456372290","wikidata":"Q30","short_code":"us","text":"United States"}]},{"id":"address.8713060929842858","type":"Feature","place_type":["address"],"relevance":0.95,"properties":{"accuracy":"street"},"text":"Down River Road","place_name":"Down River Road, Lewiston, Washington 83501, United States","matching_text":"Washington Highway 128","matching_place_name":"Washington Highway 128, Lewiston, Washington 83501, United States","center":[-117.0397913,46.4312588],"geometry":{"type":"Point","coordinates":[-117.0397913,46.4312588]},"context":[{"id":"neighborhood.278688","text":"Transfer"},{"id":"postcode.11154056676467040","text":"83501"},{"id":"place.9371029782746440","wikidata":"Q505539","text":"Lewiston"},{"id":"region.9713796497246050","wikidata":"Q1223","short_code":"US-WA","text":"Washington"},{"id":"country.19678805456372290","wikidata":"Q30","short_code":"us","text":"United States"}]},{"id":"address.8337368900196888","type":"Feature","place_type":["address"],"relevance":0.95,"properties":{"accuracy":"street"},"text":"South Washington Street","place_name":"South Washington Street, Moscow, Idaho 83843, United States","matching_text":"Washington","matching_place_name":"Washington, Moscow, Idaho 83843, United States","center":[-116.9997431,46.7299485],"geometry":{"type":"Point","coordinates":[-116.9997431,46.7299485]},"context":[{"id":"postcode.10023543810932580","text":"83843"},{"id":"place.19031168784618380","wikidata":"Q499927","text":"Moscow"},{"id":"region.9862000087605220","wikidata":"Q1221","short_code":"US-ID","text":"Idaho"},{"id":"country.19678805456372290","wikidata":"Q30","short_code":"us","text":"United States"}]}],"attribution":"NOTICE: © 2020 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5e53474a50aa75267953e6d90b2e3472021efbf2 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5e53474a50aa75267953e6d90b2e3472021efbf2 new file mode 100644 index 000000000..3de4f2cbd --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_5e53474a50aa75267953e6d90b2e3472021efbf2 @@ -0,0 +1 @@ +s:11512:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"dXJuOm1ieGFkcjo3Njg3YjZmNy01YmZkLTQzMjItOGMzOS02OGE1NDhmZWYwM2U","geometry":{"type":"Point","coordinates":[-122.413709,37.7757]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjo3Njg3YjZmNy01YmZkLTQzMjItOGMzOS02OGE1NDhmZWYwM2U","feature_type":"address","full_address":"149 9th Street, San Francisco, California 94103, United States","name":"149 9th Street","name_preferred":"149 9th Street","coordinates":{"longitude":-122.413709,"latitude":37.7757,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":37.775569,"longitude":-122.413874}]},"place_formatted":"San Francisco, California 94103, United States","match_code":{"address_number":"matched","street":"matched","postcode":"matched","place":"matched","region":"matched","locality":"not_applicable","country":"inferred","confidence":"exact"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjo3Njg3YjZmNy01YmZkLTQzMjItOGMzOS02OGE1NDhmZWYwM2U","address_number":"149","street_name":"9th Street","name":"149 9th Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6NzY4N2I2ZjctNWJmZC00MzIyLThjMzktNjhhNTQ4ZmVmMDNl","name":"9th Street"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpJOWtzN0E","name":"South of Market","alternate":{"mapbox_id":"dXJuOm1ieHBsYzpCdi9zN0E","name":"Civic Center","wikidata_id":"Q267874"}},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFcDlPN0E","name":"94103"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpFVzBJN0E","name":"San Francisco","wikidata_id":"Q62"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpBVG1HN0E","name":"San Francisco County","wikidata_id":"Q62"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCbVRz","name":"California","wikidata_id":"Q99","region_code":"CA","region_code_full":"US-CA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}},{"type":"Feature","id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDox","geometry":{"type":"Point","coordinates":[-122.360907,37.932889]},"properties":{"mapbox_id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDox","feature_type":"address","full_address":"149 9th Street, Richmond, California 94804, United States","name":"149 9th Street","name_preferred":"149 9th Street","coordinates":{"longitude":-122.360907,"latitude":37.932889,"accuracy":"interpolated","routable_points":[{"name":"default","latitude":37.932889,"longitude":-122.360907}]},"place_formatted":"Richmond, California 94804, United States","match_code":{"address_number":"plausible","street":"matched","postcode":"unmatched","place":"unmatched","region":"matched","locality":"not_applicable","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDox","address_number":"149","street_name":"9th Street","name":"149 9th Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHItaXRwOmV5SnhJam9pTVRRNUlEbDBhQ0JUZEN3Z1UyRnVJRVp5WVc1amFYTmpieXdnUTBFZ09UUXhNRE1pTENKMGVYQmxjeUk2SW1Ga1pISmxjM01pTENKc2FXMXBkQ0k2SWpVaUxDSnBibU5zZFdSbFgyMWhkR05vWDJSbGRHRnBiQ0k2SW5SeWRXVWlMQ0p0YjJSbElqb2labTl5ZDJGeVpDSXNJblkyZEhsd1pYTWlPaUpoWkdSeVpYTnpJbjA6MQ","name":"9th Street"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpFdGNNN0E","name":"Iron Triangle","wikidata_id":"Q6072867"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFcjl1N0E","name":"94804"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpGZnhvN0E","name":"Richmond","wikidata_id":"Q495377"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpUa2Jz","name":"Contra Costa County","wikidata_id":"Q108058"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCbVRz","name":"California","wikidata_id":"Q99","region_code":"CA","region_code_full":"US-CA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}},{"type":"Feature","id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDoy","geometry":{"type":"Point","coordinates":[-122.239871,38.097967]},"properties":{"mapbox_id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDoy","feature_type":"address","full_address":"149 9th Street, Vallejo, California 94590, United States","name":"149 9th Street","name_preferred":"149 9th Street","coordinates":{"longitude":-122.239871,"latitude":38.097967,"accuracy":"interpolated","routable_points":[{"name":"default","latitude":38.097967,"longitude":-122.239871}]},"place_formatted":"Vallejo, California 94590, United States","match_code":{"address_number":"plausible","street":"matched","postcode":"unmatched","place":"unmatched","region":"matched","locality":"not_applicable","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDoy","address_number":"149","street_name":"9th Street","name":"149 9th Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHItaXRwOmV5SnhJam9pTVRRNUlEbDBhQ0JUZEN3Z1UyRnVJRVp5WVc1amFYTmpieXdnUTBFZ09UUXhNRE1pTENKMGVYQmxjeUk2SW1Ga1pISmxjM01pTENKc2FXMXBkQ0k2SWpVaUxDSnBibU5zZFdSbFgyMWhkR05vWDJSbGRHRnBiQ0k2SW5SeWRXVWlMQ0p0YjJSbElqb2labTl5ZDJGeVpDSXNJblkyZEhsd1pYTWlPaUpoWkdSeVpYTnpJbjA6Mg","name":"9th Street"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFcmp1N0E","name":"94590"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpGQTFJN0E","name":"Vallejo","wikidata_id":"Q208445"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpBVWtHN0E","name":"Solano County","wikidata_id":"Q108083"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCbVRz","name":"California","wikidata_id":"Q99","region_code":"CA","region_code_full":"US-CA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}},{"type":"Feature","id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDoz","geometry":{"type":"Point","coordinates":[-122.266226,37.798081]},"properties":{"mapbox_id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDoz","feature_type":"address","full_address":"149 9th Street, Oakland, California 94607, United States","name":"149 9th Street","name_preferred":"149 9th Street","coordinates":{"longitude":-122.266226,"latitude":37.798081,"accuracy":"interpolated","routable_points":[{"name":"default","latitude":37.798081,"longitude":-122.266226}]},"place_formatted":"Oakland, California 94607, United States","match_code":{"address_number":"plausible","street":"matched","postcode":"unmatched","place":"unmatched","region":"matched","locality":"not_applicable","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkci1pdHA6ZXlKeElqb2lNVFE1SURsMGFDQlRkQ3dnVTJGdUlFWnlZVzVqYVhOamJ5d2dRMEVnT1RReE1ETWlMQ0owZVhCbGN5STZJbUZrWkhKbGMzTWlMQ0pzYVcxcGRDSTZJalVpTENKcGJtTnNkV1JsWDIxaGRHTm9YMlJsZEdGcGJDSTZJblJ5ZFdVaUxDSnRiMlJsSWpvaVptOXlkMkZ5WkNJc0luWTJkSGx3WlhNaU9pSmhaR1J5WlhOekluMDoz","address_number":"149","street_name":"9th Street","name":"149 9th Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHItaXRwOmV5SnhJam9pTVRRNUlEbDBhQ0JUZEN3Z1UyRnVJRVp5WVc1amFYTmpieXdnUTBFZ09UUXhNRE1pTENKMGVYQmxjeUk2SW1Ga1pISmxjM01pTENKc2FXMXBkQ0k2SWpVaUxDSnBibU5zZFdSbFgyMWhkR05vWDJSbGRHRnBiQ0k2SW5SeWRXVWlMQ0p0YjJSbElqb2labTl5ZDJGeVpDSXNJblkyZEhsd1pYTWlPaUpoWkdSeVpYTnpJbjA6Mw","name":"9th Street"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpCc3RzN0E","name":"Chinatown","wikidata_id":"Q5100154"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFcnF1N0E","name":"94607"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpGZnZvN0E","name":"Oakland","wikidata_id":"Q17042"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpBMGJz","name":"Alameda County","wikidata_id":"Q107146"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCbVRz","name":"California","wikidata_id":"Q99","region_code":"CA","region_code_full":"US-CA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjpjNmYwM2Y1MC0zM2MwLTQ1ZmItODYxNi1lOTAwYWM3YjBhM2E","geometry":{"type":"Point","coordinates":[-122.361262,37.929928]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjpjNmYwM2Y1MC0zM2MwLTQ1ZmItODYxNi1lOTAwYWM3YjBhM2E","feature_type":"address","full_address":"149 South 9th Street, Richmond, California 94804, United States","name":"149 South 9th Street","name_preferred":"149 South 9th Street","coordinates":{"longitude":-122.361262,"latitude":37.929928,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":37.929927,"longitude":-122.361032}]},"place_formatted":"Richmond, California 94804, United States","match_code":{"address_number":"matched","street":"unmatched","postcode":"unmatched","place":"unmatched","region":"matched","locality":"not_applicable","country":"inferred","confidence":"low"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjpjNmYwM2Y1MC0zM2MwLTQ1ZmItODYxNi1lOTAwYWM3YjBhM2E","address_number":"149","street_name":"South 9th Street","name":"149 South 9th Street"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6YzZmMDNmNTAtMzNjMC00NWZiLTg2MTYtZTkwMGFjN2IwYTNh","name":"South 9th Street"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpJYndNN0E","name":"Santa Fe"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFcjl1N0E","name":"94804"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpGZnhvN0E","name":"Richmond","wikidata_id":"Q495377"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpUa2Jz","name":"Contra Costa County","wikidata_id":"Q108058"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCbVRz","name":"California","wikidata_id":"Q99","region_code":"CA","region_code_full":"US-CA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_61c96e256b090c50a0a9a247c3808fb84b79f55c b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_61c96e256b090c50a0a9a247c3808fb84b79f55c deleted file mode 100644 index 3be44cc8c..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_61c96e256b090c50a0a9a247c3808fb84b79f55c +++ /dev/null @@ -1 +0,0 @@ -s:5251:"{"type":"FeatureCollection","query":["10","downing","st","london","uk"],"features":[{"id":"address.2844060426507784","type":"Feature","place_type":["address"],"relevance":0.9666666666666666,"properties":{},"text_en":"Downing Street","place_name_en":"10 Downing Street, St. James's, London, SW1A 2AT, United Kingdom","text":"Downing Street","place_name":"10 Downing Street, St. James's, London, SW1A 2AT, United Kingdom","center":[-0.126126,51.503157],"geometry":{"type":"Point","coordinates":[-0.126126,51.503157]},"address":"10","context":[{"id":"postcode.11318645777473120","text_en":"SW1A 2AT","text":"SW1A 2AT"},{"id":"locality.15910638793964150","wikidata":null,"text_en":"St. James's","text":"St. James's"},{"id":"place.8500383470913397","wikidata":"Q84","text_en":"London","language_en":"en","text":"London","language":"en"},{"id":"district.9655698107976620","wikidata":"Q23306","text_en":"Greater London","language_en":"en","text":"Greater London","language":"en"},{"id":"region.3185","short_code":"GB-ENG","wikidata":"Q21","text_en":"England","language_en":"en","text":"England","language":"en"},{"id":"country.358","short_code":"gb","wikidata":"Q145","text_en":"United Kingdom","language_en":"en","text":"United Kingdom","language":"en"}]},{"id":"address.4852922328439012","type":"Feature","place_type":["address"],"relevance":0.3,"properties":{},"text_en":"Rue Downing","place_name_en":"10 Rue Downing, Grande-Digue, New Brunswick, Canada","text":"Rue Downing","place_name":"10 Rue Downing, Grande-Digue, New Brunswick, Canada","matching_text":"Downing Street","matching_place_name":"10 Downing Street, Grande-Digue, New Brunswick, Canada","center":[-64.529877,46.335725],"geometry":{"type":"Point","coordinates":[-64.529877,46.335725]},"address":"10","context":[{"id":"place.18359628229490950","wikidata":"Q2406204","text_en":"Grande-Digue","language_en":"en","text":"Grande-Digue","language":"en"},{"id":"region.218977","short_code":"CA-NB","wikidata":"Q1965","text_en":"New Brunswick","language_en":"en","text":"New Brunswick","language":"en"},{"id":"country.3179","short_code":"ca","wikidata":"Q16","text_en":"Canada","language_en":"en","text":"Canada","language":"en"}]},{"id":"address.2778496043278880","type":"Feature","place_type":["address"],"relevance":0.3,"properties":{},"text_en":"Downing Street","place_name_en":"10 Downing Street, Fredericton, New Brunswick E3A 4M6, Canada","text":"Downing Street","place_name":"10 Downing Street, Fredericton, New Brunswick E3A 4M6, Canada","center":[-66.585237,45.979891],"geometry":{"type":"Point","coordinates":[-66.585237,45.979891]},"address":"10","context":[{"id":"postcode.13170795948825840","text_en":"E3A 4M6","text":"E3A 4M6"},{"id":"place.12649774315478860","wikidata":"Q2138","text_en":"Fredericton","language_en":"en","text":"Fredericton","language":"en"},{"id":"region.218977","short_code":"CA-NB","wikidata":"Q1965","text_en":"New Brunswick","language_en":"en","text":"New Brunswick","language":"en"},{"id":"country.3179","short_code":"ca","wikidata":"Q16","text_en":"Canada","language_en":"en","text":"Canada","language":"en"}]},{"id":"address.2232726546138078","type":"Feature","place_type":["address"],"relevance":0.3,"properties":{},"text_en":"Downing Street","place_name_en":"10 Downing Street, Hamilton, Ontario L0R 0A0, Canada","text":"Downing Street","place_name":"10 Downing Street, Hamilton, Ontario L0R 0A0, Canada","center":[-79.810597,43.116989],"geometry":{"type":"Point","coordinates":[-79.810597,43.116989],"interpolated":true},"address":"10","context":[{"id":"postcode.19608462426414870","text_en":"L0R 0A0","text":"L0R 0A0"},{"id":"place.14129018412865700","wikidata":"Q133116","text_en":"Hamilton","language_en":"en","text":"Hamilton","language":"en"},{"id":"region.3721","short_code":"CA-ON","wikidata":"Q1904","text_en":"Ontario","language_en":"en","text":"Ontario","language":"en"},{"id":"country.3179","short_code":"ca","wikidata":"Q16","text_en":"Canada","language_en":"en","text":"Canada","language":"en"}]},{"id":"address.4850220298517218","type":"Feature","place_type":["address"],"relevance":0.3,"properties":{},"text_en":"Downing Street","place_name_en":"10 Downing Street, Halifax, Nova Scotia B3M 2G3, Canada","text":"Downing Street","place_name":"10 Downing Street, Halifax, Nova Scotia B3M 2G3, Canada","center":[-63.669482,44.685001],"geometry":{"type":"Point","coordinates":[-63.669482,44.685001],"interpolated":true},"address":"10","context":[{"id":"neighborhood.11574814505474780","text_en":"Rockingham","text":"Rockingham"},{"id":"postcode.13399737010185770","text_en":"B3M 2G3","text":"B3M 2G3"},{"id":"place.17790518833069190","wikidata":"Q2141","text_en":"Halifax","language_en":"en","text":"Halifax","language":"en"},{"id":"region.218945","short_code":"CA-NS","wikidata":"Q1952","text_en":"Nova Scotia","language_en":"en","text":"Nova Scotia","language":"en"},{"id":"country.3179","short_code":"ca","wikidata":"Q16","text_en":"Canada","language_en":"en","text":"Canada","language":"en"}]}],"attribution":"NOTICE: © 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_798771ac350f81cfa1f5e499d3a6d7a4df71525f b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_798771ac350f81cfa1f5e499d3a6d7a4df71525f new file mode 100644 index 000000000..b2896a0d6 --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_798771ac350f81cfa1f5e499d3a6d7a4df71525f @@ -0,0 +1 @@ +s:2219:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"dXJuOm1ieGFkcjo1N2NhYTE3Mi03MGEyLTQ5YzYtYjk2ZS1jMDhkYjRkNGE5Zjc","geometry":{"type":"Point","coordinates":[-77.036948,38.900488]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjo1N2NhYTE3Mi03MGEyLTQ5YzYtYjk2ZS1jMDhkYjRkNGE5Zjc","feature_type":"address","full_address":"800 16th Street Northwest, Washington, District of Columbia 20006, United States","name":"800 16th Street Northwest","name_preferred":"800 16th Street Northwest","coordinates":{"longitude":-77.036948,"latitude":38.900488,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":38.900488,"longitude":-77.036768}]},"place_formatted":"Washington, District of Columbia 20006, United States","context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjo1N2NhYTE3Mi03MGEyLTQ5YzYtYjk2ZS1jMDhkYjRkNGE5Zjc","address_number":"800","street_name":"16th Street Northwest","name":"800 16th Street Northwest"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6NTdjYWExNzItNzBhMi00OWM2LWI5NmUtYzA4ZGI0ZDRhOWY3","name":"16th Street Northwest"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpDb1BzN0E","name":"Dupont Circle","alternate":{"mapbox_id":"dXJuOm1ieHBsYzpCK0xzN0E","name":"Connecticut Avenue","translations":{"en":{"language":"en","name":"Connecticut Avenue"}}},"translations":{"en":{"language":"en","name":"Dupont Circle"}}},"postcode":{"mapbox_id":"postcode.6693630501763360","name":"20006"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpGSmlvN0E","name":"Washington","wikidata_id":"Q61","translations":{"en":{"language":"en","name":"Washington"}}},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCUVRz","name":"District of Columbia","wikidata_id":"Q3551781","region_code":"DC","region_code_full":"US-DC","translations":{"en":{"language":"en","name":"District of Columbia"}}},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA","translations":{"en":{"language":"en","name":"United States"}}}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_7b8b47952b295102acd4cb1bc0a9536c26c7bc9b b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_7b8b47952b295102acd4cb1bc0a9536c26c7bc9b new file mode 100644 index 000000000..5fac39b0b --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_7b8b47952b295102acd4cb1bc0a9536c26c7bc9b @@ -0,0 +1 @@ +s:6626:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"dXJuOm1ieGFkcjpjM2M2NWFjNC1hMTExLTQ1NDItOGIxNi05ZDg1Y2I4YjYzMDc","geometry":{"type":"Point","coordinates":[2.388886,48.863134]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjpjM2M2NWFjNC1hMTExLTQ1NDItOGIxNi05ZDg1Y2I4YjYzMDc","feature_type":"address","full_address":"12 Avenue Gambetta, 75020 Paris, France","name":"12 Avenue Gambetta","name_preferred":"12 Avenue Gambetta","coordinates":{"longitude":2.388886,"latitude":48.863134,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":48.863236,"longitude":2.388829}]},"place_formatted":"75020 Paris, France","context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjpjM2M2NWFjNC1hMTExLTQ1NDItOGIxNi05ZDg1Y2I4YjYzMDc","address_number":"12","street_name":"Avenue Gambetta","name":"12 Avenue Gambetta"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6YzNjNjVhYzQtYTExMS00NTQyLThiMTYtOWQ4NWNiOGI2MzA3","name":"Avenue Gambetta"},"postcode":{"mapbox_id":"postcode.3248070486542928","name":"75020"},"locality":{"mapbox_id":"dXJuOm1ieHBsYzpDRXBO","name":"20th arrondissement","wikidata_id":"Q210720"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpEYVJO","name":"Paris","wikidata_id":"Q90","short_code":"FR-75"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpFc1JO","name":"Île-de-France","wikidata_id":"Q13917","region_code":"IDF","region_code_full":"FR-IDF"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazA","name":"France","wikidata_id":"Q142","country_code":"FR","country_code_alpha_3":"FRA"}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjozZjgzZmVjMi02N2UzLTRiMzctOGY4Yi01ZDVlNTNkMDgzODQ","geometry":{"type":"Point","coordinates":[2.388742,48.863306]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjozZjgzZmVjMi02N2UzLTRiMzctOGY4Yi01ZDVlNTNkMDgzODQ","feature_type":"address","full_address":"1 Avenue Gambetta, 75020 Paris, France","name":"1 Avenue Gambetta","name_preferred":"1 Avenue Gambetta","coordinates":{"longitude":2.388742,"latitude":48.863306,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":48.863226,"longitude":2.388787}]},"place_formatted":"75020 Paris, France","context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjozZjgzZmVjMi02N2UzLTRiMzctOGY4Yi01ZDVlNTNkMDgzODQ","address_number":"1","street_name":"Avenue Gambetta","name":"1 Avenue Gambetta"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6M2Y4M2ZlYzItNjdlMy00YjM3LThmOGItNWQ1ZTUzZDA4Mzg0","name":"Avenue Gambetta"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpCU25NVFE","name":"Menilmontant","alternate":{"mapbox_id":"dXJuOm1ieHBsYzpCU3NNVFE","name":"Père-Lachaise","wikidata_id":"Q3413289"}},"postcode":{"mapbox_id":"postcode.3248070486542928","name":"75020"},"locality":{"mapbox_id":"dXJuOm1ieHBsYzpDRXBO","name":"20th arrondissement","wikidata_id":"Q210720"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpEYVJO","name":"Paris","wikidata_id":"Q90","short_code":"FR-75"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpFc1JO","name":"Île-de-France","wikidata_id":"Q13917","region_code":"IDF","region_code_full":"FR-IDF"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazA","name":"France","wikidata_id":"Q142","country_code":"FR","country_code_alpha_3":"FRA"}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjphNmFhMTZmOS1jZWE3LTQ0ZTAtOGYwYS1lMjc1NDVhMTdiN2I","geometry":{"type":"Point","coordinates":[2.38854,48.863297]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjphNmFhMTZmOS1jZWE3LTQ0ZTAtOGYwYS1lMjc1NDVhMTdiN2I","feature_type":"address","full_address":"13 Place Auguste Métivier, 75020 Paris, France","name":"13 Place Auguste Métivier","name_preferred":"13 Place Auguste Métivier","coordinates":{"longitude":2.38854,"latitude":48.863297,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":48.863242,"longitude":2.388245}]},"place_formatted":"75020 Paris, France","context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjphNmFhMTZmOS1jZWE3LTQ0ZTAtOGYwYS1lMjc1NDVhMTdiN2I","address_number":"13","street_name":"Place Auguste Métivier","name":"13 Place Auguste Métivier"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6YTZhYTE2ZjktY2VhNy00NGUwLThmMGEtZTI3NTQ1YTE3Yjdi","name":"Place Auguste Métivier"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpCU25NVFE","name":"Menilmontant","alternate":{"mapbox_id":"dXJuOm1ieHBsYzpCU3NNVFE","name":"Père-Lachaise","wikidata_id":"Q3413289"}},"postcode":{"mapbox_id":"postcode.8604773807997748","name":"75020"},"locality":{"mapbox_id":"dXJuOm1ieHBsYzpDRXBO","name":"20th arrondissement","wikidata_id":"Q210720"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpEYVJO","name":"Paris","wikidata_id":"Q90","short_code":"FR-75"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpFc1JO","name":"Île-de-France","wikidata_id":"Q13917","region_code":"IDF","region_code_full":"FR-IDF"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazA","name":"France","wikidata_id":"Q142","country_code":"FR","country_code_alpha_3":"FRA"}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjpjYzVkYzQ3MS1lNGJiLTRiOTItYTU1MC1lZTg4ZTFjOWUzMmE","geometry":{"type":"Point","coordinates":[2.388546,48.863359]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjpjYzVkYzQ3MS1lNGJiLTRiOTItYTU1MC1lZTg4ZTFjOWUzMmE","feature_type":"address","full_address":"2 Rue Des Amandiers, 75020 Paris, France","name":"2 Rue Des Amandiers","name_preferred":"2 Rue Des Amandiers","coordinates":{"longitude":2.388546,"latitude":48.863359,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":48.863389,"longitude":2.388492}]},"place_formatted":"75020 Paris, France","context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjpjYzVkYzQ3MS1lNGJiLTRiOTItYTU1MC1lZTg4ZTFjOWUzMmE","address_number":"2","street_name":"Rue Des Amandiers","name":"2 Rue Des Amandiers"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6Y2M1ZGM0NzEtZTRiYi00YjkyLWE1NTAtZWU4OGUxYzllMzJh","name":"Rue Des Amandiers"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpCU25NVFE","name":"Menilmontant","alternate":{"mapbox_id":"dXJuOm1ieHBsYzpCU3NNVFE","name":"Père-Lachaise","wikidata_id":"Q3413289"}},"postcode":{"mapbox_id":"postcode.5685635047513804","name":"75020"},"locality":{"mapbox_id":"dXJuOm1ieHBsYzpDRXBO","name":"20th arrondissement","wikidata_id":"Q210720"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpEYVJO","name":"Paris","wikidata_id":"Q90","short_code":"FR-75"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpFc1JO","name":"Île-de-France","wikidata_id":"Q13917","region_code":"IDF","region_code_full":"FR-IDF"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazA","name":"France","wikidata_id":"Q142","country_code":"FR","country_code_alpha_3":"FRA"}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_9e3e5555aca6117bf14dbd86c37ed23cbece335d b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_9e3e5555aca6117bf14dbd86c37ed23cbece335d new file mode 100644 index 000000000..3c6af5dd0 --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_9e3e5555aca6117bf14dbd86c37ed23cbece335d @@ -0,0 +1 @@ +s:1325:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"address.858151070459380","geometry":{"type":"Point","coordinates":[-122.949686,47.629081]},"properties":{"mapbox_id":"address.858151070459380","feature_type":"street","full_address":"Yashi Road, Brinnon, Washington 98320, United States","name":"Yashi Road","name_preferred":"Yashi Road","coordinates":{"longitude":-122.949686,"latitude":47.629081},"place_formatted":"Brinnon, Washington 98320, United States","context":{"street":{"mapbox_id":"address.858151070459380","name":"Yashi Road"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpFNDVPN0E","name":"98320"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpBa2JJN0E","name":"Brinnon","wikidata_id":"Q612805"},"district":{"mapbox_id":"dXJuOm1ieHBsYzpyMGJz","name":"Jefferson County","wikidata_id":"Q384737"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpBUVRz","name":"Washington","wikidata_id":"Q1223","region_code":"WA","region_code_full":"US-WA"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_bbef3c8c03f148c252a89f0a36e1872e67c9a761 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_bbef3c8c03f148c252a89f0a36e1872e67c9a761 deleted file mode 100644 index 816e76110..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_bbef3c8c03f148c252a89f0a36e1872e67c9a761 +++ /dev/null @@ -1 +0,0 @@ -s:2309:"{"type":"FeatureCollection","query":[2.388911,48.863151],"features":[{"id":"address.1085979616","type":"Feature","place_type":["address"],"relevance":1,"properties":{},"text":"Avenue Gambetta","place_name":"8 Avenue Gambetta, 75020 Paris, France","center":[2.388781,48.863109],"geometry":{"type":"Point","coordinates":[2.388781,48.863109]},"address":"8","context":[{"id":"postcode.11865225190696130","text":"75020"},{"id":"place.228080","short_code":"FR-75","wikidata":"Q90","text":"Paris"},{"id":"country.3148","wikidata":"Q142","short_code":"fr","text":"France"}]},{"id":"address.1085979616","type":"Feature","place_type":["address"],"relevance":1,"properties":{},"text":"Avenue Gambetta","place_name":"10 Avenue Gambetta, 75020 Paris, France","center":[2.389073,48.863181],"geometry":{"type":"Point","coordinates":[2.389073,48.863181]},"address":"10","context":[{"id":"postcode.11865225190696130","text":"75020"},{"id":"place.228080","short_code":"FR-75","wikidata":"Q90","text":"Paris"},{"id":"country.3148","wikidata":"Q142","short_code":"fr","text":"France"}]},{"id":"address.1085979616","type":"Feature","place_type":["address"],"relevance":1,"properties":{},"text":"Avenue Gambetta","place_name":"1 Avenue Gambetta, 75020 Paris, France","center":[2.388736,48.863305],"geometry":{"type":"Point","coordinates":[2.388736,48.863305]},"address":"1","context":[{"id":"postcode.11865225190696130","text":"75020"},{"id":"place.228080","short_code":"FR-75","wikidata":"Q90","text":"Paris"},{"id":"country.3148","wikidata":"Q142","short_code":"fr","text":"France"}]},{"id":"address.1085979616","type":"Feature","place_type":["address"],"relevance":1,"properties":{},"text":"Avenue Gambetta","place_name":"12 Avenue Gambetta, 75020 Paris, France","center":[2.389194,48.863214],"geometry":{"type":"Point","coordinates":[2.389194,48.863214]},"address":"12","context":[{"id":"postcode.11865225190696130","text":"75020"},{"id":"place.228080","short_code":"FR-75","wikidata":"Q90","text":"Paris"},{"id":"country.3148","wikidata":"Q142","short_code":"fr","text":"France"}]}],"attribution":"NOTICE: © 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_c2fd1618bb5f29f1998244add688fc1668ec2416 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_c2fd1618bb5f29f1998244add688fc1668ec2416 deleted file mode 100644 index dfa6e6864..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_c2fd1618bb5f29f1998244add688fc1668ec2416 +++ /dev/null @@ -1 +0,0 @@ -s:530:"{"type":"FeatureCollection","query":[0,0],"features":[{"id":"address.262530399228832","type":"Feature","place_type":["address"],"relevance":1,"properties":{},"text":"South St","place_name":"206 South St, ","center":[0,0],"geometry":{"type":"Point","coordinates":[0,0]},"address":"206"}],"attribution":"NOTICE: © 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_c97f9d6eb99ff44a7e13d0dc8eb54c3fd8f6971b b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_c97f9d6eb99ff44a7e13d0dc8eb54c3fd8f6971b deleted file mode 100644 index fa170aee9..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_c97f9d6eb99ff44a7e13d0dc8eb54c3fd8f6971b +++ /dev/null @@ -1 +0,0 @@ -s:3470:"{"type":"FeatureCollection","query":[-77.036991,38.900206],"features":[{"id":"address.717957002859378","type":"Feature","place_type":["address"],"relevance":1,"properties":{},"text_en":"H Street Northwest","place_name_en":"1615 H Street Northwest, Washington, District of Columbia 20006, United States","text":"H Street Northwest","place_name":"1615 H Street Northwest, Washington, District of Columbia 20006, United States","center":[-77.037527,38.900583],"geometry":{"type":"Point","coordinates":[-77.037527,38.900583]},"address":"1615","context":[{"id":"neighborhood.291451","text_en":"Downtown","text":"Downtown"},{"id":"postcode.10186570277652840","text_en":"20006","text":"20006"},{"id":"place.7673410831246050","wikidata":"Q61","text_en":"Washington","language_en":"en","text":"Washington","language":"en"},{"id":"region.3403","short_code":"US-DC","wikidata":"Q61","text_en":"District of Columbia","language_en":"en","text":"District of Columbia","language":"en"},{"id":"country.3145","wikidata":"Q30","short_code":"us","text_en":"United States","language_en":"en","text":"United States","language":"en"}]},{"id":"address.8110859437053248","type":"Feature","place_type":["address"],"relevance":1,"properties":{},"text_en":"16th Street Northwest","place_name_en":"800 16th Street Northwest, Washington, District of Columbia 20006, United States","text":"16th Street Northwest","place_name":"800 16th Street Northwest, Washington, District of Columbia 20006, United States","center":[-77.036959,38.900533],"geometry":{"type":"Point","coordinates":[-77.036959,38.900533]},"address":"800","context":[{"id":"neighborhood.291451","text_en":"Downtown","text":"Downtown"},{"id":"postcode.10186570277652840","text_en":"20006","text":"20006"},{"id":"place.7673410831246050","wikidata":"Q61","text_en":"Washington","language_en":"en","text":"Washington","language":"en"},{"id":"region.3403","short_code":"US-DC","wikidata":"Q61","text_en":"District of Columbia","language_en":"en","text":"District of Columbia","language":"en"},{"id":"country.3145","wikidata":"Q30","short_code":"us","text_en":"United States","language_en":"en","text":"United States","language":"en"}]},{"id":"address.45528587931684","type":"Feature","place_type":["address"],"relevance":1,"properties":{},"text_en":"Jackson Place Northwest","place_name_en":"748 Jackson Place Northwest, Washington, District of Columbia 20062, United States","text":"Jackson Place Northwest","place_name":"748 Jackson Place Northwest, Washington, District of Columbia 20062, United States","center":[-77.038199,38.900034],"geometry":{"type":"Point","coordinates":[-77.038199,38.900034]},"address":"748","context":[{"id":"neighborhood.291451","text_en":"Downtown","text":"Downtown"},{"id":"postcode.10886799999681030","text_en":"20062","text":"20062"},{"id":"place.7673410831246050","wikidata":"Q61","text_en":"Washington","language_en":"en","text":"Washington","language":"en"},{"id":"region.3403","short_code":"US-DC","wikidata":"Q61","text_en":"District of Columbia","language_en":"en","text":"District of Columbia","language":"en"},{"id":"country.3145","wikidata":"Q30","short_code":"us","text_en":"United States","language_en":"en","text":"United States","language":"en"}]}],"attribution":"NOTICE: © 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_d72ced1f54dff6389745d11b002a772451804618 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_d72ced1f54dff6389745d11b002a772451804618 deleted file mode 100644 index 6f03b3ead..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_d72ced1f54dff6389745d11b002a772451804618 +++ /dev/null @@ -1 +0,0 @@ -s:339:"{"type":"FeatureCollection","query":["wahsington"],"features":[],"attribution":"NOTICE: © 2020 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_d73a2016dbd70a152bffadf02f4f04d7e4d6a0b7 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_d73a2016dbd70a152bffadf02f4f04d7e4d6a0b7 new file mode 100644 index 000000000..1cbcbe74c --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_d73a2016dbd70a152bffadf02f4f04d7e4d6a0b7 @@ -0,0 +1 @@ +s:1516:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"dXJuOm1ieHBsYzpoMmhQ","geometry":{"type":"Point","coordinates":[-0.83069,51.724422]},"properties":{"mapbox_id":"dXJuOm1ieHBsYzpoMmhQ","feature_type":"place","full_address":"Princes Risborough, Buckinghamshire, Inghilterra, Regno Unito","name":"Princes Risborough","name_preferred":"Princes Risborough","coordinates":{"longitude":-0.83069,"latitude":51.724422},"place_formatted":"Buckinghamshire, Inghilterra, Regno Unito","bbox":[-0.912802,51.680448,-0.770371,51.756426],"context":{"district":{"mapbox_id":"dXJuOm1ieHBsYzpBcVpQ","name":"Buckinghamshire","wikidata_id":"Q21694636","translations":{"it":{"language":"fr","name":"Buckinghamshire"}}},"region":{"mapbox_id":"dXJuOm1ieHBsYzpKRTg","name":"Inghilterra","wikidata_id":"Q21","region_code":"ENG","region_code_full":"GB-ENG","translations":{"it":{"language":"it","name":"Inghilterra"}}},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJazg","name":"Regno Unito","wikidata_id":"Q145","country_code":"GB","country_code_alpha_3":"GBR","translations":{"it":{"language":"it","name":"Regno Unito"}}},"place":{"mapbox_id":"dXJuOm1ieHBsYzpoMmhQ","name":"Princes Risborough","translations":{"it":{"language":"it","name":"Princes Risborough"}},"wikidata_id":"Q2568545"}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_eb032a2644f68b47a4076ea601305eaf8ba72a31 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_eb032a2644f68b47a4076ea601305eaf8ba72a31 deleted file mode 100644 index 6dde633d7..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_eb032a2644f68b47a4076ea601305eaf8ba72a31 +++ /dev/null @@ -1 +0,0 @@ -s:3926:"{"type":"FeatureCollection","query":["149","9th","st","san","francisco","ca","94103"],"features":[{"id":"address.3071152063251042","type":"Feature","place_type":["address"],"relevance":0.875,"properties":{},"text":"9th Street","place_name":"149 9th Street, San Francisco, California 94103, United States","center":[-122.41362,37.77572],"geometry":{"type":"Point","coordinates":[-122.41362,37.77572]},"address":"149","context":[{"id":"neighborhood.293577","text":"South of Market"},{"id":"postcode.13892342768265050","text":"94103"},{"id":"place.15734669613361910","wikidata":"Q62","text":"San Francisco"},{"id":"region.3591","short_code":"US-CA","wikidata":"Q99","text":"California"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]},{"id":"address.2787669249858206","type":"Feature","place_type":["address"],"relevance":0.25,"properties":{},"text":"9th Street","place_name":"149 9th Street, Greenport, New York 11944, United States","center":[-72.370864,41.099811],"geometry":{"type":"Point","coordinates":[-72.370864,41.099811],"interpolated":true},"address":"149","context":[{"id":"neighborhood.278108","text":"Stirling"},{"id":"postcode.5709909550190040","text":"11944"},{"id":"place.10410131002602850","wikidata":"Q94652","text":"Greenport"},{"id":"region.3866","short_code":"US-NY","wikidata":"Q1384","text":"New York"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]},{"id":"address.1299539993830358","type":"Feature","place_type":["address"],"relevance":0.25,"properties":{},"text":"East 9th Street","place_name":"149 East 9th Street, Erie, Pennsylvania 16503, United States","matching_text":"9th Street","matching_place_name":"149 9th Street, Erie, Pennsylvania 16503, United States","center":[-80.069022,42.131794],"geometry":{"type":"Point","coordinates":[-80.069022,42.131794],"interpolated":true},"address":"149","context":[{"id":"postcode.11103612841590770","text":"16503"},{"id":"place.10004124579967850","wikidata":"Q234061","text":"Erie"},{"id":"region.3337","short_code":"US-PA","wikidata":"Q1400","text":"Pennsylvania"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]},{"id":"address.7335913800968804","type":"Feature","place_type":["address"],"relevance":0.25,"properties":{},"text":"West 9th Street","place_name":"149 West 9th Street, Erie, Pennsylvania 16501, United States","matching_text":"9th Street","matching_place_name":"149 9th Street, Erie, Pennsylvania 16501, United States","center":[-80.086582,42.125322],"geometry":{"type":"Point","coordinates":[-80.086582,42.125322],"interpolated":true},"address":"149","context":[{"id":"neighborhood.270119","text":"Dock Junction"},{"id":"postcode.11009455618026990","text":"16501"},{"id":"place.10004124579967850","wikidata":"Q234061","text":"Erie"},{"id":"region.3337","short_code":"US-PA","wikidata":"Q1400","text":"Pennsylvania"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]},{"id":"address.8377599986498868","type":"Feature","place_type":["address"],"relevance":0.25,"properties":{},"text":"Ninth Street","place_name":"149 Ninth Street, Nashua, New Hampshire 03060, United States","center":[-71.481591,42.753499],"geometry":{"type":"Point","coordinates":[-71.481591,42.753499],"interpolated":true,"omitted":true},"address":"149","context":[{"id":"neighborhood.287645","text":"Downtown"},{"id":"postcode.17825302421333580","text":"03060"},{"id":"place.6791107671778960","wikidata":"Q48274","text":"Nashua"},{"id":"region.211885","short_code":"US-NH","wikidata":"Q759","text":"New Hampshire"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]}],"attribution":"NOTICE: © 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_f212d067263ee5a25cce4e79ee710e3a4af3fc5e b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_f212d067263ee5a25cce4e79ee710e3a4af3fc5e deleted file mode 100644 index c88d497a0..000000000 --- a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_f212d067263ee5a25cce4e79ee710e3a4af3fc5e +++ /dev/null @@ -1 +0,0 @@ -s:4352:"{"type":"FeatureCollection","query":["116th","st","broadway","new","york","ny","10027","united","states"],"features":[{"id":"address.2431617896783536","type":"Feature","place_type":["address"],"relevance":0.6666666666666666,"properties":{},"text":"116th Street","place_name":"116th Street, Queens, New York, New York 11356, United States","center":[-73.851157,40.786596],"geometry":{"type":"Point","coordinates":[-73.851157,40.786596]},"context":[{"id":"neighborhood.2104291","text":"College Point"},{"id":"locality.6306827455006740","wikidata":"Q18424","text":"Queens"},{"id":"postcode.11196253910231740","text":"11356"},{"id":"place.15278078705964500","wikidata":"Q60","text":"New York"},{"id":"region.3866","short_code":"US-NY","wikidata":"Q1384","text":"New York"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]},{"id":"address.4427827672964774","type":"Feature","place_type":["address"],"relevance":0.5833333333333333,"properties":{},"text":"East 116th Street","place_name":"East 116th Street, Manhattan, New York, New York 10035, United States","matching_text":"116th Street","matching_place_name":"116th Street, Manhattan, New York, New York 10035, United States","center":[-73.938724,40.797571],"geometry":{"type":"Point","coordinates":[-73.938724,40.797571]},"context":[{"id":"neighborhood.2100588","text":"East Harlem"},{"id":"locality.12696928000137850","wikidata":"Q11299","text":"Manhattan"},{"id":"postcode.11255904502577980","text":"10035"},{"id":"place.15278078705964500","wikidata":"Q60","text":"New York"},{"id":"region.3866","short_code":"US-NY","wikidata":"Q1384","text":"New York"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]},{"id":"address.2741753979749180","type":"Feature","place_type":["address"],"relevance":0.5833333333333333,"properties":{},"text":"West 116th Street","place_name":"West 116th Street, Manhattan, New York, New York 10026, United States","matching_text":"116th Street","matching_place_name":"116th Street, Manhattan, New York, New York 10026, United States","center":[-73.956278,40.804979],"geometry":{"type":"Point","coordinates":[-73.956278,40.804979]},"context":[{"id":"neighborhood.2102863","text":"Harlem"},{"id":"locality.12696928000137850","wikidata":"Q11299","text":"Manhattan"},{"id":"postcode.13768369279157190","text":"10026"},{"id":"place.15278078705964500","wikidata":"Q60","text":"New York"},{"id":"region.3866","short_code":"US-NY","wikidata":"Q1384","text":"New York"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]},{"id":"address.2201553461107342","type":"Feature","place_type":["address"],"relevance":0.5833333333333333,"properties":{},"text":"116th Street","place_name":"116th Street, Queens, New York, New York 11419, United States","matching_place_name":"116th Street, Queens, NY, New York 11419, United States","center":[-73.827854,40.687554],"geometry":{"type":"Point","coordinates":[-73.827854,40.687554]},"context":[{"id":"neighborhood.297765","text":"Richmond Hill"},{"id":"locality.6306827455006740","wikidata":"Q18424","text":"Queens"},{"id":"postcode.453327290579340","text":"11419"},{"id":"place.15278078705964500","wikidata":"Q60","text":"New York"},{"id":"region.3866","short_code":"US-NY","wikidata":"Q1384","text":"New York"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]},{"id":"address.3561887178367494","type":"Feature","place_type":["address"],"relevance":0.42857142857142855,"properties":{},"text":"South West Street","place_name":"South West Street, Mount Vernon, New York 10550, United States","matching_text":"St","matching_place_name":"St, Mount Vernon, New York 10550, United States","center":[-73.850347,40.912431],"geometry":{"type":"Point","coordinates":[-73.850347,40.912431]},"context":[{"id":"postcode.15487211573224510","text":"10550"},{"id":"place.9087657435224330","wikidata":"Q835831","text":"Mount Vernon"},{"id":"region.3866","short_code":"US-NY","wikidata":"Q1384","text":"New York"},{"id":"country.3145","short_code":"us","wikidata":"Q30","text":"United States"}]}],"attribution":"NOTICE: © 2017 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_f42b62632d0fa8733ae9eda5e6cb3c9091935380 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_f42b62632d0fa8733ae9eda5e6cb3c9091935380 new file mode 100644 index 000000000..867689ad1 --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_f42b62632d0fa8733ae9eda5e6cb3c9091935380 @@ -0,0 +1 @@ +s:285:"{"type":"FeatureCollection","features":[],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_fee388586d54f2150af453c6e033e452d85e46a8 b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_fee388586d54f2150af453c6e033e452d85e46a8 new file mode 100644 index 000000000..383d14da5 --- /dev/null +++ b/src/Provider/Mapbox/Tests/.cached_responses/api.mapbox.com_fee388586d54f2150af453c6e033e452d85e46a8 @@ -0,0 +1 @@ +s:3898:"{"type":"FeatureCollection","features":[{"type":"Feature","id":"dXJuOm1ieGFkcjoxMDg4MTIxNi1mZTUwLTQyM2QtOWNjYS00ODQxYjNjMmFkNTA","geometry":{"type":"Point","coordinates":[-77.036574,38.897684]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjoxMDg4MTIxNi1mZTUwLTQyM2QtOWNjYS00ODQxYjNjMmFkNTA","feature_type":"address","full_address":"1600 Pennsylvania Avenue Northwest, Washington, District of Columbia 20500, United States","name":"1600 Pennsylvania Avenue Northwest","name_preferred":"1600 Pennsylvania Avenue Northwest","coordinates":{"longitude":-77.036574,"latitude":38.897684,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":38.897876,"longitude":-77.036544}]},"place_formatted":"Washington, District of Columbia 20500, United States","match_code":{"address_number":"matched","street":"matched","postcode":"matched","place":"matched","region":"matched","locality":"not_applicable","country":"inferred","confidence":"exact"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjoxMDg4MTIxNi1mZTUwLTQyM2QtOWNjYS00ODQxYjNjMmFkNTA","address_number":"1600","street_name":"Pennsylvania Avenue Northwest","name":"1600 Pennsylvania Avenue Northwest"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6MTA4ODEyMTYtZmU1MC00MjNkLTljY2EtNDg0MWIzYzJhZDUw","name":"Pennsylvania Avenue Northwest"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpHYUVzN0E","name":"National Mall"},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpHVnFPN0E","name":"20500"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpGSmlvN0E","name":"Washington","wikidata_id":"Q61"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCUVRz","name":"District of Columbia","wikidata_id":"Q3551781","region_code":"DC","region_code_full":"US-DC"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}},{"type":"Feature","id":"dXJuOm1ieGFkcjpmOTYwMzc4OC01MWE4LTQ3NzQtOWVhMi1lM2ZkZGY0NWQ0OWI","geometry":{"type":"Point","coordinates":[-76.981937,38.87922]},"properties":{"mapbox_id":"dXJuOm1ieGFkcjpmOTYwMzc4OC01MWE4LTQ3NzQtOWVhMi1lM2ZkZGY0NWQ0OWI","feature_type":"address","full_address":"1600 Pennsylvania Avenue Southeast, Washington, District of Columbia 20003, United States","name":"1600 Pennsylvania Avenue Southeast","name_preferred":"1600 Pennsylvania Avenue Southeast","coordinates":{"longitude":-76.981937,"latitude":38.87922,"accuracy":"rooftop","routable_points":[{"name":"default","latitude":38.879037,"longitude":-76.98206}]},"place_formatted":"Washington, District of Columbia 20003, United States","match_code":{"address_number":"matched","street":"unmatched","postcode":"unmatched","place":"matched","region":"matched","locality":"not_applicable","country":"inferred","confidence":"medium"},"context":{"address":{"mapbox_id":"dXJuOm1ieGFkcjpmOTYwMzc4OC01MWE4LTQ3NzQtOWVhMi1lM2ZkZGY0NWQ0OWI","address_number":"1600","street_name":"Pennsylvania Avenue Southeast","name":"1600 Pennsylvania Avenue Southeast"},"street":{"mapbox_id":"dXJuOm1ieGFkci1zdHI6Zjk2MDM3ODgtNTFhOC00Nzc0LTllYTItZTNmZGRmNDVkNDli","name":"Pennsylvania Avenue Southeast"},"neighborhood":{"mapbox_id":"dXJuOm1ieHBsYzpCVnVzN0E","name":"Capitol Hill","alternate":{"mapbox_id":"dXJuOm1ieHBsYzpFVzhzN0E","name":"Hill East"}},"postcode":{"mapbox_id":"dXJuOm1ieHBsYzpBNTZ1N0E","name":"20003"},"place":{"mapbox_id":"dXJuOm1ieHBsYzpGSmlvN0E","name":"Washington","wikidata_id":"Q61"},"region":{"mapbox_id":"dXJuOm1ieHBsYzpCUVRz","name":"District of Columbia","wikidata_id":"Q3551781","region_code":"DC","region_code_full":"US-DC"},"country":{"mapbox_id":"dXJuOm1ieHBsYzpJdXc","name":"United States","wikidata_id":"Q30","country_code":"US","country_code_alpha_3":"USA"}}}}],"attribution":"NOTICE: © 2026 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained."}"; \ No newline at end of file diff --git a/src/Provider/Mapbox/Tests/MapboxAddressTest.php b/src/Provider/Mapbox/Tests/MapboxAddressTest.php new file mode 100644 index 000000000..9f3f87153 --- /dev/null +++ b/src/Provider/Mapbox/Tests/MapboxAddressTest.php @@ -0,0 +1,60 @@ +build(MapboxAddress::class); + + $this->assertNull($address->getMatchCode()); + + $matchCode = ['street' => 'matched', 'confidence' => 'exact']; + $address = $address->withMatchCode($matchCode); + + $this->assertSame($matchCode, $address->getMatchCode()); + $this->assertNull($address->withMatchCode($matchCode)->withMatchCode()->getMatchCode()); + } + + public function testMatchConfidence(): void + { + /** @var MapboxAddress $address */ + $address = (new AddressBuilder('mapbox'))->build(MapboxAddress::class); + + $this->assertNull($address->getMatchConfidence()); + + $address = $address->withMatchConfidence('exact'); + + $this->assertSame('exact', $address->getMatchConfidence()); + $this->assertNull($address->withMatchConfidence('exact')->withMatchConfidence()->getMatchConfidence()); + } + + public function testAccuracy(): void + { + /** @var MapboxAddress $address */ + $address = (new AddressBuilder('mapbox'))->build(MapboxAddress::class); + + $this->assertNull($address->getAccuracy()); + + $address = $address->withAccuracy('rooftop'); + + $this->assertSame('rooftop', $address->getAccuracy()); + $this->assertNull($address->withAccuracy('rooftop')->withAccuracy()->getAccuracy()); + } +} diff --git a/src/Provider/Mapbox/Tests/MapboxTest.php b/src/Provider/Mapbox/Tests/MapboxTest.php index 82668e672..ce351a79c 100644 --- a/src/Provider/Mapbox/Tests/MapboxTest.php +++ b/src/Provider/Mapbox/Tests/MapboxTest.php @@ -12,6 +12,7 @@ namespace Geocoder\Provider\Mapbox\Tests; +use Geocoder\Exception\InvalidServerResponse; use Geocoder\IntegrationTest\BaseTestCase; use Geocoder\Model\AddressCollection; use Geocoder\Model\Bounds; @@ -19,6 +20,7 @@ use Geocoder\Provider\Mapbox\Model\MapboxAddress; use Geocoder\Query\GeocodeQuery; use Geocoder\Query\ReverseQuery; +use Psr\Http\Message\RequestInterface; class MapboxTest extends BaseTestCase { @@ -72,28 +74,204 @@ public function testGeocodeWithQuotaExceeded(): void $provider->geocodeQuery(GeocodeQuery::create('10 avenue Gambetta, Paris, France')); } - public function testGeocodePlaceWithNoCountryShortCode(): void + public function testGeocodeWithInvalidApiKey(): void { - $provider = new Mapbox($this->getHttpClient($_SERVER['MAPBOX_GEOCODING_KEY']), $_SERVER['MAPBOX_GEOCODING_KEY']); + // The v6 API answers 401 for an invalid token (v5 answered 403). + // Both status codes map to InvalidCredentials in AbstractHttpProvider. + $this->expectException(\Geocoder\Exception\InvalidCredentials::class); - $query = GeocodeQuery::create('princ'); // Principato di Monaco - $query = $query->withLocale('it'); - $query = $query->withBounds(new Bounds( - 35.82809688193029, - -11.36323261153737, - 59.05992036364424, - 34.33947713277206 - )); - $query = $query->withLimit(1); - $query = $query->withData('location_type', [ - Mapbox::TYPE_PLACE, - Mapbox::TYPE_LOCALITY, - Mapbox::TYPE_NEIGHBORHOOD, - Mapbox::TYPE_POI, - Mapbox::TYPE_POI_LANDMARK, - ]); + $provider = new Mapbox($this->getMockedHttpClient('', 401), 'api_key'); + $provider->geocodeQuery(GeocodeQuery::create('10 avenue Gambetta, Paris, France')); + } - $results = $provider->geocodeQuery($query); + public function testReverseWithInvalidResponse(): void + { + $this->expectException(InvalidServerResponse::class); + + $provider = new Mapbox($this->getMockedHttpClient(), 'access_token'); + $provider->reverseQuery(ReverseQuery::fromCoordinates(1, 2)); + } + + private function assertRequestUrl(string $expectedUrl, callable $request): void + { + $uri = ''; + $client = $this->getMockedHttpClientCallback(function (RequestInterface $request) use (&$uri) { + $uri = (string) $request->getUri(); + }); + + try { + $request($client); + } catch (InvalidServerResponse $e) { + // the mocked client answers an empty body; we only assert the request + } + + $this->assertSame($expectedUrl, $uri); + } + + public function testForwardGeocodeUrl(): void + { + $this->assertRequestUrl( + 'https://api.mapbox.com/search/geocode/v6/forward' + .'?q=10+Downing+St%2C+London' + .'&types=address' + .'&limit=5' + .'&access_token=access_token', + static function ($client) { + (new Mapbox($client, 'access_token'))->geocodeQuery(GeocodeQuery::create('10 Downing St, London')); + } + ); + } + + public function testForwardGeocodeUrlWithAllOptions(): void + { + $this->assertRequestUrl( + 'https://api.mapbox.com/search/geocode/v6/forward' + .'?q=wahsington' + .'&bbox=-124.83609163%2C45.54372254%2C-116.91742984%2C49.00243912' + .'&types=address%2Cstreet' + .'&autocomplete=true' + .'&proximity=-120.09%2C47.60' + .'&worldview=us' + .'&country=US' + .'&language=en' + .'&limit=10' + .'&permanent=true' + .'&access_token=access_token', + static function ($client) { + $provider = new Mapbox($client, 'access_token', 'US', true); + $query = GeocodeQuery::create('wahsington') + ->withLocale('en') + ->withBounds(new Bounds(45.54372254, -124.83609163, 49.00243912, -116.91742984)) + ->withLimit(10) + ->withData('location_type', [Mapbox::TYPE_ADDRESS, Mapbox::TYPE_STREET]) + ->withData('autocomplete', true) + ->withData('proximity', '-120.09,47.60') + ->withData('worldview', 'us'); + $provider->geocodeQuery($query); + } + ); + } + + public function testForwardGeocodeUrlWithStructuredInput(): void + { + // Structured Input: the query text is NOT sent; fields use their v6 names. + // autocomplete defaults to false for structured input (Mapbox guidance). + $this->assertRequestUrl( + 'https://api.mapbox.com/search/geocode/v6/forward' + .'?address_number=2595' + .'&street=Lucky+John+Dr' + .'&place=Park+City' + .'®ion=UT' + .'&postcode=84060' + .'&types=address' + .'&autocomplete=false' + .'&country=US' + .'&limit=5' + .'&access_token=access_token', + static function ($client) { + $provider = new Mapbox($client, 'access_token'); + $query = GeocodeQuery::create('2595 Lucky John Dr, Park City, UT 84060') + ->withData('address_number', '2595') + ->withData('street', 'Lucky John Dr') + ->withData('place', 'Park City') + ->withData('region', 'UT') + ->withData('postcode', '84060') + ->withData('country', 'US'); + $provider->geocodeQuery($query); + } + ); + } + + public function testForwardGeocodeUrlWithStructuredInputAndExplicitAutocomplete(): void + { + // an explicit autocomplete value overrides the structured-input default + $this->assertRequestUrl( + 'https://api.mapbox.com/search/geocode/v6/forward' + .'?street=9th+Street' + .'&types=address' + .'&autocomplete=true' + .'&limit=5' + .'&access_token=access_token', + static function ($client) { + $provider = new Mapbox($client, 'access_token'); + $query = GeocodeQuery::create('9th Street') + ->withData('street', '9th Street') + ->withData('autocomplete', true); + $provider->geocodeQuery($query); + } + ); + } + + public function testReverseGeocodeUrl(): void + { + $this->assertRequestUrl( + 'https://api.mapbox.com/search/geocode/v6/reverse' + .'?longitude=2.388911' + .'&latitude=48.8631507' + .'&types=address' + .'&limit=5' + .'&access_token=access_token', + static function ($client) { + (new Mapbox($client, 'access_token'))->reverseQuery(ReverseQuery::fromCoordinates(48.8631507, 2.388911)); + } + ); + } + + public function testReverseGeocodeUrlWithLocationTypeAndCountry(): void + { + $this->assertRequestUrl( + 'https://api.mapbox.com/search/geocode/v6/reverse' + .'?longitude=2.388911' + .'&latitude=48.8631507' + .'&types=address%2Cpostcode' + .'&country=FR' + .'&limit=2' + .'&access_token=access_token', + static function ($client) { + $provider = new Mapbox($client, 'access_token'); + $query = ReverseQuery::fromCoordinates(48.8631507, 2.388911) + ->withData('location_type', [Mapbox::TYPE_ADDRESS, Mapbox::TYPE_POSTCODE]) + ->withData('country', 'FR') + ->withLimit(2); + $provider->reverseQuery($query); + } + ); + } + + public function testParseForwardAddressFeature(): void + { + $json = <<<'JSON' + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "dXJuOm1ieGFkcjo3Njg3YjZmNy01YmZkLTQzMjItOGMzOS02OGE1NDhmZWYwM2U", + "geometry": { "type": "Point", "coordinates": [-122.413709, 37.7757] }, + "properties": { + "mapbox_id": "dXJuOm1ieGFkcjo3Njg3YjZmNy01YmZkLTQzMjItOGMzOS02OGE1NDhmZWYwM2U", + "feature_type": "address", + "name": "149 9th Street", + "full_address": "149 9th Street, San Francisco, California 94103, United States", + "coordinates": { "longitude": -122.413709, "latitude": 37.7757, "accuracy": "rooftop" }, + "match_code": { "address_number": "matched", "street": "matched", "confidence": "exact" }, + "context": { + "address": { "address_number": "149", "street_name": "9th Street", "name": "149 9th Street" }, + "street": { "name": "9th Street" }, + "neighborhood": { "name": "South of Market" }, + "postcode": { "name": "94103" }, + "place": { "name": "San Francisco" }, + "region": { "name": "California", "region_code": "CA", "region_code_full": "US-CA" }, + "country": { "name": "United States", "country_code": "US", "country_code_alpha_3": "USA" } + } + } + } + ] + } + JSON; + + $provider = new Mapbox($this->getMockedHttpClient($json), 'access_token'); + $results = $provider->geocodeQuery(GeocodeQuery::create('149 9th St, San Francisco, CA 94103')); $this->assertInstanceOf(AddressCollection::class, $results); $this->assertCount(1, $results); @@ -101,18 +279,181 @@ public function testGeocodePlaceWithNoCountryShortCode(): void /** @var MapboxAddress $result */ $result = $results->first(); $this->assertInstanceOf(MapboxAddress::class, $result); - $this->assertEqualsWithDelta(43.73125, $result->getCoordinates()->getLatitude(), 0.001); - $this->assertEqualsWithDelta(7.41974, $result->getCoordinates()->getLongitude(), 0.001); - $this->assertEquals('Principato di Monaco', $result->getStreetName()); - $this->assertEquals('Principato di Monaco', $result->getCountry()->getName()); - $this->assertEquals('place.4899176537126140', $result->getId()); + $this->assertEqualsWithDelta(37.7757, $result->getCoordinates()->getLatitude(), 0.00001); + $this->assertEqualsWithDelta(-122.413709, $result->getCoordinates()->getLongitude(), 0.00001); + $this->assertEquals('dXJuOm1ieGFkcjo3Njg3YjZmNy01YmZkLTQzMjItOGMzOS02OGE1NDhmZWYwM2U', $result->getId()); + $this->assertEquals('9th Street', $result->getStreetName()); + $this->assertEquals('149', $result->getStreetNumber()); + $this->assertEquals('94103', $result->getPostalCode()); + $this->assertEquals('San Francisco', $result->getLocality()); + $this->assertCount(2, $result->getAdminLevels()); + $this->assertEquals('San Francisco', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('California', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('CA', $result->getAdminLevels()->get(2)->getCode()); + $this->assertEquals('United States', $result->getCountry()->getName()); + $this->assertEquals('US', $result->getCountry()->getCode()); + $this->assertEquals('149 9th Street, San Francisco, California 94103, United States', $result->getFormattedAddress()); + $this->assertEquals('South of Market', $result->getNeighborhood()); + $this->assertEquals(['address'], $result->getResultType()); + $this->assertEquals('exact', $result->getMatchConfidence()); + $this->assertEquals('matched', $result->getMatchCode()['street']); + $this->assertEquals('rooftop', $result->getAccuracy()); + $this->assertNull($result->getTimezone()); + } - // not provided - $this->assertNull($result->getCountry()->getCode()); + public function testParseForwardPlaceFeature(): void + { + // place feature: no context.address; name is the place name; region code may be 3 letters + $json = <<<'JSON' + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "dXJuOm1ieHBsYzpoMmhQ", + "geometry": { "type": "Point", "coordinates": [-0.83069, 51.724422] }, + "properties": { + "mapbox_id": "dXJuOm1ieHBsYzpoMmhQ", + "feature_type": "place", + "name": "Princes Risborough", + "full_address": "Princes Risborough, Buckinghamshire, Inghilterra, Regno Unito", + "coordinates": { "longitude": -0.83069, "latitude": 51.724422 }, + "context": { + "place": { "name": "Princes Risborough" }, + "region": { "name": "Inghilterra", "region_code": "ENG" }, + "country": { "name": "Regno Unito", "country_code": "GB" } + } + } + } + ] + } + JSON; + + $provider = new Mapbox($this->getMockedHttpClient($json), 'access_token'); + $results = $provider->geocodeQuery(GeocodeQuery::create('princ')); + + $this->assertCount(1, $results); + + /** @var MapboxAddress $result */ + $result = $results->first(); + $this->assertEquals('dXJuOm1ieHBsYzpoMmhQ', $result->getId()); + $this->assertEquals('Princes Risborough', $result->getStreetName()); + $this->assertNull($result->getStreetNumber()); $this->assertNull($result->getPostalCode()); - $this->assertNull($result->getLocality()); - $this->assertNull($result->getTimezone()); + $this->assertEquals('Princes Risborough', $result->getLocality()); + $this->assertCount(2, $result->getAdminLevels()); + $this->assertEquals('Princes Risborough', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('Inghilterra', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('ENG', $result->getAdminLevels()->get(2)->getCode()); + $this->assertEquals('Regno Unito', $result->getCountry()->getName()); + $this->assertEquals('GB', $result->getCountry()->getCode()); + $this->assertEquals('Princes Risborough, Buckinghamshire, Inghilterra, Regno Unito', $result->getFormattedAddress()); + $this->assertNull($result->getNeighborhood()); + $this->assertEquals(['place'], $result->getResultType()); + $this->assertNull($result->getMatchConfidence()); + $this->assertNull($result->getMatchCode()); + $this->assertNull($result->getAccuracy()); + } + + public function testParseForwardStreetFeature(): void + { + // v6 street feature: street name comes from context.street + $json = <<<'JSON' + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "address.7607992201284362", + "geometry": { "type": "Point", "coordinates": [-117.039767, 46.930253] }, + "properties": { + "mapbox_id": "address.7607992201284362", + "feature_type": "street", + "name": "Washington Highway 6", + "full_address": "Washington Highway 6, Palouse, Washington 99161, United States", + "coordinates": { "longitude": -117.039767, "latitude": 46.930253 }, + "context": { + "street": { "name": "Washington Highway 6" }, + "postcode": { "name": "99161" }, + "place": { "name": "Palouse" }, + "region": { "name": "Washington", "region_code": "WA" }, + "country": { "name": "United States", "country_code": "US" } + } + } + } + ] + } + JSON; + + $provider = new Mapbox($this->getMockedHttpClient($json), 'access_token'); + $results = $provider->geocodeQuery(GeocodeQuery::create('Washington Highway 6')); + + $this->assertCount(1, $results); + + /** @var MapboxAddress $result */ + $result = $results->first(); + $this->assertEquals('address.7607992201284362', $result->getId()); + $this->assertEquals('Washington Highway 6', $result->getStreetName()); $this->assertNull($result->getStreetNumber()); + $this->assertEquals('99161', $result->getPostalCode()); + $this->assertEquals('Palouse', $result->getLocality()); + $this->assertEquals('Washington', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('WA', $result->getAdminLevels()->get(2)->getCode()); + $this->assertEquals(['street'], $result->getResultType()); + } + + public function testParseFeatureWithoutContext(): void + { + // features without a context object must still parse (name + coordinates) + $json = <<<'JSON' + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "id": "abc123", + "geometry": { "type": "Point", "coordinates": [2.35, 48.85] }, + "properties": { + "mapbox_id": "abc123", + "feature_type": "place", + "name": "Some Place", + "coordinates": { "longitude": 2.35, "latitude": 48.85 } + } + } + ] + } + JSON; + + $provider = new Mapbox($this->getMockedHttpClient($json), 'access_token'); + $results = $provider->geocodeQuery(GeocodeQuery::create('Some Place')); + + $this->assertCount(1, $results); + + /** @var MapboxAddress $result */ + $result = $results->first(); + $this->assertEquals('Some Place', $result->getStreetName()); + $this->assertEquals('abc123', $result->getId()); + $this->assertEqualsWithDelta(48.85, $result->getCoordinates()->getLatitude(), 0.00001); + $this->assertEqualsWithDelta(2.35, $result->getCoordinates()->getLongitude(), 0.00001); + } + + public function testParseEmptyFeatures(): void + { + $json = '{"type":"FeatureCollection","features":[]}'; + + $provider = new Mapbox($this->getMockedHttpClient($json), 'access_token'); + $results = $provider->geocodeQuery(GeocodeQuery::create('jsajhgsdkfjhsfkjhaldkadjaslgldasd')); + + $this->assertInstanceOf(AddressCollection::class, $results); + $this->assertEmpty($results); + } + + public function testParseInvalidJson(): void + { + $this->expectException(InvalidServerResponse::class); + + $provider = new Mapbox($this->getMockedHttpClient('{invalid json'), 'access_token'); + $provider->geocodeQuery(GeocodeQuery::create('10 Downing St, London')); } public function testGeocodeWithRealAddress(): void @@ -130,30 +471,56 @@ public function testGeocodeWithRealAddress(): void /** @var MapboxAddress $result */ $result = $results->first(); $this->assertInstanceOf(MapboxAddress::class, $result); - $this->assertEqualsWithDelta(37.77572, $result->getCoordinates()->getLatitude(), 0.001); - $this->assertEqualsWithDelta(-122.41362, $result->getCoordinates()->getLongitude(), 0.001); - $this->assertNull($result->getBounds()); - $this->assertEquals(149, $result->getStreetNumber()); + $this->assertEqualsWithDelta(37.7757, $result->getCoordinates()->getLatitude(), 0.001); + $this->assertEqualsWithDelta(-122.413709, $result->getCoordinates()->getLongitude(), 0.001); $this->assertEquals('9th Street', $result->getStreetName()); - $this->assertEquals(94103, $result->getPostalCode()); + $this->assertEquals('149', $result->getStreetNumber()); + $this->assertEquals('94103', $result->getPostalCode()); $this->assertEquals('San Francisco', $result->getLocality()); + $this->assertCount(2, $result->getAdminLevels()); $this->assertEquals('California', $result->getAdminLevels()->get(2)->getName()); $this->assertEquals('CA', $result->getAdminLevels()->get(2)->getCode()); - $this->assertEquals('San Francisco', $result->getAdminLevels()->get(1)->getName()); $this->assertEquals('United States', $result->getCountry()->getName()); $this->assertEquals('US', $result->getCountry()->getCode()); - $this->assertEquals('address.3071152063251042', $result->getId()); + $this->assertEquals('149 9th Street, San Francisco, California 94103, United States', $result->getFormattedAddress()); + $this->assertEquals('South of Market', $result->getNeighborhood()); + $this->assertEquals(['address'], $result->getResultType()); + $this->assertEquals('exact', $result->getMatchConfidence()); + $this->assertEquals('rooftop', $result->getAccuracy()); // not provided $this->assertNull($result->getTimezone()); } - public function testReverse(): void + public function testGeocodeWithRealAddressInDc(): void { - $this->expectException(\Geocoder\Exception\InvalidServerResponse::class); + if (!isset($_SERVER['MAPBOX_GEOCODING_KEY'])) { + $this->markTestSkipped('You need to configure the MAPBOX_GEOCODING_KEY value in phpunit.xml'); + } - $provider = new Mapbox($this->getMockedHttpClient(), 'access_token'); - $provider->reverseQuery(ReverseQuery::fromCoordinates(1, 2)); + $provider = new Mapbox($this->getHttpClient($_SERVER['MAPBOX_GEOCODING_KEY']), $_SERVER['MAPBOX_GEOCODING_KEY']); + $results = $provider->geocodeQuery(GeocodeQuery::create('1600 Pennsylvania Avenue NW, Washington, DC 20500')); + + $this->assertInstanceOf(AddressCollection::class, $results); + $this->assertCount(2, $results); + + /** @var MapboxAddress $result */ + $result = $results->first(); + $this->assertInstanceOf(MapboxAddress::class, $result); + $this->assertEqualsWithDelta(38.897684, $result->getCoordinates()->getLatitude(), 0.001); + $this->assertEqualsWithDelta(-77.036574, $result->getCoordinates()->getLongitude(), 0.001); + $this->assertEquals('Pennsylvania Avenue Northwest', $result->getStreetName()); + $this->assertEquals('1600', $result->getStreetNumber()); + $this->assertEquals('20500', $result->getPostalCode()); + $this->assertEquals('Washington', $result->getLocality()); + $this->assertCount(2, $result->getAdminLevels()); + $this->assertEquals('District of Columbia', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('DC', $result->getAdminLevels()->get(2)->getCode()); + $this->assertEquals('United States', $result->getCountry()->getName()); + $this->assertEquals('US', $result->getCountry()->getCode()); + $this->assertEquals('1600 Pennsylvania Avenue Northwest, Washington, District of Columbia 20500, United States', $result->getFormattedAddress()); + $this->assertEquals('exact', $result->getMatchConfidence()); + $this->assertEquals('rooftop', $result->getAccuracy()); } public function testReverseWithRealCoordinates(): void @@ -171,26 +538,25 @@ public function testReverseWithRealCoordinates(): void /** @var MapboxAddress $result */ $result = $results->first(); $this->assertInstanceOf(MapboxAddress::class, $result); - $this->assertEquals(8, $result->getStreetNumber()); + $this->assertEquals('12', $result->getStreetNumber()); $this->assertEquals('Avenue Gambetta', $result->getStreetName()); - $this->assertEquals(75020, $result->getPostalCode()); + $this->assertEquals('75020', $result->getPostalCode()); $this->assertEquals('Paris', $result->getLocality()); - $this->assertCount(1, $result->getAdminLevels()); + $this->assertCount(2, $result->getAdminLevels()); $this->assertEquals('Paris', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('Île-de-France', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('IDF', $result->getAdminLevels()->get(2)->getCode()); $this->assertEquals('France', $result->getCountry()->getName()); $this->assertEquals('FR', $result->getCountry()->getCode()); - $this->assertEquals('address.1085979616', $result->getId()); - } + $this->assertEquals('12 Avenue Gambetta, 75020 Paris, France', $result->getFormattedAddress()); + $this->assertEquals('rooftop', $result->getAccuracy()); - public function testGeocodeWithInvalidApiKey(): void - { - $this->expectException(\Geocoder\Exception\InvalidCredentials::class); - - $provider = new Mapbox($this->getMockedHttpClient('', 403), 'api_key'); - $provider->geocodeQuery(GeocodeQuery::create('10 avenue Gambetta, Paris, France')); + // not provided by reverse geocoding + $this->assertNull($result->getMatchConfidence()); + $this->assertNull($result->getNeighborhood()); } - public function testGeocodeWithRealValidApiKey(): void + public function testGeocodePlaceWithLocale(): void { if (!isset($_SERVER['MAPBOX_GEOCODING_KEY'])) { $this->markTestSkipped('You need to configure the MAPBOX_GEOCODING_KEY value in phpunit.xml'); @@ -198,31 +564,48 @@ public function testGeocodeWithRealValidApiKey(): void $provider = new Mapbox($this->getHttpClient($_SERVER['MAPBOX_GEOCODING_KEY']), $_SERVER['MAPBOX_GEOCODING_KEY']); - $results = $provider->geocodeQuery(GeocodeQuery::create('116th St & Broadway, New York, NY 10027, United States')); + $query = GeocodeQuery::create('princ'); + $query = $query->withLocale('it'); + $query = $query->withBounds(new Bounds( + 35.82809688193029, + -11.36323261153737, + 59.05992036364424, + 34.33947713277206 + )); + $query = $query->withLimit(1); + $query = $query->withData('location_type', [ + Mapbox::TYPE_PLACE, + Mapbox::TYPE_LOCALITY, + Mapbox::TYPE_NEIGHBORHOOD, + ]); + + $results = $provider->geocodeQuery($query); $this->assertInstanceOf(AddressCollection::class, $results); - $this->assertCount(5, $results); + $this->assertCount(1, $results); /** @var MapboxAddress $result */ $result = $results->first(); $this->assertInstanceOf(MapboxAddress::class, $result); - $this->assertEquals('116th Street', $result->getStreetName()); - $this->assertEquals(11356, $result->getPostalCode()); - $this->assertCount(2, $result->getAdminLevels()); - $this->assertEquals('United States', $result->getCountry()->getName()); - $this->assertEquals('US', $result->getCountry()->getCode()); - $this->assertEquals('address.2431617896783536', $result->getId()); - $this->assertNotNull($result->getCoordinates()->getLatitude()); - $this->assertNotNull($result->getCoordinates()->getLongitude()); - $this->assertEqualsWithDelta(40.786596, $result->getCoordinates()->getLatitude(), 0.001); - $this->assertEqualsWithDelta(-73.851157, $result->getCoordinates()->getLongitude(), 0.001); - $this->assertEquals('New York', $result->getLocality()); + $this->assertEqualsWithDelta(51.724422, $result->getCoordinates()->getLatitude(), 0.001); + $this->assertEqualsWithDelta(-0.83069, $result->getCoordinates()->getLongitude(), 0.001); + $this->assertEquals('Princes Risborough', $result->getStreetName()); + $this->assertEquals(['place'], $result->getResultType()); + $this->assertEquals('Princes Risborough', $result->getLocality()); $this->assertCount(2, $result->getAdminLevels()); - $this->assertEquals('New York', $result->getAdminLevels()->get(1)->getName()); - $this->assertEquals('NY', $result->getAdminLevels()->get(2)->getCode()); + $this->assertEquals('Princes Risborough', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('Inghilterra', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('ENG', $result->getAdminLevels()->get(2)->getCode()); + $this->assertEquals('Regno Unito', $result->getCountry()->getName()); + $this->assertEquals('GB', $result->getCountry()->getCode()); + + // not provided + $this->assertNull($result->getPostalCode()); + $this->assertNull($result->getStreetNumber()); + $this->assertNull($result->getMatchConfidence()); } - public function testGeocodeWithFuzzyMatch(): void + public function testGeocodeWithAutocompleteEnabled(): void { if (!isset($_SERVER['MAPBOX_GEOCODING_KEY'])) { $this->markTestSkipped('You need to configure the MAPBOX_GEOCODING_KEY value in phpunit.xml'); @@ -230,21 +613,35 @@ public function testGeocodeWithFuzzyMatch(): void $provider = new Mapbox($this->getHttpClient($_SERVER['MAPBOX_GEOCODING_KEY']), $_SERVER['MAPBOX_GEOCODING_KEY']); - $query = GeocodeQuery::create('wahsington'); // Washington - $query = $query->withData('fuzzy_match', true); + $query = GeocodeQuery::create('washi'); + $query = $query->withData('autocomplete', true); $query = $query->withBounds(new Bounds( 45.54372254, -124.83609163, 49.00243912, -116.91742984 )); + $query = $query->withData('location_type', [ + Mapbox::TYPE_REGION, + Mapbox::TYPE_NEIGHBORHOOD, + Mapbox::TYPE_STREET, + Mapbox::TYPE_PLACE, + Mapbox::TYPE_LOCALITY, + ]); $results = $provider->geocodeQuery($query); $this->assertInstanceOf(AddressCollection::class, $results); $this->assertCount(5, $results); + + /** @var MapboxAddress $first */ + $first = $results->first(); + $this->assertEquals(['region'], $first->getResultType()); + $this->assertEquals('Washington', $first->getStreetName()); + $this->assertEquals('Washington', $first->getAdminLevels()->get(2)->getName()); + $this->assertEquals('WA', $first->getAdminLevels()->get(2)->getCode()); } - public function testGeocodeWithoutFuzzyMatch(): void + public function testGeocodeWithAutocompleteDisabled(): void { if (!isset($_SERVER['MAPBOX_GEOCODING_KEY'])) { $this->markTestSkipped('You need to configure the MAPBOX_GEOCODING_KEY value in phpunit.xml'); @@ -252,17 +649,70 @@ public function testGeocodeWithoutFuzzyMatch(): void $provider = new Mapbox($this->getHttpClient($_SERVER['MAPBOX_GEOCODING_KEY']), $_SERVER['MAPBOX_GEOCODING_KEY']); - $query = GeocodeQuery::create('wahsington'); // Washington - $query = $query->withData('fuzzy_match', false); + $query = GeocodeQuery::create('washi'); + $query = $query->withData('autocomplete', false); $query = $query->withBounds(new Bounds( 45.54372254, -124.83609163, 49.00243912, -116.91742984 )); + $query = $query->withData('location_type', [ + Mapbox::TYPE_REGION, + Mapbox::TYPE_NEIGHBORHOOD, + Mapbox::TYPE_STREET, + Mapbox::TYPE_PLACE, + Mapbox::TYPE_LOCALITY, + ]); $results = $provider->geocodeQuery($query); $this->assertInstanceOf(AddressCollection::class, $results); - $this->assertEmpty($results); + $this->assertCount(1, $results); + + /** @var MapboxAddress $first */ + $first = $results->first(); + $this->assertEquals(['street'], $first->getResultType()); + $this->assertEquals('Yashi Road', $first->getStreetName()); + } + + public function testGeocodeWithStructuredInput(): void + { + if (!isset($_SERVER['MAPBOX_GEOCODING_KEY'])) { + $this->markTestSkipped('You need to configure the MAPBOX_GEOCODING_KEY value in phpunit.xml'); + } + + $provider = new Mapbox($this->getHttpClient($_SERVER['MAPBOX_GEOCODING_KEY']), $_SERVER['MAPBOX_GEOCODING_KEY']); + + $query = GeocodeQuery::create('2595 Lucky John Dr, Park City, UT 84060'); + $query = $query->withData('address_number', '2595'); + $query = $query->withData('street', 'Lucky John Dr'); + $query = $query->withData('place', 'Park City'); + $query = $query->withData('region', 'UT'); + $query = $query->withData('postcode', '84060'); + + $results = $provider->geocodeQuery($query); + + $this->assertInstanceOf(AddressCollection::class, $results); + $this->assertCount(1, $results); + + /** @var MapboxAddress $result */ + $result = $results->first(); + $this->assertInstanceOf(MapboxAddress::class, $result); + $this->assertEqualsWithDelta(40.6716, $result->getCoordinates()->getLatitude(), 0.001); + $this->assertEqualsWithDelta(-111.507008, $result->getCoordinates()->getLongitude(), 0.001); + $this->assertEquals('Lucky John Drive', $result->getStreetName()); + $this->assertEquals('2595', $result->getStreetNumber()); + $this->assertEquals('84060', $result->getPostalCode()); + $this->assertEquals('Park City', $result->getLocality()); + $this->assertCount(2, $result->getAdminLevels()); + $this->assertEquals('Park City', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('Utah', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('UT', $result->getAdminLevels()->get(2)->getCode()); + $this->assertEquals('United States', $result->getCountry()->getName()); + $this->assertEquals('US', $result->getCountry()->getCode()); + $this->assertEquals('2595 Lucky John Drive, Park City, Utah 84060, United States', $result->getFormattedAddress()); + $this->assertEquals('Park Meadows', $result->getNeighborhood()); + $this->assertEquals('exact', $result->getMatchConfidence()); + $this->assertEquals('rooftop', $result->getAccuracy()); } }