diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dbeac7e..bea1bba 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,16 +13,33 @@ on: jobs: + composer-normalize: + name: Composer normalization + runs-on: "ubuntu-latest" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.5' + coverage: none + tools: composer-normalize + env: + fail-fast: true + - name: Composer normalize + run: composer-normalize --dry-run + phpcs: name: Code style (phpcs) runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.4' + php-version: '8.5' coverage: none tools: cs2pr, phpcs env: @@ -35,11 +52,11 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.3' + php-version: '8.5' coverage: none tools: cs2pr, php-cs-fixer env: @@ -52,11 +69,11 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.4' + php-version: '8.5' coverage: none tools: composer:v2, phpstan env: @@ -75,15 +92,15 @@ jobs: - name: PHPStan run: phpstan analyse --no-progress --verbose - tests: + phpunit: name: Tests on PHP ${{ matrix.php-version }} runs-on: "ubuntu-latest" strategy: matrix: - php-version: ['8.1', '8.2', '8.3', '8.4'] + php-version: ['8.1', '8.2', '8.3', '8.4', '8.5'] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -111,7 +128,7 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup PHP uses: shivammathur/setup-php@v2 with: diff --git a/.github/workflows/sonarqube-cloud.yml b/.github/workflows/sonarqube-cloud.yml index 50e01b2..bc2e122 100644 --- a/.github/workflows/sonarqube-cloud.yml +++ b/.github/workflows/sonarqube-cloud.yml @@ -6,7 +6,7 @@ on: # Actions # shivammathur/setup-php@v2 https://github.com/marketplace/actions/setup-php-action -# SonarSource/sonarqube-scan-action@v6 https://github.com/marketplace/actions/official-sonarqube-scan +# SonarSource/sonarqube-scan-action@v7 https://github.com/marketplace/actions/official-sonarqube-scan jobs: @@ -21,13 +21,13 @@ jobs: exit 1 fi - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Unshallow clone to provide blame information run: git fetch --unshallow - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.4' + php-version: '8.5' coverage: xdebug tools: composer:v2 - name: Get composer cache directory @@ -48,6 +48,6 @@ jobs: sed 's#'$GITHUB_WORKSPACE'#/github/workspace#g' build/coverage/junit.xml > build/sonar-junit.xml sed 's#'$GITHUB_WORKSPACE'#/github/workspace#g' build/coverage/clover.xml > build/sonar-coverage.xml - name: SonarCloud Scan - uses: SonarSource/sonarqube-scan-action@v6 + uses: SonarSource/sonarqube-scan-action@v7 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.phive/phars.xml b/.phive/phars.xml index ce8b9cb..e1e017c 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,8 +1,9 @@ - - - - - + + + + + + diff --git a/LICENSE b/LICENSE index 5b8acbe..4278bd5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2019 - 2025 PhpCfdi https://www.phpcfdi.com/ +Copyright (c) 2019 - 2026 PhpCfdi https://www.phpcfdi.com/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/composer.json b/composer.json index 5c80385..d0ef9c5 100644 --- a/composer.json +++ b/composer.json @@ -1,25 +1,25 @@ { "name": "phpcfdi/xml-cancelacion", "description": "Genera documentos de cancelación de CFDI firmados (XMLSEC)", - "keywords": ["phpcfdi", "sat", "cfdi", "Cancelacion", "PeticionConsultaRelacionados", "SolicitudAceptacionRechazo"], - "homepage": "https://github.com/phpcfdi/xml-cancelacion", "license": "MIT", + "keywords": [ + "phpcfdi", + "sat", + "cfdi", + "Cancelacion", + "PeticionConsultaRelacionados", + "SolicitudAceptacionRechazo" + ], "authors": [ { "name": "Carlos C Soto", "email": "eclipxe13@gmail.com" } ], + "homepage": "https://github.com/phpcfdi/xml-cancelacion", "support": { - "source": "https://github.com/phpcfdi/xml-cancelacion", - "issues": "https://github.com/phpcfdi/xml-cancelacion/issues" - }, - "prefer-stable": true, - "config": { - "optimize-autoloader": true, - "preferred-install": { - "*": "dist" - } + "issues": "https://github.com/phpcfdi/xml-cancelacion/issues", + "source": "https://github.com/phpcfdi/xml-cancelacion" }, "require": { "php": "^8.1", @@ -29,12 +29,13 @@ "phpcfdi/credentials": "^1.1.1" }, "require-dev": { - "robrichards/xmlseclibs": "^3.1.0", - "phpunit/phpunit": "^10.5.46" + "phpunit/phpunit": "^10.5.46", + "robrichards/xmlseclibs": "^3.1.0" }, "suggest": { "robrichards/xmlseclibs": "Create document signatures (partially) using xmlseclibs" }, + "prefer-stable": true, "autoload": { "psr-4": { "PhpCfdi\\XmlCancelacion\\": "src/" @@ -45,13 +46,27 @@ "PhpCfdi\\XmlCancelacion\\Tests\\": "tests/" } }, + "config": { + "optimize-autoloader": true, + "preferred-install": { + "*": "dist" + } + }, "scripts": { - "dev:build": ["@dev:fix-style", "@dev:test"], + "dev:build": [ + "@dev:fix-style", + "@dev:test" + ], "dev:check-style": [ + "@php tools/composer-normalize normalize --dry-run", "@php tools/php-cs-fixer fix --dry-run --verbose", "@php tools/phpcs --colors -sp" ], + "dev:coverage": [ + "@php -dzend_extension=xdebug.so -dxdebug.mode=coverage vendor/bin/phpunit --coverage-html build/coverage/html/" + ], "dev:fix-style": [ + "@php tools/composer-normalize normalize", "@php tools/php-cs-fixer fix --verbose", "@php tools/phpcbf --colors -sp" ], @@ -60,16 +75,13 @@ "@php vendor/bin/phpunit --testdox --display-all-issues --stop-on-failure", "@php tools/phpstan analyse --no-progress", "@php tools/infection --no-progress --no-interaction --show-mutations" - ], - "dev:coverage": [ - "@php -dzend_extension=xdebug.so -dxdebug.mode=coverage vendor/bin/phpunit --coverage-html build/coverage/html/" ] }, "scripts-descriptions": { "dev:build": "DEV: run dev:fix-style and dev:tests, run before pull request", - "dev:check-style": "DEV: search for code style errors using php-cs-fixer and phpcs", - "dev:fix-style": "DEV: fix code style errors using php-cs-fixer and phpcbf", - "dev:test": "DEV: run dev:check-style, phpunit, phpstan and infection", - "dev:coverage": "DEV: run phpunit with xdebug and storage coverage in build/coverage/html/" + "dev:check-style": "DEV: search for code style errors using composer-normalize, php-cs-fixer and phpcs", + "dev:coverage": "DEV: run phpunit with xdebug and storage coverage in build/coverage/html/", + "dev:fix-style": "DEV: fix code style errors using composer-normalize, php-cs-fixer and phpcbf", + "dev:test": "DEV: run dev:check-style, phpunit, phpstan and infection" } } diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ace6edb..dc94a53 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,6 +9,24 @@ Usamos [Versionado Semántico 2.0.0](SEMVER.md) por lo que puedes usar esta libr Pueden aparecer cambios no liberados que se integran a la rama principal, pero no ameritan una nueva liberación de versión, aunque sí su incorporación en la rama principal de trabajo. Generalmente, se tratan de cambios en el desarrollo. +### Versión 2.0.6 2026-04-01 + +- Se corrige la revisión del proyecto dado que *PHPStan* asume que la función `preg_grep` siempre retorna + un arreglo sin tipo, cuando debería limitarse solamente a las opciones que recibe. +- En las pruebas, se silencia la llamada a `XMLSecEnc::staticLocateKeyInfo` dado que tiene un + problema de compatibilidad con PHP 8.5. +- Se normaliza el archivo `composer.json`. +- Se configura *PHPUnit* para que falle y muestre los detalles en todos los problemas encontrados. +- Se agrega la herramienta `composer-normalize` a las herramientas de desarrollo. +- Se actualizan los flujos de trabajo de GitHub: + - Se agrega el trabajo `composer-normalize`. + - Se renombra el trabajo `tests` a `phpunit`. + - Se agrega PHP 8.5 a la matriz de prebas en el trabajo `phpunit`. + - Los trabajos se ejecutan en PHP 8.5 excepto el trabajo `infection`. + - Se actualizan las versiones de las acciones de GitHub. +- Se actualiza `sonarqube-scan-action` a la versión 7. +- Se actualizan las herramientas de desarrollo. + ### Mantenimiento 2025-09-27 - Se corrige una prueba donde se estaba escribiendo el archivo esperado antes de su comparación. diff --git a/docs/TODO.md b/docs/TODO.md index 6e1e19d..f87c2cc 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -7,6 +7,10 @@ - Mejorar los casos de cobertura de código para hacer mandatorio `infection` en los pasos de construcción. +- La librería `robrichards/xmlseclibs` a la fecha 2026-04-01 no es compatible con PHP 8.5. + Se debe remover el operador de ignorar errores en el archivo `SignerImplementationTestCase` + al llamar a la función estática `XMLSecEnc::staticLocateKeyInfo()`. + ## Resueltas - Generar excepciones internas en lugar de excepciones genéricas de SPL. diff --git a/docs/XmlSecLibs.md b/docs/XmlSecLibs.md index c5f23d7..29a85bb 100644 --- a/docs/XmlSecLibs.md +++ b/docs/XmlSecLibs.md @@ -2,8 +2,8 @@ A partir de la versión `1.0.0` se incluye un objeto `XmlSecLibsSigner` que implementa `SignerInterface`. -Se puede utilizar [`robrichards/xmlseclibs`](https://github.com/robrichards/xmlseclibs) para hacer el firmado, -sin embargo al 2019-04-09 aún no se han implementado los mecanismos para incluir el elemento `KeyValue`, +Se puede utilizar [`robrichards/xmlseclibs`](https://github.com/robrichards/xmlseclibs) para hacer el firmado; +sin embargo, al 2026-04-01 aún no se han implementado los mecanismos para incluir el elemento `KeyValue`, a pesar de tener un [PR #75](https://github.com/robrichards/xmlseclibs/pull/75) desde 2015-09-03 y un [ISSUE #217](https://github.com/robrichards/xmlseclibs/issues/217). @@ -29,7 +29,7 @@ $cancellation = $xmlhelper->signCancellation('11111111-2222-3333-4444-0000000000 ## Instalación -Recuerda que `robrichards/xmlseclibs` no es una dependencia (es una recomendación) de `phpcfdi/xml-cancelacion` +Recuerda que `robrichards/xmlseclibs` no es una dependencia (es una recomendación) de `phpcfdi/xml-cancelacion`. ```shell script # instalar esta librería diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 3625253..e142713 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -3,6 +3,8 @@ xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" cacheDirectory="build/phpunit.cache" bootstrap="tests/bootstrap.php" + displayDetailsOnAllIssues="true" + failOnAllIssues="true" colors="true" > diff --git a/src/Signers/CreateKeyInfoElementTrait.php b/src/Signers/CreateKeyInfoElementTrait.php index 156f648..9b681f5 100644 --- a/src/Signers/CreateKeyInfoElementTrait.php +++ b/src/Signers/CreateKeyInfoElementTrait.php @@ -27,7 +27,9 @@ protected function createKeyInfoElement( ); $x509Data->appendChild($x509IssuerSerial); - $certificateContents = implode('', preg_grep('/^((?!-).)*$/', explode(PHP_EOL, $pemContents)) ?: []); + /** @phpstan-var string[] $certificateContentLines explode returns string[] grep_grep return string[]|false */ + $certificateContentLines = preg_grep('/^((?!-).)*$/', explode(PHP_EOL, $pemContents)) ?: []; + $certificateContents = implode('', $certificateContentLines); $x509Data->appendChild( $document->createElement('X509Certificate', htmlspecialchars($certificateContents, ENT_XML1)) ); diff --git a/tests/System/SignerImplementations/SignerImplementationTestCase.php b/tests/System/SignerImplementations/SignerImplementationTestCase.php index 454baf9..5c75eef 100644 --- a/tests/System/SignerImplementations/SignerImplementationTestCase.php +++ b/tests/System/SignerImplementations/SignerImplementationTestCase.php @@ -125,7 +125,9 @@ public function checkSignatureIsValidUsingXmlSecLib(string $signedXml): void } // must call, otherwise verify will not have the public key to check signature - $this->assertNotNull(XMLSecEnc::staticLocateKeyInfo($objKey, $signature), 'Cannot extract RSAKeyValue'); + // remove silence operator when robrichards/xmlseclibs is compatible with PHP 8.5 + $expectedRsaKeyValue = @XMLSecEnc::staticLocateKeyInfo($objKey, $signature); + $this->assertNotNull($expectedRsaKeyValue, 'Cannot extract RSAKeyValue'); $this->assertSame(1, $dSig->verify($objKey), 'Xml Signature verify fail'); }