Last active
December 17, 2015 00:49
-
-
Save toin0u/5524236 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* 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; | |
use Geocoder\Exception\NoResultException; | |
use Geocoder\Exception\QuotaExceededException; | |
use Geocoder\Exception\UnsupportedException; | |
use Geocoder\HttpAdapter\HttpAdapterInterface; | |
/** | |
* @author William Durand <[email protected]> | |
*/ | |
class GoogleMapsProvider extends AbstractProvider implements ProviderInterface | |
{ | |
/** | |
* @var string | |
*/ | |
const ENDPOINT_URL = 'http://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false'; | |
/** | |
* @var string | |
*/ | |
const ENDPOINT_URL_SSL = 'https://maps.googleapis.com/maps/api/geocode/json?address=%s&sensor=false'; | |
/** | |
* @var string | |
*/ | |
private $region = null; | |
/** | |
* @var bool | |
*/ | |
private $useSsl = false; | |
/** | |
* @param HttpAdapterInterface $adapter An HTTP adapter. | |
* @param string $locale A locale (optional). | |
* @param string $region Region biasing (optional). | |
* @param bool $useSsl Whether to use an SSL connection (optional) | |
*/ | |
public function __construct(HttpAdapterInterface $adapter, $locale = null, $region = null, $useSsl = false) | |
{ | |
parent::__construct($adapter, $locale); | |
$this->region = $region; | |
$this->useSsl = $useSsl; | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function getGeocodedData($address) | |
{ | |
// Google API returns invalid data if IP address given | |
// This API doesn't handle IPs | |
if (filter_var($address, FILTER_VALIDATE_IP)) { | |
throw new UnsupportedException('The GoogleMapsProvider does not support IP addresses.'); | |
} | |
$query = sprintf( | |
$this->useSsl ? self::ENDPOINT_URL_SSL : self::ENDPOINT_URL, | |
rawurlencode($address) | |
); | |
return $this->executeQuery($query); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function getReversedData(array $coordinates) | |
{ | |
return $this->getGeocodedData(sprintf('%F,%F', $coordinates[0], $coordinates[1])); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function getName() | |
{ | |
return 'google_maps'; | |
} | |
/** | |
* @param string $query | |
* | |
* @return string Query with extra params | |
*/ | |
protected function buildQuery($query) | |
{ | |
if (null !== $this->getLocale()) { | |
$query = sprintf('%s&language=%s', $query, $this->getLocale()); | |
} | |
if (null !== $this->getRegion()) { | |
$query = sprintf('%s®ion=%s', $query, $this->getRegion()); | |
} | |
return $query; | |
} | |
/** | |
* @param string $query | |
* | |
* @return array | |
*/ | |
protected function executeQuery($query) | |
{ | |
$query = $this->buildQuery($query); | |
$content = $this->getAdapter()->getContent($query); | |
if (null === $content) { | |
throw new NoResultException(sprintf('Could not execute query %s', $query)); | |
} | |
$json = json_decode($content); | |
// API error | |
if (!isset($json)) { | |
throw new NoResultException(sprintf('Could not execute query %s', $query)); | |
} | |
// you are over your quota | |
if ('OVER_QUERY_LIMIT' === $json->status) { | |
throw new QuotaExceededException(sprintf('Daily quota exceeded %s', $query)); | |
} | |
// no result | |
if (!isset($json->results) || !count($json->results) || 'OK' !== $json->status) { | |
throw new NoResultException(sprintf('Could not execute query %s', $query)); | |
} | |
$results = array(); | |
foreach ($json->results as $result) { | |
$resultset = $this->getDefaults(); | |
// update address components | |
foreach ($result->address_components as $component) { | |
foreach ($component->types as $type) { | |
$this->updateAddressComponent($resultset, $type, $component); | |
} | |
} | |
// update coordinates | |
$coordinates = $result->geometry->location; | |
$resultset['latitude'] = $coordinates->lat; | |
$resultset['longitude'] = $coordinates->lng; | |
$resultset['bounds'] = null; | |
if (isset($result->geometry->bounds)) { | |
$resultset['bounds'] = array( | |
'south' => $result->geometry->bounds->southwest->lat, | |
'west' => $result->geometry->bounds->southwest->lng, | |
'north' => $result->geometry->bounds->northeast->lat, | |
'east' => $result->geometry->bounds->northeast->lng | |
); | |
} elseif ('ROOFTOP' === $result->geometry->location_type) { | |
// Fake bounds | |
$resultset['bounds'] = array( | |
'south' => $coordinates->lat, | |
'west' => $coordinates->lng, | |
'north' => $coordinates->lat, | |
'east' => $coordinates->lng | |
); | |
} | |
$results[] = array_merge($this->getDefaults(), $resultset); | |
} | |
return $results; | |
} | |
/** | |
* Update current resultset with given key/value. | |
* | |
* @param array $resultset Resultset to update. | |
* @param string $type Component type. | |
* @param object $values The component values; | |
* | |
* @return array | |
*/ | |
protected function updateAddressComponent(&$resultset, $type, $values) | |
{ | |
switch ($type) { | |
case 'postal_code': | |
$resultset['zipcode'] = $values->long_name; | |
break; | |
case 'locality': | |
$resultset['city'] = $values->long_name; | |
break; | |
case 'administrative_area_level_2': | |
$resultset['county'] = $values->long_name; | |
$resultset['countyCode'] = $values->short_name; | |
break; | |
case 'administrative_area_level_1': | |
$resultset['region'] = $values->long_name; | |
$resultset['regionCode'] = $values->short_name; | |
break; | |
case 'country': | |
$resultset['country'] = $values->long_name; | |
$resultset['countryCode'] = $values->short_name; | |
break; | |
case 'street_number': | |
$resultset['streetNumber'] = $values->long_name; | |
break; | |
case 'route': | |
$resultset['streetName'] = $values->long_name; | |
break; | |
case 'sublocality': | |
$resultset['cityDistrict'] = $values->long_name; | |
break; | |
default: | |
} | |
return $resultset; | |
} | |
/** | |
* Returns the configured region or null. | |
* | |
* @return string|null | |
*/ | |
protected function getRegion() | |
{ | |
return $this->region; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Array | |
( | |
[0] => Array | |
( | |
[latitude] => 48.856614 | |
[longitude] => 2.3522219 | |
[bounds] => Array | |
( | |
[south] => 48.815573 | |
[west] => 2.224199 | |
[north] => 48.9021449 | |
[east] => 2.4699208 | |
) | |
[streetNumber] => | |
[streetName] => | |
[city] => Paris | |
[zipcode] => | |
[cityDistrict] => | |
[county] => Paris | |
[countyCode] => 75 | |
[region] => Île-de-France | |
[regionCode] => IdF | |
[country] => France | |
[countryCode] => FR | |
[timezone] => | |
) | |
[1] => Array | |
( | |
[latitude] => 33.6609389 | |
[longitude] => -95.555513 | |
[bounds] => Array | |
( | |
[south] => 33.6118529 | |
[west] => -95.6279279 | |
[north] => 33.7383781 | |
[east] => -95.435455 | |
) | |
[streetNumber] => | |
[streetName] => | |
[city] => Paris | |
[zipcode] => | |
[cityDistrict] => | |
[county] => Lamar | |
[countyCode] => Lamar | |
[region] => Texas | |
[regionCode] => TX | |
[country] => United States | |
[countryCode] => US | |
[timezone] => | |
) | |
[2] => Array | |
( | |
[latitude] => 36.3020023 | |
[longitude] => -88.3267107 | |
[bounds] => Array | |
( | |
[south] => 36.266 | |
[west] => -88.3671149 | |
[north] => 36.3291321 | |
[east] => -88.2650759 | |
) | |
[streetNumber] => | |
[streetName] => | |
[city] => Paris | |
[zipcode] => 38242 | |
[cityDistrict] => | |
[county] => Henry | |
[countyCode] => Henry | |
[region] => Tennessee | |
[regionCode] => TN | |
[country] => United States | |
[countryCode] => US | |
[timezone] => | |
) | |
[3] => Array | |
( | |
[latitude] => 39.611146 | |
[longitude] => -87.6961374 | |
[bounds] => Array | |
( | |
[south] => 39.581415 | |
[west] => -87.721046 | |
[north] => 39.6485756 | |
[east] => -87.6505408 | |
) | |
[streetNumber] => | |
[streetName] => | |
[city] => Paris | |
[zipcode] => 61944 | |
[cityDistrict] => | |
[county] => Edgar | |
[countyCode] => Edgar | |
[region] => Illinois | |
[regionCode] => IL | |
[country] => United States | |
[countryCode] => US | |
[timezone] => | |
) | |
[4] => Array | |
( | |
[latitude] => 38.2097987 | |
[longitude] => -84.2529869 | |
[bounds] => Array | |
( | |
[south] => 38.164922 | |
[west] => -84.3073259 | |
[north] => 38.238271 | |
[east] => -84.232089 | |
) | |
[streetNumber] => | |
[streetName] => | |
[city] => Paris | |
[zipcode] => 40361 | |
[cityDistrict] => | |
[county] => Bourbon | |
[countyCode] => Bourbon | |
[region] => Kentucky | |
[regionCode] => KY | |
[country] => United States | |
[countryCode] => US | |
[timezone] => | |
) | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Array | |
( | |
[latitude] => 48.8234055 | |
[longitude] => 2.3072664 | |
[bounds] => Array | |
( | |
[south] => 48.8234055 | |
[west] => 2.3072664 | |
[north] => 48.8234055 | |
[east] => 2.3072664 | |
) | |
[streetNumber] => 10 | |
[streetName] => Rue Gambetta | |
[city] => Paris | |
[zipcode] => 92240 | |
[cityDistrict] => 14th arrondissement of Paris | |
[county] => Hauts-de-Seine | |
[countyCode] => 92 | |
[region] => Île-de-France | |
[regionCode] => IdF | |
[country] => France | |
[countryCode] => FR | |
[timezone] => | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment