v2.0.0 — PHP 8.2, check-digit validation, typed API, and new formats#17
Merged
Conversation
- Bump php floor ^8.0 -> ^8.2; drop unused spatie/ray - Upgrade pestphp/pest ^1 -> ^3, php-cs-fixer -> ^3.64, allow pest plugin - Migrate phpunit.xml.dist to the PHPUnit 11 schema - Test CI matrix on PHP 8.2/8.3/8.4/8.5; bump actions/checkout to v4 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Bump php floor ^8.0 -> ^8.2; drop unused spatie/ray - Upgrade pestphp/pest ^1 -> ^3, php-cs-fixer -> ^3.64, allow pest plugin - Migrate phpunit.xml.dist to the PHPUnit 11 schema - Test CI matrix on PHP 8.2/8.3/8.4/8.5; bump actions/checkout to v4
- Convert DocumentType from abstract-class constants to a backed enum - Add declare(strict_types=1), typed properties, and explicit return types - Replace the adapter switch with a match keyed on the enum - Add MrzNormalizer (CRLF/whitespace handling) used before validation Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Convert DocumentType from abstract-class constants to a backed enum - Add declare(strict_types=1), typed properties, and explicit return types - Replace the adapter switch with a match keyed on the enum - Add MrzNormalizer (CRLF/whitespace handling) used before validation
- DateFormatter: strict validation (reject Feb 30 etc.) and shift a future date of birth back a century; guard against false from createFromFormat - GenderMapper/CountryMapper: fix PHP 8.4 implicit-nullable params (?string) - CountryMapper: cache the merged lookup table; add mapCountryCode() - Add NameFormatter trait with consistent trailing-filler trimming Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- DateFormatter: strict validation (reject Feb 30 etc.) and shift a future date of birth back a century; guard against false from createFromFormat - GenderMapper/CountryMapper: fix PHP 8.4 implicit-nullable params (?string) - CountryMapper: cache the merged lookup table; add mapCountryCode() - Add NameFormatter trait with consistent trailing-filler trimming
- Add Support/CheckDigit (7-3-1 weighted modulo-10 scheme) - Every parser now returns a 'valid' flag and per-field 'validation' map (card_no, date_of_birth, date_of_expiry, personal_number, composite) - Add issuer_code, nationality_code, sex, optional_data and raw keys - Modernize parsers: typed props, NameFormatter, rtrim, normalized input Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Add Support/CheckDigit (7-3-1 weighted modulo-10 scheme) - Every parser now returns a 'valid' flag and per-field 'validation' map (card_no, date_of_birth, date_of_expiry, personal_number, composite) - Add issuer_code, nationality_code, sex, optional_data and raw keys - Modernize parsers: typed props, NameFormatter, rtrim, normalized input
- Replace the placeholder ExampleTest with real coverage (~99%) - Happy paths per document type, invalid-input and boundary datasets - CRLF regression, check-digit mutation, getType() branches - DateFormatter, gender/country mappers and name edge cases Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Replace the placeholder ExampleTest with real coverage (~99%) - Happy paths per document type, invalid-input and boundary datasets - CRLF regression, check-digit mutation, getType() branches - DateFormatter, gender/country mappers and name edge cases
- README: PHP 8.2 requirement, new output block, check-digit and input-handling notes - CHANGELOG: v2.0.0 entry (breaking changes, features, fixes) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README: PHP 8.2 requirement, new output block, check-digit and input-handling notes - CHANGELOG: v2.0.0 entry (breaking changes, features, fixes)
- MrzResult value object via read()/tryRead(): typed props, date accessors, isExpired(), fullName(), toArray() - tryParse()/tryRead() return null instead of throwing on invalid input - strict flag on parse()/read() throws InvalidChecksumException on bad digits Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- MrzResult value object via read()/tryRead(): typed props, date accessors, isExpired(), fullName(), toArray() - tryParse()/tryRead() return null instead of throwing on invalid input - strict flag on parse()/read() throws InvalidChecksumException on bad digits
- Support\Transliterator: fromLatin() (ICAO digraph/diacritic folding) and matches() to compare a visual-zone name against an MRZ name - Visa optional_data now sliced by line length (16 on MRV-A, 8 on MRV-B) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Support\Transliterator: fromLatin() (ICAO digraph/diacritic folding) and matches() to compare a visual-zone name against an MRZ name - Visa optional_data now sliced by line length (16 on MRV-A, 8 on MRV-B)
- New FrenchIdMrzParser with the bespoke CNI layout (no expiry encoded) - Detected by the 'IDFRA' prefix ahead of TD2; composite check digit uses the continuous cross-line 7-3-1 weighting specific to this format - Add DocumentType::FRENCH_ID Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- New FrenchIdMrzParser with the bespoke CNI layout (no expiry encoded) - Detected by the 'IDFRA' prefix ahead of TD2; composite check digit uses the continuous cross-line 7-3-1 weighting specific to this format - Add DocumentType::FRENCH_ID
- Auto-discovered MrzParserServiceProvider (binds MrzParser) - ValidMrz validation rule (optional strict check-digit mode) - Declare illuminate/support (dev + suggest) and laravel provider discovery Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Auto-discovered MrzParserServiceProvider (binds MrzParser) - ValidMrz validation rule (optional strict check-digit mode) - Declare illuminate/support (dev + suggest) and laravel provider discovery
… rule - MrzResult, tryParse/tryRead, strict mode - Transliterator fromLatin/matches - French national ID (verified GioviQ specimen) + tamper regression - Visa optional-data lengths; ValidMrz rule - Suite now 99 tests / ~99% coverage Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… rule - MrzResult, tryParse/tryRead, strict mode - Transliterator fromLatin/matches - French national ID (verified GioviQ specimen) + tamper regression - Visa optional-data lengths; ValidMrz rule - Suite now 99 tests / ~99% coverage
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… into hotfix/upgrade
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Modernizes the package to PHP 8.2, fixes several correctness/robustness bugs, adds a real test suite (there was none), and introduces MRZ check-digit validation plus a typed API. This is a breaking release (PHP floor raised, new output keys), so it targets v2.0.0.
▎ ℹ️ MrzParser::parse() keeps returning the same associative array — all changes to it are additive keys. No existing key was renamed or removed.
Why
Breaking changes
Highlights
Check-digit validation
Implements the ICAO 9303 7‑3‑1 weighted checksum (Support\CheckDigit). Every result now carries an overall valid flag and a per-field validation map (document number, date of birth, date of expiry, personal number, and composite). Verified against the ICAO 9303 specimens.
Typed API & ergonomics
New formats & helpers
Robustness fixes
Modernization
declare(strict_types=1) throughout, typed properties, match-based adapter selection, cached country lookup table.
Laravel
Auto-discovered MrzParserServiceProvider and a ValidMrz validation rule (with optional strict mode). Requires illuminate/support (declared as a suggest + dev dependency).
Tooling & CI
Testing
Notes for reviewers