diff --git a/src/Geocoder/Provider/GoogleMaps.php b/src/Geocoder/Provider/GoogleMaps.php index e0d179507..2c3295e53 100644 --- a/src/Geocoder/Provider/GoogleMaps.php +++ b/src/Geocoder/Provider/GoogleMaps.php @@ -39,6 +39,11 @@ final class GoogleMaps extends AbstractHttpProvider implements LocaleAwareProvid */ private $region; + /** + * @var array + */ + private $componentFilters; + /** * @var bool */ @@ -133,6 +138,11 @@ public function getName() return 'google_maps'; } + /** + * @param $region + * + * @return $this + */ public function setRegion($region) { $this->region = $region; @@ -140,6 +150,21 @@ public function setRegion($region) return $this; } + /** + * Add components for filtering. + * https://developers.google.com/maps/documentation/geocoding/#ComponentFiltering + * + * @param array $filters + * + * @return $this + */ + public function setComponentFilters(array $filters) + { + $this->componentFilters = $filters; + + return $this; + } + /** * @param string $query * @@ -167,11 +192,21 @@ private function buildQuery($query) } } + if (!empty($this->componentFilters)) { + $componentFilters = $this->componentFilters; + + $query = sprintf('%s&key=%s&components=%s', $query, $this->apiKey, implode('|', array_map(function($key) use ($componentFilters) { + return $key.':'.urlencode($componentFilters[$key]); + }, array_keys($componentFilters)))); + } + return $query; } /** * @param string $query + * @return \Geocoder\Model\AddressCollection + * @throws Exception */ private function executeQuery($query) { diff --git a/tests/Geocoder/Tests/Provider/GoogleMapsTest.php b/tests/Geocoder/Tests/Provider/GoogleMapsTest.php index 258ed5bfc..0580ec99a 100644 --- a/tests/Geocoder/Tests/Provider/GoogleMapsTest.php +++ b/tests/Geocoder/Tests/Provider/GoogleMapsTest.php @@ -427,4 +427,64 @@ public function testGeocodeWithInvalidClientIdAndKeyNoSsl() $provider = GoogleMaps::business($this->getAdapter(), 'foo', 'bogus', null, null, false); $provider->geocode('Columbia University'); } + + /** + * @expectedException \Geocoder\Exception\NoResult + * @expectedExceptionMessage Could not execute query + */ + public function testGeocodeWithComponentFiltersInvalidCountry() + { + $provider = new GoogleMaps($this->getAdapter(), 'fr-FR', 'Île-de-France'); + $arrFilters = ['country' => 'ru', 'postal_code' => '75020']; + $provider->setComponentFilters($arrFilters); + + $provider->geocode('10 avenue Gambetta, Paris, France'); + } + + /** + * @expectedException \Geocoder\Exception\NoResult + * @expectedExceptionMessage Could not execute query + */ + public function testGeocodeWithComponentFiltersInvalidZipCode() + { + $provider = new GoogleMaps($this->getAdapter(), 'fr-FR', 'Île-de-France'); + $arrFilters = ['country' => 'fr', 'postal_code' => '00000']; + $provider->setComponentFilters($arrFilters); + + $provider->geocode('10 avenue Gambetta, Paris, France'); + } + + public function testGeocodeWithValidComponentFilters() + { + $provider = new GoogleMaps($this->getAdapter(), 'fr-FR', 'Île-de-France'); + $arrFilters = ['country' => 'fr', 'postal_code' => '75020']; + $provider->setComponentFilters($arrFilters); + + $results = $provider->geocode('10 avenue Gambetta, Paris, France'); + + $this->assertInstanceOf('Geocoder\Model\AddressCollection', $results); + $this->assertCount(1, $results); + + /** @var \Geocoder\Model\Address $result */ + $result = $results->first(); + $this->assertInstanceOf('\Geocoder\Model\Address', $result); + $this->assertEquals(48.8630462, $result->getLatitude(), '', 0.001); + $this->assertEquals(2.3882487, $result->getLongitude(), '', 0.001); + $this->assertTrue($result->getBounds()->isDefined()); + $this->assertEquals(48.8630462, $result->getBounds()->getSouth(), '', 0.001); + $this->assertEquals(2.3882487, $result->getBounds()->getWest(), '', 0.001); + $this->assertEquals(48.8630462, $result->getBounds()->getNorth(), '', 0.001); + $this->assertEquals(2.3882487, $result->getBounds()->getEast(), '', 0.001); + $this->assertEquals(10, $result->getStreetNumber()); + $this->assertEquals('Avenue Gambetta', $result->getStreetName()); + $this->assertEquals(75020, $result->getPostalCode()); + $this->assertEquals('Paris', $result->getLocality()); + $this->assertEquals('Paris', $result->getAdminLevels()->get(2)->getName()); + $this->assertEquals('Île-de-France', $result->getAdminLevels()->get(1)->getName()); + $this->assertEquals('France', $result->getCountry()->getName()); + $this->assertEquals('FR', $result->getCountry()->getCode()); + // not provided + $this->assertNull($result->getTimezone()); + } + }