summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Zhineng <[email protected]>2025-05-14 13:15:03 +0800
committerLi Zhineng <[email protected]>2025-05-14 13:15:03 +0800
commitc09fdd361c8ca9fe75aaba744c85c82f21b9ac68 (patch)
treea74305e392cb84b64b3bba2d4673978ea839ce9e
parentb22f622c8e8d41aa477a075c0b22804a7f27092a (diff)
downloadvehicle-license-china-c09fdd361c8ca9fe75aaba744c85c82f21b9ac68.tar.gz
vehicle-license-china-c09fdd361c8ca9fe75aaba744c85c82f21b9ac68.zip
vehicle type checks
-rw-r--r--src/RegistrationNumber.php123
-rw-r--r--tests/RegistrationNumberTest.php58
2 files changed, 173 insertions, 8 deletions
diff --git a/src/RegistrationNumber.php b/src/RegistrationNumber.php
index 346a1c9..abc1364 100644
--- a/src/RegistrationNumber.php
+++ b/src/RegistrationNumber.php
@@ -144,15 +144,24 @@ final readonly class RegistrationNumber
/**
* @var string[]
*/
- private const array SPECIAL_SUFFIXS = [
- '领', '使', '警', '学', '挂', '港', '澳', '试', '超',
+ private const array AVAILLABLE_SUFFIXS = [
+ self::EMBASSY_SUFFIX,
+ self::CONSULATE_SUFFIX,
+ self::POLICE_SUFFIX,
+ self::COACH_SUFFIX,
+ self::TRAILER_SUFFIX,
+ self::HONG_KONG_SUFFIX,
+ self::MACAU_SUFFIX,
+ self::TEST_SUFFIX,
+ self::SPECIAL_SUFFIX,
];
/**
* @var string[]
*/
private const array GUANGDONG_Z_SPECIAL_SUFFIXS = [
- '港', '澳',
+ self::HONG_KONG_SUFFIX,
+ self::MACAU_SUFFIX,
];
private const string GUANGDONG_PROVINCE = '粤';
@@ -163,12 +172,30 @@ final readonly class RegistrationNumber
private const string CONSULATE_SUFFIX = '领';
+ private const string POLICE_SUFFIX = '警';
+
+ private const string COACH_SUFFIX = '学';
+
+ private const string TRAILER_SUFFIX = '挂';
+
+ private const string HONG_KONG_SUFFIX = '港';
+
+ private const string MACAU_SUFFIX = '澳';
+
+ private const string TEST_SUFFIX = '试';
+
+ private const string SPECIAL_SUFFIX = '超';
+
public string $region;
+ public string $agencyNumber;
+
public string $authority;
public string $sequence;
+ public string $suffix;
+
private function __construct(
public string $registrationNumber
) {
@@ -311,7 +338,7 @@ final readonly class RegistrationNumber
$last = mb_substr($registrationNumber, -1);
- $suffix = in_array($last, self::SPECIAL_SUFFIXS, strict: true)
+ $suffix = in_array($last, self::AVAILLABLE_SUFFIXS, strict: true)
? $last
: '';
@@ -361,7 +388,7 @@ final readonly class RegistrationNumber
&& $authority === self::GUANGDONG_SPECIAL_AUTHORITY;
}
- if ($suffix !== '' && ! in_array($suffix, self::SPECIAL_SUFFIXS, strict: true)) {
+ if ($suffix !== '' && ! in_array($suffix, self::AVAILLABLE_SUFFIXS, strict: true)) {
$len = mb_strlen($sequence);
return $len >= 4 && $len <= 5;
@@ -505,9 +532,89 @@ final readonly class RegistrationNumber
private function parse(string $registrationNumber): void
{
- $this->region = mb_substr($registrationNumber, 0, 1);
- $this->authority = mb_substr($registrationNumber, 1, 1);
- $this->sequence = mb_substr($registrationNumber, 2);
+ $registrationNumber = mb_strtoupper($registrationNumber);
+
+ $last = mb_substr($registrationNumber, -1);
+
+ match ($last) {
+ self::EMBASSY_SUFFIX => $this->parseEmbassyRegistrationNumber($registrationNumber),
+ self::CONSULATE_SUFFIX => $this->parseConsulateRegistrationNumber($registrationNumber),
+ default => $this->parseRegistrationNumber($registrationNumber),
+ };
+ }
+
+ private function parseEmbassyRegistrationNumber(string $registrationNumber): void
+ {
+ [$agency, $sequence, $suffix] = static::extractEmbassyComponents($registrationNumber);
+
+ $this->agencyNumber = $agency;
+ $this->sequence = $sequence;
+ $this->suffix = $suffix;
+ }
+
+ private function parseConsulateRegistrationNumber(string $registrationNumber): void
+ {
+ [$region, $agency, $sequence, $suffix] = static::extractConsulateComponents($registrationNumber);
+
+ $this->region = $region;
+ $this->agencyNumber = $agency;
+ $this->sequence = $sequence;
+ $this->suffix = $suffix;
+ }
+
+ private function parseRegistrationNumber(string $registrationNumber): void
+ {
+ [$region, $authority, $sequence, $suffix] = static::extractComponents($registrationNumber);
+
+ $this->region = $region;
+ $this->authority = $authority;
+ $this->sequence = $sequence;
+ $this->suffix = $suffix;
+ }
+
+ public function isEmbassy(): bool
+ {
+ return $this->suffix === self::EMBASSY_SUFFIX;
+ }
+
+ public function isConsulate(): bool
+ {
+ return $this->suffix === self::CONSULATE_SUFFIX;
+ }
+
+ public function isPolice(): bool
+ {
+ return $this->suffix === self::POLICE_SUFFIX;
+ }
+
+ public function isCoach(): bool
+ {
+ return $this->suffix === self::COACH_SUFFIX;
+ }
+
+ public function isTrailer(): bool
+ {
+ return $this->suffix === self::TRAILER_SUFFIX;
+ }
+
+ public function isFromHongKong(): bool
+ {
+ return $this->suffix === self::HONG_KONG_SUFFIX;
+ }
+
+ public function isFromMacau(): bool
+ {
+ return $this->suffix === self::MACAU_SUFFIX;
+ }
+
+ public function isTest(): bool
+ {
+ return $this->suffix === self::TEST_SUFFIX;
+ }
+
+ public function isSpecial(): bool
+ {
+ return $this->suffix === self::SPECIAL_SUFFIX;
}
public function isCleanEnergy(): bool
diff --git a/tests/RegistrationNumberTest.php b/tests/RegistrationNumberTest.php
index b014072..9a599b6 100644
--- a/tests/RegistrationNumberTest.php
+++ b/tests/RegistrationNumberTest.php
@@ -38,6 +38,64 @@ final class RegistrationNumberTest extends TestCase
RegistrationNumber::make($registrationNumber);
}
+ public function test_is_embassy_deteremins_if_registration_number_is_used_by_embassies(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('224578使')->isEmbassy());
+ $this->assertFalse(RegistrationNumber::make('沪22478领')->isEmbassy());
+ }
+
+ public function test_is_consulate_determines_if_registration_number_is_used_by_consulates(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('沪22478领')->isConsulate());
+ $this->assertFalse(RegistrationNumber::make('224578使')->isConsulate());
+ }
+
+ public function test_is_police_determines_if_registration_number_is_used_by_police_officers(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('京A0006警')->isPolice());
+ $this->assertFalse(RegistrationNumber::make('粤E12345学')->isPolice());
+ }
+
+ public function test_is_coach_determines_if_registration_number_is_used_by_coaches(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('粤E12345学')->isCoach());
+ $this->assertFalse(RegistrationNumber::make('粤E12345挂')->isCoach());
+ }
+
+ public function test_is_trailer_determines_if_registration_number_is_used_by_trailers(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('粤E12345挂')->isTrailer());
+ $this->assertFalse(RegistrationNumber::make('粤E12345学')->isTrailer());
+ }
+
+ public function test_is_from_hong_kong_determines_if_registration_number_is_used_by_hong_kong_drivers(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('粤Z1234港')->isFromHongKong());
+ $this->assertTrue(RegistrationNumber::make('粤Z12345港')->isFromHongKong());
+ $this->assertFalse(RegistrationNumber::make('粤Z1234澳')->isFromHongKong());
+ $this->assertFalse(RegistrationNumber::make('粤Z12345澳')->isFromHongKong());
+ }
+
+ public function test_is_from_macau_determines_if_registration_number_is_used_by_macau_drivers(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('粤Z1234澳')->isFromMacau());
+ $this->assertTrue(RegistrationNumber::make('粤Z12345澳')->isFromMacau());
+ $this->assertFalse(RegistrationNumber::make('粤Z1234港')->isFromMacau());
+ $this->assertFalse(RegistrationNumber::make('粤Z12345港')->isFromMacau());
+ }
+
+ public function test_is_test_determines_if_registration_number_is_used_by_test_vehicles(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('粤E12345试')->isTest());
+ $this->assertFalse(RegistrationNumber::make('粤E12345学')->isTest());
+ }
+
+ public function test_is_special_determines_if_registration_number_is_used_by_special_vehicles(): void
+ {
+ $this->assertTrue(RegistrationNumber::make('粤E12345超')->isSpecial());
+ $this->assertFalse(RegistrationNumber::make('粤E12345学')->isSpecial());
+ }
+
public function test_is_clean_energy_determines_if_vehicle_is_clean_energy(): void
{
$this->assertTrue(RegistrationNumber::make('粤ED12345')->isCleanEnergy());