default services conflit ?

This commit is contained in:
armansansd
2022-04-27 11:30:43 +02:00
parent 28190a5749
commit 8bb1064a3b
8132 changed files with 900138 additions and 426 deletions

View File

@@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml

View File

@@ -0,0 +1,31 @@
# Change Log
The change log describes what is "Added", "Removed", "Changed" or "Fixed" between each release.
## 4.2.0
### Added
- Add support for PHP 8.0
### Removed
- Drop support for PHP 7.2
### Changed
- Upgrade PHPUnit to version 9
## 4.1.0
### Added
- Add `5BOX` support for address
### Removed
- Drop support for PHP < 7.2
## 4.0.0
First release of this library.

View File

@@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Provider\MapQuest;
use Geocoder\Location;
interface GetAddressInterface
{
/**
* @return Location|null
*/
public function getAddress();
}

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2011 — William Durand <william.durand1@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,417 @@
<?php
declare(strict_types=1);
/*
* This file is part of the Geocoder package.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @license MIT License
*/
namespace Geocoder\Provider\MapQuest;
use Geocoder\Collection;
use Geocoder\Exception\InvalidArgument;
use Geocoder\Exception\InvalidCredentials;
use Geocoder\Exception\InvalidServerResponse;
use Geocoder\Exception\QuotaExceeded;
use Geocoder\Exception\UnsupportedOperation;
use Geocoder\Http\Provider\AbstractHttpProvider;
use Geocoder\Location;
use Geocoder\Model\Address;
use Geocoder\Model\AddressCollection;
use Geocoder\Model\AdminLevel;
use Geocoder\Model\Bounds;
use Geocoder\Model\Country;
use Geocoder\Query\GeocodeQuery;
use Geocoder\Query\ReverseQuery;
use Geocoder\Provider\Provider;
use Http\Client\HttpClient;
use Psr\Http\Message\ResponseInterface;
/**
* @author William Durand <william.durand1@gmail.com>
*/
final class MapQuest extends AbstractHttpProvider implements Provider
{
const DATA_KEY_ADDRESS = 'address';
const KEY_API_KEY = 'key';
const KEY_LOCATION = 'location';
const KEY_OUT_FORMAT = 'outFormat';
const KEY_MAX_RESULTS = 'maxResults';
const KEY_THUMB_MAPS = 'thumbMaps';
const KEY_INTL_MODE = 'intlMode';
const KEY_BOUNDING_BOX = 'boundingBox';
const KEY_LAT = 'lat';
const KEY_LNG = 'lng';
const MODE_5BOX = '5BOX';
const OPEN_BASE_URL = 'https://open.mapquestapi.com/geocoding/v1/';
const LICENSED_BASE_URL = 'https://www.mapquestapi.com/geocoding/v1/';
const GEOCODE_ENDPOINT = 'address';
const DEFAULT_GEOCODE_PARAMS = [
self::KEY_LOCATION => '',
self::KEY_OUT_FORMAT => 'json',
self::KEY_API_KEY => '',
];
const DEFAULT_GEOCODE_OPTIONS = [
self::KEY_MAX_RESULTS => 3,
self::KEY_THUMB_MAPS => false,
];
const REVERSE_ENDPOINT = 'reverse';
const ADMIN_LEVEL_STATE = 1;
const ADMIN_LEVEL_COUNTY = 2;
/**
* MapQuest offers two geocoding endpoints one commercial (true) and one open (false)
* More information: http://developer.mapquest.com/web/tools/getting-started/platform/licensed-vs-open.
*
* @var bool
*/
private $licensed;
/**
* @var bool
*/
private $useRoadPosition;
/**
* @var string
*/
private $apiKey;
/**
* @param HttpClient $client an HTTP adapter
* @param string $apiKey an API key
* @param bool $licensed true to use MapQuest's licensed endpoints, default is false to use the open endpoints (optional)
* @param bool $useRoadPosition true to use nearest point on a road for the entrance, false to use map display position
*/
public function __construct(HttpClient $client, string $apiKey, bool $licensed = false, bool $useRoadPosition = false)
{
if (empty($apiKey)) {
throw new InvalidCredentials('No API key provided.');
}
$this->apiKey = $apiKey;
$this->licensed = $licensed;
$this->useRoadPosition = $useRoadPosition;
parent::__construct($client);
}
/**
* {@inheritdoc}
*/
public function geocodeQuery(GeocodeQuery $query): Collection
{
$params = static::DEFAULT_GEOCODE_PARAMS;
$params[static::KEY_API_KEY] = $this->apiKey;
$options = static::DEFAULT_GEOCODE_OPTIONS;
$options[static::KEY_MAX_RESULTS] = $query->getLimit();
$useGetQuery = true;
$address = $this->extractAddressFromQuery($query);
if ($address instanceof Location) {
$params[static::KEY_LOCATION] = $this->mapAddressToArray($address);
$options[static::KEY_INTL_MODE] = static::MODE_5BOX;
$useGetQuery = false;
} else {
$addressAsText = $query->getText();
if (!$addressAsText) {
throw new InvalidArgument('Cannot geocode empty address');
}
// This API doesn't handle IPs
if (filter_var($addressAsText, FILTER_VALIDATE_IP)) {
throw new UnsupportedOperation('The MapQuest provider does not support IP addresses, only street addresses.');
}
$params[static::KEY_LOCATION] = $addressAsText;
}
$bounds = $query->getBounds();
if ($bounds instanceof Bounds) {
$options[static::KEY_BOUNDING_BOX] = $this->mapBoundsToArray($bounds);
$useGetQuery = false;
}
if ($useGetQuery) {
$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);
}
}
/**
* {@inheritdoc}
*/
public function reverseQuery(ReverseQuery $query): Collection
{
$coordinates = $query->getCoordinates();
$longitude = $coordinates->getLongitude();
$latitude = $coordinates->getLatitude();
$params = [
static::KEY_API_KEY => $this->apiKey,
static::KEY_LAT => $latitude,
static::KEY_LNG => $longitude,
];
return $this->executeGetQuery(static::REVERSE_ENDPOINT, $params);
}
/**
* {@inheritdoc}
*/
public function getName(): string
{
return 'map_quest';
}
private function extractAddressFromQuery(GeocodeQuery $query)
{
return $query->getData(static::DATA_KEY_ADDRESS);
}
private function getUrl($endpoint): string
{
if ($this->licensed) {
$baseUrl = static::LICENSED_BASE_URL;
} else {
$baseUrl = static::OPEN_BASE_URL;
}
return $baseUrl.$endpoint;
}
private function addGetQuery(string $url, array $params): string
{
return $url.'?'.http_build_query($params, '', '&', PHP_QUERY_RFC3986);
}
private function addOptionsForGetQuery(array $params, array $options): array
{
foreach ($options as $key => $value) {
if (false === $value) {
$value = 'false';
} elseif (true === $value) {
$value = 'true';
}
$params[$key] = $value;
}
return $params;
}
private function addOptionsForPostQuery(array $params, array $options): array
{
$params['options'] = $options;
return $params;
}
private function executePostQuery(string $endpoint, array $params)
{
$url = $this->getUrl($endpoint);
$appKey = $params[static::KEY_API_KEY];
unset($params[static::KEY_API_KEY]);
$url .= '?key='.$appKey;
$requestBody = json_encode($params);
$request = $this->getMessageFactory()->createRequest('POST', $url, [], $requestBody);
$response = $this->getHttpClient()->sendRequest($request);
$content = $this->parseHttpResponse($response, $url);
return $this->parseResponseContent($content);
}
/**
* @param string $url
*
* @return AddressCollection
*/
private function executeGetQuery(string $endpoint, array $params): AddressCollection
{
$baseUrl = $this->getUrl($endpoint);
$url = $this->addGetQuery($baseUrl, $params);
$content = $this->getUrlContents($url);
return $this->parseResponseContent($content);
}
private function parseResponseContent(string $content): AddressCollection
{
$json = json_decode($content, true);
if (!isset($json['results']) || empty($json['results'])) {
return new AddressCollection([]);
}
$locations = $json['results'][0]['locations'];
if (empty($locations)) {
return new AddressCollection([]);
}
$results = [];
foreach ($locations as $location) {
if ($location['street'] || $location['postalCode'] || $location['adminArea5'] || $location['adminArea4'] || $location['adminArea3']) {
$admins = [];
$state = $location['adminArea3'];
if ($state) {
$code = null;
if (2 == strlen($state)) {
$code = $state;
}
$admins[] = [
'name' => $state,
'code' => $code,
'level' => static::ADMIN_LEVEL_STATE,
];
}
if ($location['adminArea4']) {
$admins[] = ['name' => $location['adminArea4'], 'level' => static::ADMIN_LEVEL_COUNTY];
}
$position = $location['latLng'];
if (!$this->useRoadPosition) {
if ($location['displayLatLng']) {
$position = $location['displayLatLng'];
}
}
$results[] = Address::createFromArray([
'providedBy' => $this->getName(),
'latitude' => $position['lat'],
'longitude' => $position['lng'],
'streetName' => $location['street'] ?: null,
'locality' => $location['adminArea5'] ?: null,
'subLocality' => $location['adminArea6'] ?: null,
'postalCode' => $location['postalCode'] ?: null,
'adminLevels' => $admins,
'country' => $location['adminArea1'] ?: null,
'countryCode' => $location['adminArea1'] ?: null,
]);
}
}
return new AddressCollection($results);
}
private function mapAddressToArray(Location $address): array
{
$location = [];
$streetParts = [
trim($address->getStreetNumber() ?: ''),
trim($address->getStreetName() ?: ''),
];
$street = implode(' ', array_filter($streetParts));
if ($street) {
$location['street'] = $street;
}
if ($address->getSubLocality()) {
$location['adminArea6'] = $address->getSubLocality();
$location['adminArea6Type'] = 'Neighborhood';
}
if ($address->getLocality()) {
$location['adminArea5'] = $address->getLocality();
$location['adminArea5Type'] = 'City';
}
/** @var AdminLevel $adminLevel */
foreach ($address->getAdminLevels() as $adminLevel) {
switch ($adminLevel->getLevel()) {
case static::ADMIN_LEVEL_STATE:
$state = $adminLevel->getCode();
if (!$state) {
$state = $adminLevel->getName();
}
$location['adminArea3'] = $state;
$location['adminArea3Type'] = 'State';
break;
case static::ADMIN_LEVEL_COUNTY:
$county = $adminLevel->getName();
$location['adminArea4'] = $county;
$location['adminArea4Type'] = 'County';
}
}
$country = $address->getCountry();
if ($country instanceof Country) {
$code = $country->getCode();
if (!$code) {
$code = $country->getName();
}
$location['adminArea1'] = $code;
$location['adminArea1Type'] = 'Country';
}
$postalCode = $address->getPostalCode();
if ($postalCode) {
$location['postalCode'] = $address->getPostalCode();
}
return $location;
}
private function mapBoundsToArray(Bounds $bounds)
{
return [
'ul' => [static::KEY_LAT => $bounds->getNorth(), static::KEY_LNG => $bounds->getWest()],
'lr' => [static::KEY_LAT => $bounds->getSouth(), static::KEY_LNG => $bounds->getEast()],
];
}
protected function parseHttpResponse(ResponseInterface $response, string $url): string
{
$statusCode = $response->getStatusCode();
if (401 === $statusCode || 403 === $statusCode) {
throw new InvalidCredentials();
} elseif (429 === $statusCode) {
throw new QuotaExceeded();
} elseif ($statusCode >= 300) {
throw InvalidServerResponse::create($url, $statusCode);
}
$body = (string) $response->getBody();
if (empty($body)) {
throw InvalidServerResponse::emptyResponse($url);
}
return $body;
}
}

View File

@@ -0,0 +1,78 @@
# MapQuest Geocoder provider
[![Build Status](https://travis-ci.org/geocoder-php/mapquest-provider.svg?branch=master)](http://travis-ci.org/geocoder-php/mapquest-provider)
[![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)
[![Monthly Downloads](https://poser.pugx.org/geocoder-php/mapquest-provider/d/monthly.png)](https://packagist.org/packages/geocoder-php/mapquest-provider)
[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/geocoder-php/mapquest-provider.svg?style=flat-square)](https://scrutinizer-ci.com/g/geocoder-php/mapquest-provider)
[![Quality Score](https://img.shields.io/scrutinizer/g/geocoder-php/mapquest-provider.svg?style=flat-square)](https://scrutinizer-ci.com/g/geocoder-php/mapquest-provider)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE)
This is the MapQuest provider from the PHP Geocoder. This is a **READ ONLY** repository. See the
[main repo](https://github.com/geocoder-php/Geocoder) for information and documentation.
### Install
```bash
composer require geocoder-php/mapquest-provider
```
### Geocode with more exact addresses
The MapQuest Provider allows you to create and pass geocode queries based on a full Address object of
class `Geocoder\Model\Address` or any other object that implements `Geocoder\Location`.
This will take advantage of what MapQuest calls the 5-box Input address format.
Quote from [MapQuest Developer: Specifying Locations](https://developer.mapquest.com/documentation/common/forming-locations/):
> The 5-Box Input address format (which is compatible with JSON and XML),
> allows for a higher degree of address specification by entering the full address in its individual location parameters.
> The 5-Box Input format is beneficial as it bypasses the parsing functionality of the single-line request.
If you have an object of a class that implements `Geocoder\Location` stored in the variable `$address`,
this new type of GeocodeQuery can be created with:
```
$query = GeocodeQuery::create('foobar');
$query = $query->withData(MapQuest::DATA_KEY_ADDRESS, $address);
```
If you want the GeocodeQuery to also work fine with all the other providers,
you will need to convert the `$address` object to a text string first.
Say you have stored this text string in the variable `$addressAsString`, the the example will read as follows:
```
$query = GeocodeQuery::create($addressAsString);
$query = $query->withData(MapQuest::DATA_KEY_ADDRESS, $address);
```
Here is a more complete example with use statements, and building of the address object:
**Example**
```
use Geocoder\Model\AddressBuilder;
use Geocoder\Provider\MapQuest\MapQuest;
use Geocoder\Query\GeocodeQuery;
$provider = new MapQuest($httpClient, $apiKey);
$addressBuilder = new AddressBuilder('Address provided by me');
$addressBuilder
->setStreetNumber(4868)
->setStreetName('Payne Rd');
->setLocality('Nashville');
->setSubLocality('Antioch');
->setAdminLevels([
new AdminLevel(1, 'Tennessee', 'TN')
])
->setPostalCode('37013');
->setCountry('USA');
->setCountryCode('US');
$address = $addressBuilder->build();
$query = GeocodeQuery::create('dummy data');
$query = $query->withData(MapQuest::DATA_KEY_ADDRESS, $address);
$results = $provider->geocodeQuery($query);
```
### Contribute
Contributions are very welcome! Send a pull request to the [main repository](https://github.com/geocoder-php/Geocoder) or
report any issues you find on the [issue tracker](https://github.com/geocoder-php/Geocoder/issues).

View File

@@ -0,0 +1,47 @@
{
"name": "geocoder-php/mapquest-provider",
"type": "library",
"description": "Geocoder MapQuest adapter",
"keywords": [],
"homepage": "http://geocoder-php.org/Geocoder/",
"license": "MIT",
"authors": [
{
"name": "William Durand",
"email": "william.durand1@gmail.com"
}
],
"require": {
"php": "^7.3 || ^8.0",
"geocoder-php/common-http": "^4.0",
"willdurand/geocoder": "^4.0"
},
"provide": {
"geocoder-php/provider-implementation": "1.0"
},
"require-dev": {
"geocoder-php/provider-integration-tests": "^1.1",
"php-http/curl-client": "^2.2",
"php-http/message": "^1.0",
"phpunit/phpunit": "^9.5"
},
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"psr-4": {
"Geocoder\\Provider\\MapQuest\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"test": "vendor/bin/phpunit",
"test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml"
}
}