Skip to content

Commit

Permalink
ADD: methods getCitiesInProvince and getCountiesInCity
Browse files Browse the repository at this point in the history
  • Loading branch information
hyperjiang committed Aug 7, 2019
1 parent 08ab393 commit f36e14f
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 3 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ $res = $divisionCode->get('110000'); // 北京市
// Get all the provinces
$provinces = $divisionCode->getAllProvinces();
print_r($provinces);
// Get all the cities in the specified province
$province = '110000';
$cities = $divisionCode->getCitiesInProvince($province);
print_r($cities);
// Get all the counties in the specified city
$city = '445200';
$counties = $divisionCode->getCountiesInCity($city);
print_r($counties);
```

## Upgrade
Expand Down
78 changes: 77 additions & 1 deletion src/DivisionCode/DivisionCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ class DivisionCode
*/
public static $codes = [];

/**
* Municipalities in China includes Beijing, Tianjin, Shanghai, Chongqing
*/
const MUNICIPALITIES = ['110000', '120000', '310000', '500000'];

protected $disableSQLite = false;

protected $db;
Expand Down Expand Up @@ -231,7 +236,7 @@ public function getSlice($offset = 0, $limit = 1): array
}

/**
* Get all the provinces
* Get all the provinces including municipalities and autonomous regions
*
* @param bool $includeGAT include Hong Kong, Macao and Taiwan? exclude them by default
* @return array
Expand Down Expand Up @@ -260,4 +265,75 @@ public function getAllProvinces($includeGAT = false): array
return substr($k, 2) == '0000';
}, ARRAY_FILTER_USE_KEY);
}

/**
* Get all the cities in the specified province
* Municipalities do not have cities so will return the counties(districts) instead
*
* @param string $province
* @return array
*/
public function getCitiesInProvince($province): array
{
// check if it is really a province, return empty array if it is not
if (substr($province, 2) != '0000') {
return [];
}

$prefix = substr($province, 0, 2);

if ($this->supportSQLite()) {
if (in_array($province, self::MUNICIPALITIES)) {
$sql = "SELECT code, name FROM division_codes WHERE code LIKE '$prefix%' AND code != '$province'";
} else {
$sql = "SELECT code, name FROM division_codes WHERE code LIKE '$prefix%00' AND code != '$province'";
}
$res = $this->db->query($sql);
$arr = [];
while ($row = $res->fetchArray()) {
$arr[$row['code']] = $row['name'];
}

return $arr;
}

return array_filter(self::$codes, function ($k) use ($province, $prefix) {
if (in_array($province, self::MUNICIPALITIES)) {
return substr($k, 0, 2) == $prefix && $k != $province;
}

return substr($k, 0, 2) == $prefix && $k != $province && substr($k, 4) == '00';
}, ARRAY_FILTER_USE_KEY);
}

/**
* Get all the counties in the specified city
*
* @param string $city
* @return array
*/
public function getCountiesInCity($city): array
{
// check if it is really a city, return empty array if it is not
if (substr($city, 4) != '00') {
return [];
}

$prefix = substr($city, 0, 4);

if ($this->supportSQLite()) {
$sql = "SELECT code, name FROM division_codes WHERE code LIKE '$prefix%' AND code != '$city'";
$res = $this->db->query($sql);
$arr = [];
while ($row = $res->fetchArray()) {
$arr[$row['code']] = $row['name'];
}

return $arr;
}

return array_filter(self::$codes, function ($k) use ($city, $prefix) {
return substr($k, 0, 4) == $prefix && $k != $city;
}, ARRAY_FILTER_USE_KEY);
}
}
Binary file modified src/DivisionCode/codes.db
Binary file not shown.
58 changes: 56 additions & 2 deletions tests/DivisionCodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public function getSliceProvider(): array
}

/**
* @dataProvider ggetAllProvincesProvider
* @dataProvider getAllProvincesProvider
*/
public function testGetAllProvinces($useSQLite, $includeGAT, $expected): void
{
Expand All @@ -127,7 +127,7 @@ public function testGetAllProvinces($useSQLite, $includeGAT, $expected): void
$this->assertEquals($expected, count($provinces));
}

public function ggetAllProvincesProvider(): array
public function getAllProvincesProvider(): array
{
return [
[true, false, 31],
Expand All @@ -136,4 +136,58 @@ public function ggetAllProvincesProvider(): array
[false, true, 34],
];
}

/**
* @dataProvider getCitiesInProvinceProvider
*/
public function testGetCitiesInProvince($useSQLite, $province, $expected): void
{
$this->divisionCode->useSQLite($useSQLite);
$cities = $this->divisionCode->getCitiesInProvince($province);
$this->assertEquals($expected, count($cities));
}

public function getCitiesInProvinceProvider(): array
{
return [
[true, '110000', 16],
[true, '710000', 0],
[true, '630000', 8],
[true, '150000', 12],
[true, '440000', 21],
[true, '445200', 0], // not a province
[false, '110000', 16],
[false, '710000', 0],
[false, '630000', 8],
[false, '150000', 12],
[false, '440000', 21],
[false, '445200', 0], // not a province
];
}

/**
* @dataProvider getCountiesInCityProvider
*/
public function testGetCountiesInCity($useSQLite, $city, $expected): void
{
$this->divisionCode->useSQLite($useSQLite);
$counties = $this->divisionCode->getCountiesInCity($city);
$this->assertEquals($expected, count($counties));
}

public function getCountiesInCityProvider(): array
{
return [
[true, '110000', 0],
[true, '445200', 5],
[true, '150100', 9],
[true, '630100', 7],
[true, '110101', 0], // not a city
[false, '110000', 0],
[false, '445200', 5],
[false, '150100', 9],
[false, '630100', 7],
[false, '110101', 0], // not a city
];
}
}

0 comments on commit f36e14f

Please sign in to comment.