From 1d87901bfb2015e0978503825a985eb12ff7ec11 Mon Sep 17 00:00:00 2001 From: Michele Locati Date: Tue, 2 Jul 2024 12:26:33 +0200 Subject: [PATCH] Allow restricting searching by names to specific territories --- README.md | 12 ++++ src/Finder.php | 55 +++++++++++++----- test/tests/Finder/FindByNameTest.php | 85 +++++++++++++++++++++++++--- 3 files changed, 132 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 6241981..281d5c8 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,18 @@ $provinces = $finder->findProvincesByName('ozen', true); $municipalities = $finder->findMunicipalitiesByName('oma ombard', true); ``` +You can also restrict the search to specific territories: + +```php +use MLocati\ComuniItaliani\Finder; + +$finder = new Finder(); + +$province = $finder->getProvinceByVehicleCode('BG'); +$municipalities = $finder->findMunicipalitiesByName('romano', false, $province); +// The same applies to findRegionsByName and findProvincesByName +``` + ### Testing Hierarchy Given two territories, you can check if they are the same by using the `isSame()` method: diff --git a/src/Finder.php b/src/Finder.php index c198b99..ffdf50e 100644 --- a/src/Finder.php +++ b/src/Finder.php @@ -130,6 +130,8 @@ public function getMunicipalityByID(string $id): ?Municipality } /** + * @param bool $allowMiddle Set to true to look for in the moddle of the words too. + * * @return \MLocati\ComuniItaliani\GeographicalSubdivision[] */ public function findGeographicalSubdivisionsByName(string $name, bool $allowMiddle = false): array @@ -138,27 +140,37 @@ public function findGeographicalSubdivisionsByName(string $name, bool $allowMidd } /** + * @param bool $allowMiddle Set to true to look for in the moddle of the words too. + * @param \MLocati\ComuniItaliani\GeographicalSubdivision|null $restrictTo only look for regions contained in a specific territory + * * @return \MLocati\ComuniItaliani\Region[] */ - public function findRegionsByName(string $name, bool $allowMiddle = false): array + public function findRegionsByName(string $name, bool $allowMiddle = false, ?TerritoryWithChildren $restrictTo = null): array { - return $this->findByName($name, $this->listRegions(), $allowMiddle, true); + return $this->findByName($name, $this->listRegions($restrictTo), $allowMiddle, true); } /** + * @param bool $allowMiddle Set to true to look for in the moddle of the words too. + * @param \MLocati\ComuniItaliani\GeographicalSubdivision|\MLocati\ComuniItaliani\Region|null $restrictTo only look for regions contained in a specific territory + * Only meaning + * * @return \MLocati\ComuniItaliani\Province[] */ - public function findProvincesByName(string $name, bool $allowMiddle = false): array + public function findProvincesByName(string $name, bool $allowMiddle = false, ?TerritoryWithChildren $restrictTo = null): array { - return $this->findByName($name, $this->listProvinces(), $allowMiddle, true); + return $this->findByName($name, $this->listProvinces($restrictTo), $allowMiddle, true); } /** + * @param bool $allowMiddle Set to true to look for in the moddle of the words too. + * @param \MLocati\ComuniItaliani\TerritoryWithChildren|null $restrictTo only look for regions contained in a specific territory + * * @return \MLocati\ComuniItaliani\Municipality[] */ - public function findMunicipalitiesByName(string $name, bool $allowMiddle = false): array + public function findMunicipalitiesByName(string $name, bool $allowMiddle = false, ?TerritoryWithChildren $restrictTo = null): array { - return $this->findByName($name, $this->listMunicipalities(), $allowMiddle, true); + return $this->findByName($name, $this->listMunicipalities($restrictTo), $allowMiddle, true); } /** @@ -173,7 +185,7 @@ protected function findByName(string $name, Generator $lister, bool $allowMiddle } $result = []; foreach ($lister as $territory) { - $territoryWords = $this->extractWords((string) $territory); + $territoryWords = $this->extractWords($territory->getName()); if ($this->matchesWords($wantedWords, $territoryWords, $allowMiddle)) { $result[] = $territory; } @@ -195,9 +207,16 @@ protected function listGeographicalSubdivisions(): Generator /** * @return \Generator<\MLocati\ComuniItaliani\Region> */ - protected function listRegions(): Generator + protected function listRegions(?TerritoryWithChildren $restrictTo = null): Generator { - foreach ($this->listGeographicalSubdivisions() as $geographicalSubdivision) { + if ($restrictTo instanceof GeographicalSubdivision) { + $geographicalSubdivisions = [$restrictTo]; + } elseif ($restrictTo === null) { + $geographicalSubdivisions = $this->listGeographicalSubdivisions(); + } else { + return; + } + foreach ($geographicalSubdivisions as $geographicalSubdivision) { foreach ($geographicalSubdivision->getRegions() as $region) { yield $region; } @@ -207,9 +226,14 @@ protected function listRegions(): Generator /** * @return \Generator<\MLocati\ComuniItaliani\Province> */ - protected function listProvinces(): Generator + protected function listProvinces(?TerritoryWithChildren $restrictTo = null): Generator { - foreach ($this->listRegions() as $region) { + if ($restrictTo instanceof Region) { + $regions = [$restrictTo]; + } else { + $regions = $this->listRegions($restrictTo); + } + foreach ($regions as $region) { foreach ($region->getProvinces() as $province) { yield $province; } @@ -219,9 +243,14 @@ protected function listProvinces(): Generator /** * @return \Generator<\MLocati\ComuniItaliani\Municipality> */ - protected function listMunicipalities(): Generator + protected function listMunicipalities(?TerritoryWithChildren $restrictTo = null): Generator { - foreach ($this->listProvinces() as $province) { + if ($restrictTo instanceof Province) { + $provinces = [$restrictTo]; + } else { + $provinces = $this->listProvinces($restrictTo); + } + foreach ($provinces as $province) { foreach ($province->getMunicipalities() as $municipality) { yield $municipality; } diff --git a/test/tests/Finder/FindByNameTest.php b/test/tests/Finder/FindByNameTest.php index 036bbab..f281b80 100644 --- a/test/tests/Finder/FindByNameTest.php +++ b/test/tests/Finder/FindByNameTest.php @@ -110,15 +110,15 @@ public function provideFindMunicipalitiesByNameCases(): array ['', []], ['ozzuoli', []], ['ozzuoli', ['Pozzuoli (NA)'], true], + ['lombard roma', []], + ['roma lombard', ['Romano di Lombardia (BG)']], + ['roma d lombard', ['Romano di Lombardia (BG)']], ['mano i lomb', []], ['mano i lomb', ['Romano di Lombardia (BG)'], true], - ['mano i bg', []], - ['mano i bg', ['Romano di Lombardia (BG)'], true], - ['roman d bg', ['Romano di Lombardia (BG)']], - ['ant su', ["Sant'Antioco (SU)", "Sant'Antonino di Susa (TO)"]], - ['roma d lombard', ['Romano di Lombardia (BG)']], - ['oma i ombard', []], - ['oma i ombard', ['Romano di Lombardia (BG)'], true], + ['mano i bardi', []], + ['mano i bardi', ['Romano di Lombardia (BG)'], true], + ['roman d lom', ['Romano di Lombardia (BG)']], + ['ant su', ["Sant'Antonino di Susa (TO)"]], ]; } @@ -134,6 +134,77 @@ public function testFindMunicipalitiesByName(string $search, array $expectedName $this->assertSame($expectedNames, $actualNames); } + public function testFindRestricted(): void + { + $finder = $this->getFinder(); + $geographicalSubdivision1 = $finder->findGeographicalSubdivisionsByName('nord ovest')[0]; + $this->assertSame('nord-ovest', strtolower((string) $geographicalSubdivision1)); + $geographicalSubdivision2 = $finder->findGeographicalSubdivisionsByName('sud')[0]; + $this->assertSame('sud', strtolower((string) $geographicalSubdivision2)); + $region1 = $finder->findRegionsByName('piemonte')[0]; + $this->assertSame('piemonte', strtolower((string) $region1)); + $region2 = $finder->findRegionsByName('puglia')[0]; + $this->assertSame('puglia', strtolower((string) $region2)); + $province1 = $finder->getProvinceByVehicleCode('to'); + $this->assertSame('torino', strtolower((string) $province1)); + $province2 = $finder->getProvinceByVehicleCode('ba'); + $this->assertSame('bari', strtolower((string) $province2)); + $municipality1 = null; + foreach ($province1->getMunicipalities() as $m) { + if ($municipality1 === null || strlen($m->getName()) > strlen($municipality1->getName())) { + $municipality1 = $m; + } + } + $this->assertNotSame('', (string) $municipality1); + $municipality2 = null; + foreach ($province2->getMunicipalities() as $m) { + if ($municipality2 === null || strlen($m->getName()) > strlen($municipality2->getName())) { + $municipality2 = $m; + } + } + $this->assertNotSame('', (string) $municipality2); + + $found = array_map('strval', $finder->findRegionsByName($region1->getName())); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findRegionsByName($region1->getName(), false, $geographicalSubdivision1)); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findRegionsByName($region1->getName(), false, $geographicalSubdivision2)); + $this->assertSame([], $found); + + $found = array_map('strval', $finder->findRegionsByName($region1->getName(), false, $region1)); + $this->assertSame([], $found); + $found = array_map('strval', $finder->findRegionsByName($region1->getName(), false, $province1)); + $this->assertSame([], $found); + + $found = array_map('strval', $finder->findProvincesByName($province1->getName())); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findProvincesByName($province1->getName(), false, $geographicalSubdivision1)); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findProvincesByName($province1->getName(), false, $geographicalSubdivision2)); + $this->assertSame([], $found); + $found = array_map('strval', $finder->findProvincesByName($province1->getName(), false, $region1)); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findProvincesByName($province1->getName(), false, $region2)); + $this->assertSame([], $found); + $found = array_map('strval', $finder->findProvincesByName($province1->getName(), false, $province1)); + $this->assertSame([], $found); + + $found = array_map('strval', $finder->findMunicipalitiesByName($municipality1->getName())); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findMunicipalitiesByName($municipality1->getName(), false, $geographicalSubdivision1)); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findMunicipalitiesByName($municipality1->getName(), false, $geographicalSubdivision2)); + $this->assertSame([], $found); + $found = array_map('strval', $finder->findMunicipalitiesByName($municipality1->getName(), false, $region1)); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findMunicipalitiesByName($municipality1->getName(), false, $region2)); + $this->assertSame([], $found); + $found = array_map('strval', $finder->findMunicipalitiesByName($municipality1->getName(), false, $province1)); + $this->assertCount(1, $found); + $found = array_map('strval', $finder->findMunicipalitiesByName($municipality1->getName(), false, $province2)); + $this->assertSame([], $found); + } + private function getFinder(): Finder { return self::$finder ??= new Finder();