Skip to content

Commit

Permalink
Allow restricting searching by names to specific territories
Browse files Browse the repository at this point in the history
  • Loading branch information
mlocati committed Jul 2, 2024
1 parent 1b52bd7 commit 67e104f
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 20 deletions.
55 changes: 42 additions & 13 deletions src/Finder.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}

/**
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down
85 changes: 78 additions & 7 deletions test/tests/Finder/FindByNameTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)"]],
];
}

Expand All @@ -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();
Expand Down

0 comments on commit 67e104f

Please sign in to comment.