Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Google Maps] Fix issue with duplicated SubLocalityLevels #1174

Merged
merged 9 commits into from
Apr 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions src/Provider/GoogleMaps/Model/GoogleAddress.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -516,21 +516,26 @@ public function getSubLocalityLevels()
*/ */
public function withSubLocalityLevels(array $subLocalityLevel) public function withSubLocalityLevels(array $subLocalityLevel)
{ {
$levels = array_filter($subLocalityLevel, function ($level) {
return !empty($level['level']) && (!empty($level['name']) || !empty($level['code']));
});

$levelCount = array_count_values(array_column($levels, 'level'));

$subLocalityLevels = []; $subLocalityLevels = [];
foreach ($subLocalityLevel as $level) { foreach ($levelCount as $level => $count) {
if (empty($level['level'])) { $_levels = array_filter($levels, function ($l) use ($level) {
continue; return $l['level'] === $level;
} });


$name = $level['name'] ?? $level['code'] ?? ''; $names = array_filter(array_column($_levels, 'name'), function ($name) { return !empty($name); });
if (empty($name)) { $codes = array_filter(array_column($_levels, 'code'), function ($code) { return !empty($code); });
continue;
}


$subLocalityLevels[] = new AdminLevel($level['level'], $name, $level['code'] ?? null); $name = count($names) > 0 ? implode(' / ', $names) : implode(' / ', $codes);
} $code = count($codes) > 0 ? implode(' / ', $codes) : null;


$subLocalityLevels = array_unique($subLocalityLevels); $subLocalityLevels[] = new AdminLevel($level, $name, $code);
}


$new = clone $this; $new = clone $this;
$new->subLocalityLevels = new AdminLevelCollection($subLocalityLevels); $new->subLocalityLevels = new AdminLevelCollection($subLocalityLevels);
Expand Down
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,80 @@
s:2655:"{
"results" : [
{
"address_components" : [
{
"long_name" : "Rue de Pont-à-Migneloux",
"short_name" : "Rue de Pont-à-Migneloux",
"types" : [ "route" ]
},
{
"long_name" : "Wayaux",
"short_name" : "Wayaux",
"types" : [ "political", "sublocality", "sublocality_level_1" ]
},
{
"long_name" : "Les Bons Villers",
"short_name" : "Les Bons Villers",
"types" : [ "political", "sublocality", "sublocality_level_1" ]
},
{
"long_name" : "Frasnes-lez-Gosselies",
"short_name" : "Frasnes-lez-Gosselies",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Hainaut",
"short_name" : "HT",
"types" : [ "administrative_area_level_2", "political" ]
},
{
"long_name" : "Région Wallonne",
"short_name" : "Région Wallonne",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "Belgium",
"short_name" : "BE",
"types" : [ "country", "political" ]
},
{
"long_name" : "6210",
"short_name" : "6210",
"types" : [ "postal_code" ]
}
],
"formatted_address" : "Rue de Pont-à-Migneloux, 6210 Les Bons Villers, Belgium",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 50.49571500000003,
"lng" : 4.473629799999999
},
"southwest" : {
"lat" : 50.48990779999998,
"lng" : 4.4595167
}
},
"location" : {
"lat" : 50.4944514,
"lng" : 4.4694362
},
"location_type" : "GEOMETRIC_CENTER",
"viewport" : {
"northeast" : {
"lat" : 50.49571500000003,
"lng" : 4.473629799999999
},
"southwest" : {
"lat" : 50.48990779999998,
"lng" : 4.4595167
}
}
},
"place_id" : "EjhSdWUgZGUgUG9udC3DoC1NaWduZWxvdXgsIDYyMTAgTGVzIEJvbnMgVmlsbGVycywgQmVsZ2l1bSIuKiwKFAoSCcPJx0xGKcJHEUw-Q8kfZcEeEhQKEgmHf2F_QCnCRxF02JKWsgNAAA",
"types" : [ "route" ]
}
],
"status" : "OK"
}
";
41 changes: 31 additions & 10 deletions src/Provider/GoogleMaps/Tests/GoogleMapsTest.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@


use Geocoder\Exception\InvalidServerResponse; use Geocoder\Exception\InvalidServerResponse;
use Geocoder\IntegrationTest\BaseTestCase; use Geocoder\IntegrationTest\BaseTestCase;
use Geocoder\Location;
use Geocoder\Model\Address; use Geocoder\Model\Address;
use Geocoder\Model\AddressCollection; use Geocoder\Model\AddressCollection;
use Geocoder\Provider\GoogleMaps\Model\GoogleAddress; use Geocoder\Provider\GoogleMaps\Model\GoogleAddress;
Expand Down Expand Up @@ -94,7 +93,7 @@ public function testGeocodeWithRealAddress()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(1, $results); $this->assertCount(1, $results);


/** @var Location $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertEqualsWithDelta(48.8630462, $result->getCoordinates()->getLatitude(), 0.001); $this->assertEqualsWithDelta(48.8630462, $result->getCoordinates()->getLatitude(), 0.001);
Expand Down Expand Up @@ -128,7 +127,7 @@ public function testGeocodeBoundsWithRealAddressForNonRooftopLocation()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(1, $results); $this->assertCount(1, $results);


/** @var Location $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertNotNull($result->getBounds()); $this->assertNotNull($result->getBounds());
Expand Down Expand Up @@ -156,7 +155,7 @@ public function testReverseWithRealCoordinates()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(5, $results); $this->assertCount(5, $results);


/** @var Location $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertEquals(12, $result->getStreetNumber()); $this->assertEquals(12, $result->getStreetNumber());
Expand All @@ -180,7 +179,7 @@ public function testReverseWithRealCoordinatesAndLocale()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(5, $results); $this->assertCount(5, $results);


/** @var Location $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertEquals(12, $result->getStreetNumber()); $this->assertEquals(12, $result->getStreetNumber());
Expand All @@ -204,7 +203,7 @@ public function testGeocodeWithCityDistrict()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(1, $results); $this->assertCount(1, $results);


/** @var Location $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertEquals('Kalbach-Riedberg', $result->getSubLocality()); $this->assertEquals('Kalbach-Riedberg', $result->getSubLocality());
Expand All @@ -228,7 +227,7 @@ public function testGeocodeWithRealValidApiKey()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(1, $results); $this->assertCount(1, $results);


/** @var Location $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertNotNull($result->getCoordinates()->getLatitude()); $this->assertNotNull($result->getCoordinates()->getLatitude());
Expand All @@ -251,7 +250,7 @@ public function testGeocodeWithComponentFiltering()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(1, $results); $this->assertCount(1, $results);


/** @var Location $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertEquals('Malmö', $result->getLocality()); $this->assertEquals('Malmö', $result->getLocality());
Expand Down Expand Up @@ -340,7 +339,7 @@ public function testGeocodePostalTown()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(1, $results); $this->assertCount(1, $results);


/** @var Location $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertEquals('Pontypridd', $result->getLocality()); $this->assertEquals('Pontypridd', $result->getLocality());
Expand Down Expand Up @@ -558,7 +557,7 @@ public function testGeocodeBoundsWithRealAddressWithViewportOnly()
$this->assertInstanceOf(AddressCollection::class, $results); $this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(1, $results); $this->assertCount(1, $results);


/** @var \Geocoder\Model\Address $result */ /** @var GoogleAddress $result */
$result = $results->first(); $result = $results->first();
$this->assertInstanceOf(Address::class, $result); $this->assertInstanceOf(Address::class, $result);
$this->assertNotNull($result->getBounds()); $this->assertNotNull($result->getBounds());
Expand All @@ -569,6 +568,28 @@ public function testGeocodeBoundsWithRealAddressWithViewportOnly()
$this->assertEquals(false, $result->isPartialMatch()); $this->assertEquals(false, $result->isPartialMatch());
} }


public function testGeocodeDuplicateSubLocalityLevel()
{
$provider = $this->getGoogleMapsProvider();
$results = $provider->geocodeQuery(GeocodeQuery::create('Rue de Pont-A-Migneloux, 6210 Wayaux, Belgique'));

$this->assertInstanceOf(AddressCollection::class, $results);
$this->assertCount(1, $results);

/** @var GoogleAddress $result */
$result = $results->first();
$this->assertInstanceOf(Address::class, $result);
$this->assertEquals('Rue de Pont-à-Migneloux, 6210 Les Bons Villers, Belgium', $result->getFormattedAddress());
$this->assertEquals('Les Bons Villers', $result->getSubLocality());
$this->assertCount(2, $result->getAdminLevels());
$this->assertEquals('Région Wallonne', $result->getAdminLevels()->get(1)->getName());
$this->assertEquals('Hainaut', $result->getAdminLevels()->get(2)->getName());
$this->assertInstanceOf('\Geocoder\Model\AdminLevelCollection', $result->getSubLocalityLevels());
$this->assertEquals(1, $result->getSubLocalityLevels()->get(1)->getLevel());
$this->assertEquals('Wayaux / Les Bons Villers', $result->getSubLocalityLevels()->get(1)->getName());
$this->assertEquals('Wayaux / Les Bons Villers', $result->getSubLocalityLevels()->get(1)->getCode());
}

private function getGoogleMapsProvider(): GoogleMaps private function getGoogleMapsProvider(): GoogleMaps
{ {
if (!isset($_SERVER['GOOGLE_GEOCODING_KEY'])) { if (!isset($_SERVER['GOOGLE_GEOCODING_KEY'])) {
Expand Down