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');
}