diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 1b2d09a..6b682c4 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -1,42 +1,49 @@ name: PHP Composer -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] +on: [push, pull_request] jobs: build: name: ViesBuild runs-on: ${{ matrix.operating-system }} + # Let the experimental (next-PHP) leg fail without failing the workflow. + # Legs without an "experimental" value resolve to false and stay blocking. + continue-on-error: ${{ matrix.experimental || false }} strategy: + fail-fast: false matrix: operating-system: [ubuntu-latest] - php-versions: ['7.4', '8.0', '8.1'] + php: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5'] + include: + # Forward-looking, non-blocking signal against the next PHP. + # This plugin exists to smooth installs on newer PHP, so an + # early-warning leg against the upcoming release fits its purpose. + - operating-system: ubuntu-latest + php: '8.6' + experimental: true steps: - - name: Set default PHP version ${{ matrix.php-versions }} + - name: Set default PHP version ${{ matrix.php }} uses: shivammathur/setup-php@v2 with: - php-version: "${{ matrix.php-versions }}" + php-version: "${{ matrix.php }}" - name: Display current PHP version run: php --version - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - name: Validate composer.json and composer.lock run: composer validate - name: Cache Composer packages id: composer-cache - uses: actions/cache@v2 + uses: actions/cache@v5 with: path: vendor - key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-php-${{ matrix.php }}-${{ hashFiles('**/composer.json') }} restore-keys: | - ${{ runner.os }}-php- + ${{ runner.os }}-php-${{ matrix.php }}- - name: Install dependencies if: steps.composer-cache.outputs.cache-hit != 'true' diff --git a/src/Vies/Validator/ValidatorIE.php b/src/Vies/Validator/ValidatorIE.php index 10eb54c..b1bec55 100644 --- a/src/Vies/Validator/ValidatorIE.php +++ b/src/Vies/Validator/ValidatorIE.php @@ -76,7 +76,9 @@ private function validateIENew(string $vatNumber): bool $checkChar = 'A'; for ($i = $checkVal - 1; $i > 0; $i--) { - $checkChar++; + // chr(ord(...) + 1) replaces $checkChar++ to avoid incrementing a + // non-numeric string, deprecated since PHP 8.3 (valid on PHP 7.3+). + $checkChar = chr(ord($checkChar) + 1); } return $checkChar == $checksum; diff --git a/src/Vies/Validator/ValidatorSK.php b/src/Vies/Validator/ValidatorSK.php index da923dc..e490b44 100644 --- a/src/Vies/Validator/ValidatorSK.php +++ b/src/Vies/Validator/ValidatorSK.php @@ -35,6 +35,7 @@ class ValidatorSK extends ValidatorAbstract public function validate(string $vatNumber): bool { if (strlen($vatNumber) != 10 + || ! ctype_digit($vatNumber) || intval($vatNumber[0]) == 0 || ! in_array((int) $vatNumber[2], [2, 3, 4, 7, 8, 9]) ) { diff --git a/tests/Vies/Validator/ValidatorSKTest.php b/tests/Vies/Validator/ValidatorSKTest.php index 26576e6..22c1b60 100644 --- a/tests/Vies/Validator/ValidatorSKTest.php +++ b/tests/Vies/Validator/ValidatorSKTest.php @@ -4,6 +4,8 @@ namespace DragonBe\Test\Vies\Validator; +use DragonBe\Vies\Validator\ValidatorSK; + class ValidatorSKTest extends AbstractValidatorTest { /** @@ -25,4 +27,25 @@ public function vatNumberProvider() ['4060000007', false], ]; } + + /** + * @covers \DragonBe\Vies\Validator\ValidatorSK + */ + public function testValidateRaisesNoWarningOnNonNumericInput() + { + $raised = null; + set_error_handler(static function (int $errno, string $errstr) use (&$raised): bool { + $raised = $errstr; + return true; + }, E_DEPRECATED | E_WARNING); + + try { + $result = (new ValidatorSK())->validate('222222222A'); + } finally { + restore_error_handler(); + } + + self::assertFalse($result, 'Non-numeric SK input must be invalid'); + self::assertNull($raised, 'Validator must not trigger E_WARNING or E_DEPRECATED'); + } } diff --git a/tests/Vies/ViesTest.php b/tests/Vies/ViesTest.php index 47f2fd1..cfd3ac0 100644 --- a/tests/Vies/ViesTest.php +++ b/tests/Vies/ViesTest.php @@ -389,7 +389,9 @@ public function testCanAddOptionalArgumentsWithValue() { $viesRef = new \ReflectionClass(Vies::class); $addOptionalArguments = $viesRef->getMethod('addOptionalArguments'); - $addOptionalArguments->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $addOptionalArguments->setAccessible(true); + } $array = []; $object = new Vies(); @@ -409,7 +411,9 @@ public function testCanNotAddOptionalArgumentsWithoutValue() { $viesRef = new \ReflectionClass(Vies::class); $addOptionalArguments = $viesRef->getMethod('addOptionalArguments'); - $addOptionalArguments->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $addOptionalArguments->setAccessible(true); + } $array = []; $object = new Vies(); @@ -484,7 +488,9 @@ public function testRejectBadOptionalInformation( ) { $viesRef = new \ReflectionClass(Vies::class); $addOptionalArguments = $viesRef->getMethod('addOptionalArguments'); - $addOptionalArguments->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $addOptionalArguments->setAccessible(true); + } $array = []; $object = new Vies(); @@ -538,7 +544,9 @@ public function testAllowValidOptionalInformation( ) { $viesRef = new \ReflectionClass(Vies::class); $addOptionalArguments = $viesRef->getMethod('addOptionalArguments'); - $addOptionalArguments->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $addOptionalArguments->setAccessible(true); + } $array = []; $object = new Vies(); @@ -561,7 +569,9 @@ public function testBreakValidationOfOptionalArguments() { $viesRef = new \ReflectionClass(Vies::class); $addOptionalArguments = $viesRef->getMethod('addOptionalArguments'); - $addOptionalArguments->setAccessible(true); + if (\PHP_VERSION_ID < 80100) { + $addOptionalArguments->setAccessible(true); + } $this->expectException(\TypeError::class); $array = [];