From f77f697fdd0ba2e2eb4c1ed7fe1d72175c76f8d3 Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Mon, 6 Jul 2026 16:09:02 +0200 Subject: [PATCH 1/2] Implement VIN rule --- README.md | 12 +++++++ src/Rules/Vin.php | 73 +++++++++++++++++++++++++++++++++++++++++ tests/Rules/VinTest.php | 51 ++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 src/Rules/Vin.php create mode 100644 tests/Rules/VinTest.php diff --git a/README.md b/README.md index 402ae05..63f9010 100644 --- a/README.md +++ b/README.md @@ -327,6 +327,18 @@ minus chars are not allowed at the beginning or end. public Intervention\Validation\Rules\Username::__construct() +### VIN (Vehicle Identification Number) + +The field under validation must be a valid Vehicle identification number according to ISO-3779. + + public Intervention\Validation\Rules\Vin::__construct(bool $checkDigit = false) + +#### Parameters + +**checkDigit** + +Optional verification according to the North American check system. Default `false`. + ## Development & Testing With this package comes a Docker image to build a test suite container. To diff --git a/src/Rules/Vin.php b/src/Rules/Vin.php new file mode 100644 index 0000000..a5c2b97 --- /dev/null +++ b/src/Rules/Vin.php @@ -0,0 +1,73 @@ +checkDigit) { + return $this->validateCheckDigit((string) $value); + } + + return true; + } + + /** + * Validate the VIN check digit using the North American standard. + */ + private function validateCheckDigit(string $vin): bool + { + // weights for each position (position 8 has weight 0 as it's the check digit) + $weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2]; + + // transliteration values for letters + $transliteration = [ + 'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, 'G' => 7, 'H' => 8, + 'J' => 1, 'K' => 2, 'L' => 3, 'M' => 4, 'N' => 5, 'P' => 7, 'R' => 9, 'S' => 2, + 'T' => 3, 'U' => 4, 'V' => 5, 'W' => 6, 'X' => 7, 'Y' => 8, 'Z' => 9, + ]; + + $sum = 0; + foreach (str_split($vin) as $i => $char) { + $value = is_numeric($char) ? (int) $char : $transliteration[$char]; + $sum += $value * $weights[$i]; + } + + $checkDigit = $sum % 11; + $expectedCheckDigit = $checkDigit === 10 ? 'X' : (string) $checkDigit; + + return $vin[8] === $expectedCheckDigit; + } +} diff --git a/tests/Rules/VinTest.php b/tests/Rules/VinTest.php new file mode 100644 index 0000000..2e97e05 --- /dev/null +++ b/tests/Rules/VinTest.php @@ -0,0 +1,51 @@ +isValid($value); + $this->assertEquals($result, $valid); + } + + #[DataProvider('dataProviderCheckDigit')] + public function testValidationCheckDigit(bool $result, string $value): void + { + $valid = (new Vin(true))->isValid($value); + $this->assertEquals($result, $valid); + } + + public static function dataProvider(): Generator + { + yield [true, 'WP0ZZZ99ZTS392124']; + yield [true, '5GZCZ43D13S812715']; + yield [true, 'KLATF08Y1VB363636']; + yield [true, 'SGZCZ43D13S812715']; + yield [true, 'W0L000051T2123456']; + yield [true, 'WDD1690071J236589']; + yield [true, 'WVWZZZ1JZ3W386752']; + yield [false, 'WVWZZZ1OZ3W386752']; + } + + public static function dataProviderCheckDigit(): Generator + { + yield [true, '5GZCZ43D13S812715']; + yield [false, 'WP0ZZZ99ZTS392124']; + yield [false, 'KLATF08Y1VB363636']; + yield [false, 'SGZCZ43D13S812715']; + yield [false, 'W0L000051T2123456']; + yield [false, 'WDD1690071J236589']; + yield [false, 'WVWZZZ1JZ3W386752']; + yield [false, 'WVWZZZ1OZ3W386752']; + } +} From e5c44399eb976258a930748aeda42856d01305db Mon Sep 17 00:00:00 2001 From: Oliver Vogel Date: Mon, 6 Jul 2026 17:07:16 +0200 Subject: [PATCH 2/2] Rename phpunit.dist.xml --- phpunit.dist.xml | 27 +++++++++++++++++++++++++++ phpunit.xml.dist | 13 ------------- 2 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 phpunit.dist.xml delete mode 100644 phpunit.xml.dist diff --git a/phpunit.dist.xml b/phpunit.dist.xml new file mode 100644 index 0000000..cfa3bc7 --- /dev/null +++ b/phpunit.dist.xml @@ -0,0 +1,27 @@ + + + + + ./tests/ + + + + + ./src/Intervention/Validation/Validator.php + + + diff --git a/phpunit.xml.dist b/phpunit.xml.dist deleted file mode 100644 index a3730b2..0000000 --- a/phpunit.xml.dist +++ /dev/null @@ -1,13 +0,0 @@ - - - - - ./tests/ - - - - - ./src/Intervention/Validation/Validator.php - - -