From f5db5f6e3b662ce3c48a60e794f591d36f1e043c Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Sat, 17 Jun 2023 12:30:18 -0600 Subject: [PATCH 01/34] Test Persona::getRegimenes() --- docs/CHANGELOG.md | 6 ++++++ tests/Unit/Persona/Traits/PersonaTrait.php | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index cc2279f..5db4783 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,6 +9,12 @@ 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. +### Mantenimiento 2023-06-17 + +Sí, el mismo día de un *release*. + +- Se agrega un último test para alcanzar el 100% de cobertura de código. + ## Listado de cambios ### Versión 0.1.7 2024-01-10 diff --git a/tests/Unit/Persona/Traits/PersonaTrait.php b/tests/Unit/Persona/Traits/PersonaTrait.php index 845a710..1e31cff 100644 --- a/tests/Unit/Persona/Traits/PersonaTrait.php +++ b/tests/Unit/Persona/Traits/PersonaTrait.php @@ -41,4 +41,20 @@ public function test_assign_dynamic_property(): void $this->person->{'dynamic'} = 'dynamic'; $this->assertSame('dynamic', $this->person->{'dynamic'}); } + + public function test_allows_more_than_one_regimen(): void + { + $first = new Regimen(); + $first->setRegimen('Simplificado de confianza'); + $second = new Regimen(); + $second->setRegimen('Demás ingresos'); + + $person = $this->person; + $person->addRegimenes($first, $second); + + $this->assertSame( + [$first, $second], + $person->getRegimenes()->getRegimenes(), + ); + } } From f56ec1310e3b863b8851b5e9297db9a9a3e45a5c Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Sat, 17 Jun 2023 12:30:32 -0600 Subject: [PATCH 02/34] Fix release notes on 0.1.6 --- docs/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5db4783..2fed717 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -14,6 +14,7 @@ versión, aunque sí su incorporación en la rama principal de trabajo, generalm Sí, el mismo día de un *release*. - Se agrega un último test para alcanzar el 100% de cobertura de código. +- Se corrige en este archivo, que "los flujos de trabajo corren en PHP 8.2", decía "PHP 8.0". ## Listado de cambios @@ -35,7 +36,7 @@ Sí, el mismo día de un *release*. - Se actualiza el archivo de configuración de SonarCloud para excluir correctamente los archivos en `tests/_files`. - Para los flujos de trabajo: - Se permite ejecutarlos a petición. - - Los trabajos se ejecutan en PHP 8.0. + - Los trabajos se ejecutan en PHP 8.2. - No se instala `composer` cuando no es necesario. - Se sustituye la directiva `::set-output` con `$GITHUB_OUTPUT`. - Se actualizan las herramientas de desarrollo. From 462b03ae8c163e8a35b80aa171a766bfe33fa797 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:07:36 -0600 Subject: [PATCH 03/34] Run GitHub action on version 4 --- .github/workflows/build.yml | 12 ++++++------ .github/workflows/sonarcloud.yml | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9c7d028..c201893 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -35,7 +35,7 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -52,7 +52,7 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -66,7 +66,7 @@ jobs: shell: bash run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} @@ -85,7 +85,7 @@ jobs: php-versions: ['8.0', '8.1', '8.2'] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP on Linux if: matrix.operating-systems == 'ubuntu-latest' uses: shivammathur/setup-php@v2 @@ -114,7 +114,7 @@ jobs: shell: bash run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 574ad48..b9d0819 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -15,7 +15,7 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -32,7 +32,7 @@ jobs: id: composer-cache run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} @@ -42,7 +42,7 @@ jobs: - name: Create code coverage run: vendor/bin/phpunit --testdox --verbose --coverage-xml=build/coverage --coverage-clover=build/coverage/clover.xml --log-junit=build/coverage/junit.xml - name: Store code coverage - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: code-coverage path: build/coverage @@ -77,7 +77,7 @@ jobs: runs-on: "ubuntu-latest" steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Unshallow clone to provide blame information run: git fetch --unshallow - name: Setup PHP @@ -90,7 +90,7 @@ jobs: id: composer-cache run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - name: Cache dependencies - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} @@ -98,7 +98,7 @@ jobs: - name: Install project dependencies run: composer upgrade --no-interaction --no-progress --prefer-dist - name: Obtain code coverage - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: code-coverage path: build/coverage From 1ebf8176437dc7fc284511e591a4c5c060afbfa9 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:07:47 -0600 Subject: [PATCH 04/34] Remove deprecated rule --- phpcs.xml.dist | 1 - 1 file changed, 1 deletion(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 422820a..4316cec 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -18,7 +18,6 @@ - From 9ded7185e83c2453207cd8bef561cdfc94038787 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:08:53 -0600 Subject: [PATCH 05/34] Use php-version variable (singular) --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c201893..77e797e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,12 +77,12 @@ jobs: run: phpstan analyse --no-progress --verbose tests: - name: PHP ${{ matrix.php-versions }} on ${{ matrix.operating-systems }} + name: PHP ${{ matrix.php-version }} on ${{ matrix.operating-systems }} runs-on: ${{ matrix.operating-systems }} strategy: matrix: operating-systems: ["windows-latest", "ubuntu-latest"] - php-versions: ['8.0', '8.1', '8.2'] + php-version: ['8.0', '8.1', '8.2'] steps: - name: Checkout uses: actions/checkout@v4 @@ -90,7 +90,7 @@ jobs: if: matrix.operating-systems == 'ubuntu-latest' uses: shivammathur/setup-php@v2 with: - php-version: ${{ matrix.php-versions }} + php-version: ${{ matrix.php-version }} coverage: none tools: composer:v2 env: @@ -99,7 +99,7 @@ jobs: if: matrix.operating-systems == 'windows-latest' uses: shivammathur/setup-php@v2 with: - php-version: ${{ matrix.php-versions }} + php-version: ${{ matrix.php-version }} coverage: none tools: composer:v2 env: From 7ff26bf661e7df4aa7ad7ded38de55d9c9ddd2fb Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:14:29 -0600 Subject: [PATCH 06/34] Remove duplicated test --- tests/Unit/Persona/Traits/PersonaTrait.php | 23 +++------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/tests/Unit/Persona/Traits/PersonaTrait.php b/tests/Unit/Persona/Traits/PersonaTrait.php index 1e31cff..719de8e 100644 --- a/tests/Unit/Persona/Traits/PersonaTrait.php +++ b/tests/Unit/Persona/Traits/PersonaTrait.php @@ -31,30 +31,13 @@ public function test_allows_more_than_one_regimen(): void } /** - * - * test to check if new property not contained in Persona is found is assigned and value can be retrieved - * its goal is not to be used but to prevent unexpected exceptions - * */ + * test to check if new property not contained in Persona is found is assigned and value can be retrieved + * its goal is not to be used but to prevent unexpected exceptions + */ public function test_assign_dynamic_property(): void { /** @phpstan-ignore-next-line */ $this->person->{'dynamic'} = 'dynamic'; $this->assertSame('dynamic', $this->person->{'dynamic'}); } - - public function test_allows_more_than_one_regimen(): void - { - $first = new Regimen(); - $first->setRegimen('Simplificado de confianza'); - $second = new Regimen(); - $second->setRegimen('Demás ingresos'); - - $person = $this->person; - $person->addRegimenes($first, $second); - - $this->assertSame( - [$first, $second], - $person->getRegimenes()->getRegimenes(), - ); - } } From e8ee9e6a1c355987d66a14bf77c57030d6e2793e Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:15:30 -0600 Subject: [PATCH 07/34] Fix fully qualified strict types (code standard) --- src/Scraper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Scraper.php b/src/Scraper.php index 528890f..fe661d6 100644 --- a/src/Scraper.php +++ b/src/Scraper.php @@ -64,9 +64,9 @@ public function obtainFromRfcAndCif(Rfc $rfc, string $idCIF): PersonaMoral|Perso * @param string $path * @return PersonaMoral|PersonaFisica * @throws Exceptions\CifNotFoundException - * @throws Exceptions\PdfReader\CifFromPdfNotFoundException + * @throws CifFromPdfNotFoundException * @throws Exceptions\PdfReader\EmptyPdfContentException - * @throws Exceptions\PdfReader\RfcFromPdfNotFoundException + * @throws RfcFromPdfNotFoundException * @throws InvalidExpressionToParseException */ public function obtainFromPdfPath(string $path): PersonaMoral|PersonaFisica From baf484a869fabdbc989c1f24d8c5ab512447a2d2 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:16:18 -0600 Subject: [PATCH 08/34] Update code standards for ph-pcs-fixer --- .php-cs-fixer.dist.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 6c84854..084f69c 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -15,9 +15,10 @@ ->setRules([ '@PSR12' => true, '@PSR12:risky' => true, - '@PHP80Migration' => true, - '@PHP80Migration:risky' => true, + '@PHP8x0Migration' => true, + '@PHP8x0Migration:risky' => true, // symfony + 'array_indentation' => true, 'class_attributes_separation' => true, 'whitespace_after_comma_in_array' => true, 'no_empty_statement' => true, @@ -36,6 +37,8 @@ 'standardize_not_equals' => true, 'concat_space' => ['spacing' => 'one'], 'linebreak_after_opening_tag' => true, + 'fully_qualified_strict_types' => true, + 'global_namespace_import' => ['import_classes' => true], // symfony:risky 'no_alias_functions' => true, 'self_accessor' => true, From c70de7186538284e07b08e95190aab65b1cc650f Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:17:27 -0600 Subject: [PATCH 09/34] Update development tools --- .phive/phars.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.phive/phars.xml b/.phive/phars.xml index f334cd6..f51d40e 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,8 +1,8 @@ - - - - - + + + + + From 6cc8bf9d62b74c424385a25a7190ab26232e5410 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:27:30 -0600 Subject: [PATCH 10/34] Upgrade to PHPStan 2.x and resolve issues --- .phive/phars.xml | 2 +- src/DataExtractor.php | 2 +- src/Regimenes.php | 13 +++---------- tests/Unit/Exceptions/CifDownloadExceptionTest.php | 1 + tests/Unit/Exceptions/CifNotFoundExceptionTest.php | 1 + .../PdfReader/CifFromPdfNotFoundExceptionTest.php | 1 + .../PdfReader/EmptyPdfContentExceptionTest.php | 1 + .../PdfReader/PdfToTextConvertExceptionTest.php | 1 + .../PdfReader/RfcFromPdfNotFoundExceptionTest.php | 1 + tests/Unit/Persona/PersonaJsonSerializeTest.php | 6 ++---- tests/Unit/Regimen/RegimenJsonSerializeTest.php | 3 +-- tests/Unit/Regimen/RegimenesJsonSerializeTest.php | 3 +-- 12 files changed, 15 insertions(+), 20 deletions(-) diff --git a/.phive/phars.xml b/.phive/phars.xml index f51d40e..c1560e9 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,6 +1,6 @@ - + diff --git a/src/DataExtractor.php b/src/DataExtractor.php index 876cec0..3c0bf85 100644 --- a/src/DataExtractor.php +++ b/src/DataExtractor.php @@ -48,7 +48,7 @@ private function getValueByTdTitleText(Crawler $crawler, string $valueToSearch): if (null === $node) { return ''; } - return trim(str_replace($valueToSearch, ' ', $this->normalizeWhiteSpaces($node->parentNode?->parentNode?->textContent ?? ''))); + return trim(str_replace($valueToSearch, ' ', $this->normalizeWhiteSpaces($node->parentNode->parentNode->textContent ?? ''))); } private function normalizeWhiteSpaces(string $str): string diff --git a/src/Regimenes.php b/src/Regimenes.php index e429cc1..627fcad 100644 --- a/src/Regimenes.php +++ b/src/Regimenes.php @@ -9,15 +9,10 @@ class Regimenes implements JsonSerializable { - /** - * @var Regimen[] - */ + /** @var list */ private array $regimenes = []; - /** - * - * @return Regimen[] - */ + /** @return list */ public function getRegimenes(): array { return $this->regimenes; @@ -31,9 +26,7 @@ public function addRegimen(Regimen $regimen, Regimen ...$regimenes): void } } - /** - * @return array - */ + /** @return list */ public function toArray(): array { return array_map( diff --git a/tests/Unit/Exceptions/CifDownloadExceptionTest.php b/tests/Unit/Exceptions/CifDownloadExceptionTest.php index ce7b670..1292371 100644 --- a/tests/Unit/Exceptions/CifDownloadExceptionTest.php +++ b/tests/Unit/Exceptions/CifDownloadExceptionTest.php @@ -13,6 +13,7 @@ final class CifDownloadExceptionTest extends TestCase { public function test_implements_library_exception_type(): void { + /** @phpstan-ignore function.alreadyNarrowedType */ $this->assertTrue(is_a(CifDownloadException::class, CsfScraperException::class, true)); } diff --git a/tests/Unit/Exceptions/CifNotFoundExceptionTest.php b/tests/Unit/Exceptions/CifNotFoundExceptionTest.php index bd5f323..a552ce8 100644 --- a/tests/Unit/Exceptions/CifNotFoundExceptionTest.php +++ b/tests/Unit/Exceptions/CifNotFoundExceptionTest.php @@ -12,6 +12,7 @@ final class CifNotFoundExceptionTest extends TestCase { public function test_implements_library_exception_type(): void { + /** @phpstan-ignore function.alreadyNarrowedType */ $this->assertTrue(is_a(CifNotFoundException::class, CsfScraperException::class, true)); } } diff --git a/tests/Unit/Exceptions/PdfReader/CifFromPdfNotFoundExceptionTest.php b/tests/Unit/Exceptions/PdfReader/CifFromPdfNotFoundExceptionTest.php index 81bb9c4..0e7eafb 100644 --- a/tests/Unit/Exceptions/PdfReader/CifFromPdfNotFoundExceptionTest.php +++ b/tests/Unit/Exceptions/PdfReader/CifFromPdfNotFoundExceptionTest.php @@ -12,6 +12,7 @@ final class CifFromPdfNotFoundExceptionTest extends TestCase { public function test_implements_library_exception_type(): void { + /** @phpstan-ignore function.alreadyNarrowedType */ $this->assertTrue(is_a(CifFromPdfNotFoundException::class, CsfScraperException::class, true)); } } diff --git a/tests/Unit/Exceptions/PdfReader/EmptyPdfContentExceptionTest.php b/tests/Unit/Exceptions/PdfReader/EmptyPdfContentExceptionTest.php index aaa4172..f297f56 100644 --- a/tests/Unit/Exceptions/PdfReader/EmptyPdfContentExceptionTest.php +++ b/tests/Unit/Exceptions/PdfReader/EmptyPdfContentExceptionTest.php @@ -12,6 +12,7 @@ final class EmptyPdfContentExceptionTest extends TestCase { public function test_implements_library_exception_type(): void { + /** @phpstan-ignore function.alreadyNarrowedType */ $this->assertTrue(is_a(EmptyPdfContentException::class, CsfScraperException::class, true)); } } diff --git a/tests/Unit/Exceptions/PdfReader/PdfToTextConvertExceptionTest.php b/tests/Unit/Exceptions/PdfReader/PdfToTextConvertExceptionTest.php index 73e8abe..05ba22b 100644 --- a/tests/Unit/Exceptions/PdfReader/PdfToTextConvertExceptionTest.php +++ b/tests/Unit/Exceptions/PdfReader/PdfToTextConvertExceptionTest.php @@ -12,6 +12,7 @@ final class PdfToTextConvertExceptionTest extends TestCase { public function test_implements_library_exception_type(): void { + /** @phpstan-ignore function.alreadyNarrowedType */ $this->assertTrue(is_a(PdfToTextConvertException::class, CsfScraperException::class, true)); } diff --git a/tests/Unit/Exceptions/PdfReader/RfcFromPdfNotFoundExceptionTest.php b/tests/Unit/Exceptions/PdfReader/RfcFromPdfNotFoundExceptionTest.php index b6a8bb9..99563f5 100644 --- a/tests/Unit/Exceptions/PdfReader/RfcFromPdfNotFoundExceptionTest.php +++ b/tests/Unit/Exceptions/PdfReader/RfcFromPdfNotFoundExceptionTest.php @@ -12,6 +12,7 @@ final class RfcFromPdfNotFoundExceptionTest extends TestCase { public function test_implements_library_exception_type(): void { + /** @phpstan-ignore function.alreadyNarrowedType */ $this->assertTrue(is_a(RfcFromPdfNotFoundException::class, CsfScraperException::class, true)); } } diff --git a/tests/Unit/Persona/PersonaJsonSerializeTest.php b/tests/Unit/Persona/PersonaJsonSerializeTest.php index 4f98130..0305a08 100644 --- a/tests/Unit/Persona/PersonaJsonSerializeTest.php +++ b/tests/Unit/Persona/PersonaJsonSerializeTest.php @@ -14,8 +14,7 @@ public function test_serialize_default_person_moral(): void { $person = new PersonaMoral(); - /** @var string $json */ - $json = json_encode($person); + $json = (string) json_encode($person); $this->assertSame([ 'razon_social' => '', @@ -45,8 +44,7 @@ public function test_serialize_default_person_fisica(): void { $person = new PersonaFisica(); - /** @var string $json */ - $json = json_encode($person); + $json = (string) json_encode($person); $this->assertSame([ 'curp' => '', diff --git a/tests/Unit/Regimen/RegimenJsonSerializeTest.php b/tests/Unit/Regimen/RegimenJsonSerializeTest.php index 6a50e55..ff4bf6c 100644 --- a/tests/Unit/Regimen/RegimenJsonSerializeTest.php +++ b/tests/Unit/Regimen/RegimenJsonSerializeTest.php @@ -13,8 +13,7 @@ public function test_serialize_default_regimen(): void { $regimen = new Regimen(); - /** @var string $json */ - $json = json_encode($regimen); + $json = (string) json_encode($regimen); $this->assertSame([ 'regimen' => '', diff --git a/tests/Unit/Regimen/RegimenesJsonSerializeTest.php b/tests/Unit/Regimen/RegimenesJsonSerializeTest.php index 96973eb..c8d7148 100644 --- a/tests/Unit/Regimen/RegimenesJsonSerializeTest.php +++ b/tests/Unit/Regimen/RegimenesJsonSerializeTest.php @@ -16,8 +16,7 @@ public function test_serialize_default_regimenes(): void $regimenes->addRegimen(new Regimen(), new Regimen()); - /** @var string $json */ - $json = json_encode($regimenes); + $json = (string) json_encode($regimenes); $this->assertSame([ [ From ba089ac544bc7800b3a70f5fa3f34a55f3758876 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:28:40 -0600 Subject: [PATCH 11/34] Add PHP 8.3 & PHP 8.4 to test matrix --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77e797e..95d02c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,7 +82,7 @@ jobs: strategy: matrix: operating-systems: ["windows-latest", "ubuntu-latest"] - php-version: ['8.0', '8.1', '8.2'] + php-version: ['8.0', '8.1', '8.2', '8.3', '8.4'] steps: - name: Checkout uses: actions/checkout@v4 From ecd3991f83ea3ca3d535e334a5c362c15a126b1c Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:29:49 -0600 Subject: [PATCH 12/34] Run jobs using PHP 8.4 --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 95d02c2..4e2b73a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: '8.4' coverage: none tools: cs2pr, phpcs env: @@ -39,7 +39,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: '8.4' coverage: none tools: cs2pr, php-cs-fixer env: @@ -56,7 +56,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.2' + php-version: '8.4' coverage: none tools: composer:v2, phpstan env: From 5dad3a97976a0735d1ca787777e65b0473863108 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:33:35 -0600 Subject: [PATCH 13/34] Add composer-normalize development tool --- .github/workflows/build.yml | 17 +++++++++++++++++ .phive/phars.xml | 1 + composer.json | 6 ++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4e2b73a..730c17e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,6 +13,23 @@ 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.4' + 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" diff --git a/.phive/phars.xml b/.phive/phars.xml index c1560e9..b46df33 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -5,4 +5,5 @@ + diff --git a/composer.json b/composer.json index 22d1935..b76b70e 100644 --- a/composer.json +++ b/composer.json @@ -57,10 +57,12 @@ "scripts": { "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 src/ tests/" ], "dev:fix-style": [ + "@php tools/composer-normalize normalize", "@php tools/php-cs-fixer fix --verbose", "@php tools/phpcbf --colors -sp src/ tests/" ], @@ -76,8 +78,8 @@ }, "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:check-style": "DEV: search for code style errors using composer-normalize, php-cs-fixer and phpcs", + "dev:fix-style": "DEV: fix code style errors using composer-normalize, php-cs-fixer and phpcbf", "dev:test": "DEV: run @dev:check-style, phpunit and phpstan", "dev:coverage": "DEV: run phpunit with xdebug and storage coverage in build/coverage/html/" } From ad18ed986477f79eb52ce9ebbf165ec879fb65bd Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:34:23 -0600 Subject: [PATCH 14/34] Normalize composer.json using composer-normalize --- composer.json | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index b76b70e..719613e 100644 --- a/composer.json +++ b/composer.json @@ -1,10 +1,13 @@ { "name": "phpcfdi/csf-scraper", "description": "Obtiene los datos fiscales actuales de una persona moral o física dado su RFC y CIFID", - "keywords": ["phpcfdi", "sat", "csf"], - "homepage": "https://github.com/phpcfdi/csf-scraper", - "type": "library", "license": "MIT", + "type": "library", + "keywords": [ + "phpcfdi", + "sat", + "csf" + ], "authors": [ { "name": "Cesar Aguilera", @@ -19,22 +22,16 @@ "email": "fernando.isidro@ocelotlstudio.com" } ], + "homepage": "https://github.com/phpcfdi/csf-scraper", "support": { - "source": "https://github.com/phpcfdi/csf-scraper", - "issues": "https://github.com/phpcfdi/csf-scraper/issues" - }, - "prefer-stable": true, - "config": { - "optimize-autoloader": true, - "preferred-install": { - "*": "dist" - } + "issues": "https://github.com/phpcfdi/csf-scraper/issues", + "source": "https://github.com/phpcfdi/csf-scraper" }, "require": { "php": ">=8.0", - "ext-mbstring": "*", - "ext-json": "*", "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", "guzzlehttp/guzzle": "^7.4", "phpcfdi/rfc": "^1.1", "symfony/css-selector": ">=6.0", @@ -42,8 +39,9 @@ "symfony/process": ">=6.0" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^9.5" }, + "prefer-stable": true, "autoload": { "psr-4": { "PhpCfdi\\CsfScraper\\": "src/" @@ -54,13 +52,25 @@ "PhpCfdi\\CsfScraper\\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 src/ tests/" ], + "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", @@ -71,16 +81,13 @@ "@php vendor/bin/phpunit --testdox --verbose --stop-on-failure", "@php tools/phpstan analyse --no-interaction --no-progress", "@php tools/composer-require-checker" - ], - "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 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 and phpstan", - "dev:coverage": "DEV: run phpunit with xdebug and storage coverage in build/coverage/html/" + "dev:test": "DEV: run @dev:check-style, phpunit and phpstan" } } From b4beb8c7624e297c8e02808d0978a9aa737b3623 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:39:02 -0600 Subject: [PATCH 15/34] Fix `composer validate` warning dependence Unbound version constraints should be avoided --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 719613e..98d4ba9 100644 --- a/composer.json +++ b/composer.json @@ -34,9 +34,9 @@ "ext-mbstring": "*", "guzzlehttp/guzzle": "^7.4", "phpcfdi/rfc": "^1.1", - "symfony/css-selector": ">=6.0", - "symfony/dom-crawler": ">=6.0", - "symfony/process": ">=6.0" + "symfony/css-selector": "^6.0 || ^7.0", + "symfony/dom-crawler": "^6.0 || ^7.0", + "symfony/process": "^6.0 || ^7.0" }, "require-dev": { "phpunit/phpunit": "^9.5" From 270e4146cdcaf7f208324693ef83808639e93184 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:42:29 -0600 Subject: [PATCH 16/34] Update license year to 2025 --- LICENCE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENCE b/LICENCE index 1791339..84985b8 100644 --- a/LICENCE +++ b/LICENCE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2022 - 2024 PhpCfdi https://www.phpcfdi.com/ +Copyright (c) 2022 - 2025 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 From 32a0b566dfe799e61d2a7335869af83de406fa62 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:47:28 -0600 Subject: [PATCH 17/34] Fix SonarQube Cloud integration --- .github/workflows/sonarcloud.yml | 113 -------------------------- .github/workflows/sonarqube-cloud.yml | 57 +++++++++++++ README.md | 4 +- 3 files changed, 59 insertions(+), 115 deletions(-) delete mode 100644 .github/workflows/sonarcloud.yml create mode 100644 .github/workflows/sonarqube-cloud.yml diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml deleted file mode 100644 index b9d0819..0000000 --- a/.github/workflows/sonarcloud.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: sonarcloud -on: - workflow_dispatch: - push: - branches: [ "main" ] - -# Actions -# shivammathur/setup-php@v2 https://github.com/marketplace/actions/setup-php-action -# sonarsource/sonarcloud-github-action@master https://github.com/marketplace/actions/sonarcloud-scan - -jobs: - - tests-coverage: - name: Build code coverage - runs-on: "ubuntu-latest" - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.2' - coverage: xdebug - tools: composer:v2 - env: - fail-fast: true - - name: Install poppler-utils - run: | - sudo apt-get update -y -qq - sudo apt-get install -y poppler-utils - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Cache dependencies - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Install project dependencies - run: composer upgrade --no-interaction --no-progress --prefer-dist - - name: Create code coverage - run: vendor/bin/phpunit --testdox --verbose --coverage-xml=build/coverage --coverage-clover=build/coverage/clover.xml --log-junit=build/coverage/junit.xml - - name: Store code coverage - uses: actions/upload-artifact@v4 - with: - name: code-coverage - path: build/coverage - - sonarcloud-secrets: - name: SonarCloud check secrets are present - runs-on: ubuntu-latest - outputs: - github: ${{ steps.check-secrets.outputs.github }} - sonar: ${{ steps.check-secrets.outputs.sonar }} - steps: - - name: Check secrets are present - id: check-secrets - run: | - if [ -n "${{ secrets.GITHUB_TOKEN }}" ]; then - echo "github=yes" >> $GITHUB_OUTPUT - else - echo "github=no" >> $GITHUB_OUTPUT - echo "::warning ::GITHUB_TOKEN non set" - fi - if [ -n "${{ secrets.SONAR_TOKEN }}" ]; then - echo "sonar=yes" >> $GITHUB_OUTPUT - else - echo "sonar=no" >> $GITHUB_OUTPUT - echo "::warning ::SONAR_TOKEN non set" - fi - - sonarcloud: - name: SonarCloud Scan and Report - needs: [ "tests-coverage", "sonarcloud-secrets" ] - if: ${{ needs.sonarcloud-secrets.outputs.github == 'yes' && needs.sonarcloud-secrets.outputs.sonar == 'yes' }} - runs-on: "ubuntu-latest" - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Unshallow clone to provide blame information - run: git fetch --unshallow - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.2' - coverage: none - tools: composer:v2 - - name: Get composer cache directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - name: Cache dependencies - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Install project dependencies - run: composer upgrade --no-interaction --no-progress --prefer-dist - - name: Obtain code coverage - uses: actions/download-artifact@v4 - with: - name: code-coverage - path: build/coverage - - name: Prepare SonarCloud Code Coverage Files - run: | - 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/sonarcloud-github-action@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/sonarqube-cloud.yml b/.github/workflows/sonarqube-cloud.yml new file mode 100644 index 0000000..ffd67c2 --- /dev/null +++ b/.github/workflows/sonarqube-cloud.yml @@ -0,0 +1,57 @@ +name: "SonarQube Cloud" +on: + workflow_dispatch: + push: + branches: [ "main" ] + +# 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 + +jobs: + + sonarqube-cloud: + name: SonarCloud Scan and Report + runs-on: "ubuntu-latest" + steps: + - name: Check SONAR_TOKEN secret + run: | + if [ -z "${{ secrets.SONAR_TOKEN }}" ]; then + echo "::warning ::SONAR_TOKEN non set" + exit 1 + fi + - name: Checkout + uses: actions/checkout@v4 + - name: Unshallow clone to provide blame information + run: git fetch --unshallow + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + coverage: xdebug + tools: composer:v2 + - name: Install poppler-utils + run: | + sudo apt-get update -y -qq + sudo apt-get install -y poppler-utils + - name: Get composer cache directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + - name: Install project dependencies + run: composer upgrade --no-interaction --no-progress --prefer-dist + - name: Create code coverage + run: vendor/bin/phpunit --testdox --verbose --coverage-xml=build/coverage --coverage-clover=build/coverage/clover.xml --log-junit=build/coverage/junit.xml + - name: Prepare SonarCloud Code Coverage Files + run: | + 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 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/README.md b/README.md index 43c7345..e5e7a37 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,6 @@ and licensed for use under the MIT License (MIT). Please see [LICENSE][] for mor [badge-build]: https://img.shields.io/github/actions/workflow/status/phpcfdi/csf-scraper/build.yml?branch=main&logo=github-actions [badge-reliability]: https://sonarcloud.io/api/project_badges/measure?project=phpcfdi_csf-scraper&metric=reliability_rating [badge-maintainability]: https://sonarcloud.io/api/project_badges/measure?project=phpcfdi_csf-scraper&metric=sqale_rating -[badge-coverage]: https://img.shields.io/sonar/coverage/phpcfdi_csf-scraper/main?logo=sonarcloud&server=https%3A%2F%2Fsonarcloud.io -[badge-violations]: https://img.shields.io/sonar/violations/phpcfdi_csf-scraper/main?format=long&logo=sonarcloud&server=https%3A%2F%2Fsonarcloud.io +[badge-coverage]: https://img.shields.io/sonar/coverage/phpcfdi_csf-scraper/main?logo=sonarqubecloud&server=https%3A%2F%2Fsonarcloud.io +[badge-violations]: https://img.shields.io/sonar/violations/phpcfdi_csf-scraper/main?format=long&logo=sonarqubecloud&server=https%3A%2F%2Fsonarcloud.io [badge-downloads]: https://img.shields.io/packagist/dt/phpcfdi/csf-scraper.svg?logo=packagist From 3758beeefc066d4c4ae45e40d19515071bbba34d Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 13:49:43 -0600 Subject: [PATCH 18/34] Leave only one step for set up php There is no need to split linux from windows --- .github/workflows/build.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 730c17e..274c5e0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -103,17 +103,7 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Setup PHP on Linux - if: matrix.operating-systems == 'ubuntu-latest' - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - coverage: none - tools: composer:v2 - env: - fail-fast: true - - name: Setup PHP on Windows - if: matrix.operating-systems == 'windows-latest' + - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} From 241f90abb24ee6cd1b97aa2c048cc25a1d4a25e9 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 14:00:06 -0600 Subject: [PATCH 19/34] Bump to PHP 8.1 --- .github/workflows/build.yml | 2 +- .php-cs-fixer.dist.php | 2 +- composer.json | 2 +- src/DataExtractor.php | 2 +- src/Exceptions/CifDownloadException.php | 2 +- src/Exceptions/PdfReader/PdfToTextConvertException.php | 8 ++++---- src/PdfReader/CsfExtractor.php | 4 ++-- src/PdfReader/PdfToText.php | 2 +- src/Persona.php | 2 +- src/Scraper.php | 6 +----- 10 files changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 274c5e0..4513de4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -99,7 +99,7 @@ jobs: strategy: matrix: operating-systems: ["windows-latest", "ubuntu-latest"] - php-version: ['8.0', '8.1', '8.2', '8.3', '8.4'] + php-version: ['8.1', '8.2', '8.3', '8.4'] steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 084f69c..cb9d2f4 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -15,7 +15,7 @@ ->setRules([ '@PSR12' => true, '@PSR12:risky' => true, - '@PHP8x0Migration' => true, + '@PHP8x1Migration' => true, '@PHP8x0Migration:risky' => true, // symfony 'array_indentation' => true, diff --git a/composer.json b/composer.json index 98d4ba9..497e116 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "source": "https://github.com/phpcfdi/csf-scraper" }, "require": { - "php": ">=8.0", + "php": ">=8.1", "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", diff --git a/src/DataExtractor.php b/src/DataExtractor.php index 3c0bf85..0be2f40 100644 --- a/src/DataExtractor.php +++ b/src/DataExtractor.php @@ -11,7 +11,7 @@ final class DataExtractor implements DataExtractorInterface { - public function __construct(private string $html) + public function __construct(private readonly string $html) { } diff --git a/src/Exceptions/CifDownloadException.php b/src/Exceptions/CifDownloadException.php index 153b283..c1f3e93 100644 --- a/src/Exceptions/CifDownloadException.php +++ b/src/Exceptions/CifDownloadException.php @@ -9,7 +9,7 @@ final class CifDownloadException extends RuntimeException implements CsfScraperException { - public function __construct(private string $url, Throwable $previous) + public function __construct(private readonly string $url, Throwable $previous) { parent::__construct('The request has failed', previous: $previous); } diff --git a/src/Exceptions/PdfReader/PdfToTextConvertException.php b/src/Exceptions/PdfReader/PdfToTextConvertException.php index 8f0c765..5825f12 100644 --- a/src/Exceptions/PdfReader/PdfToTextConvertException.php +++ b/src/Exceptions/PdfReader/PdfToTextConvertException.php @@ -14,10 +14,10 @@ final class PdfToTextConvertException extends RuntimeException implements CsfScr */ public function __construct( string $message, - private array $command, - private int $exitCode, - private string $output, - private string $error, + private readonly array $command, + private readonly int $exitCode, + private readonly string $output, + private readonly string $error, ) { parent::__construct($message); } diff --git a/src/PdfReader/CsfExtractor.php b/src/PdfReader/CsfExtractor.php index 905a5ca..503df40 100644 --- a/src/PdfReader/CsfExtractor.php +++ b/src/PdfReader/CsfExtractor.php @@ -15,14 +15,14 @@ final class CsfExtractor /** * @var string[] */ - private array $lines; + private readonly array $lines; /** * @throws EmptyPdfContentException */ public function __construct(string $contents) { - if ('' == $contents) { + if ('' === $contents) { throw new EmptyPdfContentException('Cannot read pdf contents.'); } $this->lines = explode("\n", $contents); diff --git a/src/PdfReader/PdfToText.php b/src/PdfReader/PdfToText.php index 9daad4a..62a4872 100644 --- a/src/PdfReader/PdfToText.php +++ b/src/PdfReader/PdfToText.php @@ -12,7 +12,7 @@ */ final class PdfToText { - private string $pdftotext; + private readonly string $pdftotext; public function __construct(string $pathPdfToText = '') { diff --git a/src/Persona.php b/src/Persona.php index a243446..6656c75 100644 --- a/src/Persona.php +++ b/src/Persona.php @@ -39,7 +39,7 @@ abstract class Persona implements JsonSerializable private string $al = ''; - private Regimenes $regimenes; + private readonly Regimenes $regimenes; /** @var mixed[] */ private array $data = []; diff --git a/src/Scraper.php b/src/Scraper.php index fe661d6..d3ec795 100644 --- a/src/Scraper.php +++ b/src/Scraper.php @@ -22,7 +22,7 @@ class Scraper implements ScraperInterface { public static string $url = 'https://siat.sat.gob.mx/app/qr/faces/pages/mobile/validadorqr.jsf?D1=10&D2=1&D3=%s_%s'; - public function __construct(private ClientInterface $client) + public function __construct(private readonly ClientInterface $client) { } @@ -61,8 +61,6 @@ public function obtainFromRfcAndCif(Rfc $rfc, string $idCIF): PersonaMoral|Perso * Obtain a PersonaMoral or PersonaFisica object with the information from SAT website * The RFC and CIF is taken from the "Constancia de Situación Fiscal" PDF file * - * @param string $path - * @return PersonaMoral|PersonaFisica * @throws Exceptions\CifNotFoundException * @throws CifFromPdfNotFoundException * @throws Exceptions\PdfReader\EmptyPdfContentException @@ -88,8 +86,6 @@ public function obtainFromPdfPath(string $path): PersonaMoral|PersonaFisica /** * Helper method to extract the text information from PDF to plain text * - * @param string $path - * @return string * @throws Exceptions\PdfReader\PdfToTextConvertException when call to pdftotext fail */ protected function pdfToTextContent(string $path): string From c93ace6d69a756cf8a251d560e5dc4dab83369dc Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 14:04:29 -0600 Subject: [PATCH 20/34] Bump to PHP 8.2 --- .github/workflows/build.yml | 2 +- .php-cs-fixer.dist.php | 8 ++++---- composer.json | 2 +- src/DataExtractor.php | 4 ++-- src/PdfReader/CsfExtractor.php | 4 ++-- src/PdfReader/PdfToText.php | 6 +++--- src/Regimenes.php | 2 +- tests/Unit/ScraperTest.php | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4513de4..905d832 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -99,7 +99,7 @@ jobs: strategy: matrix: operating-systems: ["windows-latest", "ubuntu-latest"] - php-version: ['8.1', '8.2', '8.3', '8.4'] + php-version: ['8.2', '8.3', '8.4'] steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index cb9d2f4..712e3dc 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -15,8 +15,8 @@ ->setRules([ '@PSR12' => true, '@PSR12:risky' => true, - '@PHP8x1Migration' => true, - '@PHP8x0Migration:risky' => true, + '@PHP8x2Migration' => true, + '@PHP8x2Migration:risky' => true, // symfony 'array_indentation' => true, 'class_attributes_separation' => true, @@ -24,7 +24,7 @@ 'no_empty_statement' => true, 'no_extra_blank_lines' => true, 'type_declaration_spaces' => true, - 'trailing_comma_in_multiline' => ['after_heredoc' => true, 'elements' => ['arrays']], + 'trailing_comma_in_multiline' => ['after_heredoc' => true, 'elements' => ['array_destructuring', 'arrays', 'match', 'arguments', 'parameters']], 'no_blank_lines_after_phpdoc' => true, 'object_operator_without_whitespace' => true, 'binary_operator_spaces' => true, @@ -50,6 +50,6 @@ PhpCsFixer\Finder::create() ->in(__DIR__) ->append([__FILE__]) - ->exclude(['tools', 'vendor', 'build']) + ->exclude(['tools', 'vendor', 'build']), ) ; diff --git a/composer.json b/composer.json index 497e116..dad654b 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "source": "https://github.com/phpcfdi/csf-scraper" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*", diff --git a/src/DataExtractor.php b/src/DataExtractor.php index 0be2f40..2a21d37 100644 --- a/src/DataExtractor.php +++ b/src/DataExtractor.php @@ -9,9 +9,9 @@ use RuntimeException; use Symfony\Component\DomCrawler\Crawler; -final class DataExtractor implements DataExtractorInterface +final readonly class DataExtractor implements DataExtractorInterface { - public function __construct(private readonly string $html) + public function __construct(private string $html) { } diff --git a/src/PdfReader/CsfExtractor.php b/src/PdfReader/CsfExtractor.php index 503df40..84ac22c 100644 --- a/src/PdfReader/CsfExtractor.php +++ b/src/PdfReader/CsfExtractor.php @@ -10,12 +10,12 @@ * * @internal */ -final class CsfExtractor +final readonly class CsfExtractor { /** * @var string[] */ - private readonly array $lines; + private array $lines; /** * @throws EmptyPdfContentException diff --git a/src/PdfReader/PdfToText.php b/src/PdfReader/PdfToText.php index 62a4872..8171ec5 100644 --- a/src/PdfReader/PdfToText.php +++ b/src/PdfReader/PdfToText.php @@ -10,9 +10,9 @@ /** * Extract the contents of a pdf file using pdftotext (apt-get install poppler-utils) */ -final class PdfToText +final readonly class PdfToText { - private readonly string $pdftotext; + private string $pdftotext; public function __construct(string $pathPdfToText = '') { @@ -37,7 +37,7 @@ public function extract(string $path): string $command, $exitCode, $process->getOutput(), - $process->getErrorOutput() + $process->getErrorOutput(), ); } return $process->getOutput(); diff --git a/src/Regimenes.php b/src/Regimenes.php index 627fcad..d8b9854 100644 --- a/src/Regimenes.php +++ b/src/Regimenes.php @@ -31,7 +31,7 @@ public function toArray(): array { return array_map( fn (Regimen $regimen): array => $regimen->toArray(), - $this->regimenes + $this->regimenes, ); } diff --git a/tests/Unit/ScraperTest.php b/tests/Unit/ScraperTest.php index e82240a..723a69c 100644 --- a/tests/Unit/ScraperTest.php +++ b/tests/Unit/ScraperTest.php @@ -27,7 +27,7 @@ public function test_create_with_specific_openssl_cipher_list(): void */ $this->assertSame( [CURLOPT_SSL_CIPHER_LIST => 'DEFAULT@SECLEVEL=1'], - $client->getConfig('curl') + $client->getConfig('curl'), ); } } From 4b679444b243eea084987f056cc17603bbb5a356 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 14:20:16 -0600 Subject: [PATCH 21/34] Clean up code --- src/DataExtractor.php | 2 +- src/PdfReader/CsfExtractor.php | 9 ++------- src/PdfReader/PdfToText.php | 4 +--- src/Persona.php | 2 +- src/Regimen.php | 9 ++------- 5 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/DataExtractor.php b/src/DataExtractor.php index 2a21d37..5878b66 100644 --- a/src/DataExtractor.php +++ b/src/DataExtractor.php @@ -43,7 +43,7 @@ public function extract(bool $isFisica): PersonaMoral|PersonaFisica private function getValueByTdTitleText(Crawler $crawler, string $valueToSearch): string { - $element = $crawler->filterXPath("//td[@role='gridcell']/span[contains(normalize-space(.), '{$valueToSearch}')]"); + $element = $crawler->filterXPath("//td[@role='gridcell']/span[contains(normalize-space(.), '$valueToSearch')]"); $node = $element->getNode(0); if (null === $node) { return ''; diff --git a/src/PdfReader/CsfExtractor.php b/src/PdfReader/CsfExtractor.php index 84ac22c..98449f0 100644 --- a/src/PdfReader/CsfExtractor.php +++ b/src/PdfReader/CsfExtractor.php @@ -6,15 +6,10 @@ use PhpCfdi\CsfScraper\Exceptions\PdfReader\EmptyPdfContentException; -/** - * - * @internal - */ +/** @internal */ final readonly class CsfExtractor { - /** - * @var string[] - */ + /** @var list */ private array $lines; /** diff --git a/src/PdfReader/PdfToText.php b/src/PdfReader/PdfToText.php index 8171ec5..debc891 100644 --- a/src/PdfReader/PdfToText.php +++ b/src/PdfReader/PdfToText.php @@ -43,9 +43,7 @@ public function extract(string $path): string return $process->getOutput(); } - /** - * @return string[] - */ + /** @return list */ public function buildCommand(string $pdfFile): array { return [$this->pdftotext, '-eol', 'unix', '-raw', '-q', $pdfFile, '-']; diff --git a/src/Persona.php b/src/Persona.php index 6656c75..19cef1b 100644 --- a/src/Persona.php +++ b/src/Persona.php @@ -212,7 +212,7 @@ public function addRegimenes(Regimen ...$regimenes): void } /** - * The values must be a simple text to search using xpath as in contains(normalize-space(.), {value})' + * The values must be a simple text to search using xpath as in 'contains(normalize-space(.), {value})' * @return array */ abstract public function getTdTitlesTextToSearch(): array; diff --git a/src/Regimen.php b/src/Regimen.php index 0537a3a..9d42650 100644 --- a/src/Regimen.php +++ b/src/Regimen.php @@ -15,10 +15,7 @@ class Regimen implements JsonSerializable private ?DateTimeImmutable $fechaAlta = null; - /** - * - * @var array - */ + /** @var list */ private array $regimenes = [ [ 'id' => '601', @@ -137,9 +134,7 @@ private function searchRegimenIdByText(string $text): string return ''; } - /** - * @return array{regimen: string, regimen_id: string, fecha_alta: ?DateTimeImmutable} - */ + /** @return array{regimen: string, regimen_id: string, fecha_alta: ?DateTimeImmutable} */ public function toArray(): array { return [ From 0281804b49e069334c9c877a21382d8e903fd651 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 14:21:20 -0600 Subject: [PATCH 22/34] Static var Scraper::$url used as static and not self In case a class extends the object, the extended object may change this value --- src/Scraper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Scraper.php b/src/Scraper.php index d3ec795..1abef9d 100644 --- a/src/Scraper.php +++ b/src/Scraper.php @@ -49,7 +49,7 @@ public static function create(): self */ public function obtainFromRfcAndCif(Rfc $rfc, string $idCIF): PersonaMoral|PersonaFisica { - $uri = sprintf(self::$url, $idCIF, $rfc->getRfc()); + $uri = sprintf(static::$url, $idCIF, $rfc->getRfc()); $html = $this->obtainHtml($uri); $person = (new DataExtractor($html))->extract($rfc->isFisica()); $person->setRfc($rfc->getRfc()); From 63d84fba03ceb660d83fbe9384db7936a19fdc76 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 14:23:51 -0600 Subject: [PATCH 23/34] As of PHP 8.2, symfony dependeces can be set to ^7.0 --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index dad654b..85c3a8a 100644 --- a/composer.json +++ b/composer.json @@ -34,9 +34,9 @@ "ext-mbstring": "*", "guzzlehttp/guzzle": "^7.4", "phpcfdi/rfc": "^1.1", - "symfony/css-selector": "^6.0 || ^7.0", - "symfony/dom-crawler": "^6.0 || ^7.0", - "symfony/process": "^6.0 || ^7.0" + "symfony/css-selector": "^7.0", + "symfony/dom-crawler": "^7.0", + "symfony/process": "^7.0" }, "require-dev": { "phpunit/phpunit": "^9.5" From e0c91aca3d17e1a1cdbd927036af55f60db0cf01 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 14:28:48 -0600 Subject: [PATCH 24/34] Add job composer-require-checker --- .github/workflows/build.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 905d832..d22d0c3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,6 +30,35 @@ jobs: - name: Composer normalize run: composer-normalize --dry-run + composer-require-checker: + name: Composer require checker + runs-on: "ubuntu-latest" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + coverage: none + tools: composer-require-checker + env: + fail-fast: true + - name: Get composer cache directory + id: composer-cache + shell: bash + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + - name: Install project dependencies + run: composer upgrade --no-interaction --no-progress --prefer-dist + - name: Composer require checker + run: composer-require-checker + phpcs: name: Code style (phpcs) runs-on: "ubuntu-latest" From 8d66c730628a0eb1d45cee94bf2c56d19c725924 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 14:30:04 -0600 Subject: [PATCH 25/34] Reorder development tools --- .phive/phars.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.phive/phars.xml b/.phive/phars.xml index b46df33..f95968a 100644 --- a/.phive/phars.xml +++ b/.phive/phars.xml @@ -1,9 +1,9 @@ - + + - + - From 6ad1b843ca165f53e6cb47203021e9558f84c4c7 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 21:24:37 -0600 Subject: [PATCH 26/34] Upgrade to PHPUnit 11.5 --- composer.json | 2 +- phpunit.xml.dist | 26 ++++++++++++------- tests/Integration/ScrapFromCsfFileTest.php | 12 +++------ .../PdfReader/CsfExtractor/GetRfcTest.php | 5 ++-- .../PdfToText/PdfToTextConstructorTest.php | 5 ++-- .../Persona/CommonPersonaPropertiesTest.php | 18 +++++-------- .../Persona/PersonaFisicaPropertiesTest.php | 18 +++++-------- .../Persona/PersonaMoralPropertiesTest.php | 18 +++++-------- tests/Unit/Regimen/SetRegimenTest.php | 9 ++++--- 9 files changed, 47 insertions(+), 66 deletions(-) diff --git a/composer.json b/composer.json index 85c3a8a..65110b6 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "symfony/process": "^7.0" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^11.5" }, "prefer-stable": true, "autoload": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ab9a195..f28de6a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,16 +1,22 @@ + xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" + cacheDirectory="build/phpunit" + bootstrap="tests/bootstrap.php" + colors="true" + displayDetailsOnAllIssues="true" +> + + + + src + + + - - ./tests/ + + tests - - - ./src/ - - + diff --git a/tests/Integration/ScrapFromCsfFileTest.php b/tests/Integration/ScrapFromCsfFileTest.php index 11a081a..9d8c17f 100644 --- a/tests/Integration/ScrapFromCsfFileTest.php +++ b/tests/Integration/ScrapFromCsfFileTest.php @@ -14,6 +14,7 @@ use PhpCfdi\CsfScraper\Scraper; use PhpCfdi\CsfScraper\Tests\Integration\Helpers\ScraperHelper; use PhpCfdi\CsfScraper\Tests\TestCase; +use PHPUnit\Framework\Attributes\RequiresOperatingSystem; class ScrapFromCsfFileTest extends TestCase { @@ -68,9 +69,6 @@ public function test_scrap_from_idcif_and_rfc_by_moral(): void $this->assertEquals($expectedData, $data); } - /** - * @requires OSFAMILY Linux - */ public function test_obtain_from_pdf_with_invalid_data(): void { $csfScrap = new Scraper(new Client()); @@ -80,9 +78,7 @@ public function test_obtain_from_pdf_with_invalid_data(): void $csfScrap->obtainFromPdfPath($this->filePath('csf-correct-but-invalid.pdf')); } - /** - * @requires OSFAMILY Linux - */ + #[RequiresOperatingSystem('Linux')] public function test_obtain_from_pdf_without_rfc(): void { $csfScrap = new Scraper(new Client()); @@ -92,9 +88,7 @@ public function test_obtain_from_pdf_without_rfc(): void $csfScrap->obtainFromPdfPath($this->filePath('csf-without-rfc.pdf')); } - /** - * @requires OSFAMILY Linux - */ + #[RequiresOperatingSystem('Linux')] public function test_obtain_from_pdf_without_cif(): void { $csfScrap = new Scraper(new Client()); diff --git a/tests/Unit/PdfReader/CsfExtractor/GetRfcTest.php b/tests/Unit/PdfReader/CsfExtractor/GetRfcTest.php index 770cf0b..4e85641 100644 --- a/tests/Unit/PdfReader/CsfExtractor/GetRfcTest.php +++ b/tests/Unit/PdfReader/CsfExtractor/GetRfcTest.php @@ -7,6 +7,7 @@ use PhpCfdi\CsfScraper\Exceptions\PdfReader\EmptyPdfContentException; use PhpCfdi\CsfScraper\PdfReader\CsfExtractor; use PhpCfdi\CsfScraper\Tests\TestCase; +use PHPUnit\Framework\Attributes\RequiresOperatingSystem; class GetRfcTest extends TestCase { @@ -23,9 +24,7 @@ public function test_bad_content_returns_empty_rfc(): void $this->assertNull($rfc); } - /** - * @requires OSFAMILY Linux - */ + #[RequiresOperatingSystem('Linux')] public function test_cannot_read_content(): void { $this->expectException(EmptyPdfContentException::class); diff --git a/tests/Unit/PdfReader/PdfToText/PdfToTextConstructorTest.php b/tests/Unit/PdfReader/PdfToText/PdfToTextConstructorTest.php index 7a8038a..f70dd0c 100644 --- a/tests/Unit/PdfReader/PdfToText/PdfToTextConstructorTest.php +++ b/tests/Unit/PdfReader/PdfToText/PdfToTextConstructorTest.php @@ -6,13 +6,12 @@ use PhpCfdi\CsfScraper\PdfReader\PdfToText; use PhpCfdi\CsfScraper\Tests\TestCase; +use PHPUnit\Framework\Attributes\RequiresOperatingSystem; use RuntimeException; class PdfToTextConstructorTest extends TestCase { - /** - * @requires OSFAMILY Linux - */ + #[RequiresOperatingSystem('Linux')] public function test_pdftotext_is_installed_default_path(): void { $csfExtractor = new PdfToText(); diff --git a/tests/Unit/Persona/CommonPersonaPropertiesTest.php b/tests/Unit/Persona/CommonPersonaPropertiesTest.php index c883a27..104b9c3 100644 --- a/tests/Unit/Persona/CommonPersonaPropertiesTest.php +++ b/tests/Unit/Persona/CommonPersonaPropertiesTest.php @@ -8,6 +8,7 @@ use PhpCfdi\CsfScraper\PersonaMoral; use PhpCfdi\CsfScraper\Tests\TestCase; use PhpCfdi\CsfScraper\Tests\Unit\Persona\Traits\PersonaTrait; +use PHPUnit\Framework\Attributes\DataProvider; class CommonPersonaPropertiesTest extends TestCase { @@ -25,7 +26,7 @@ public function setUp(): void * * @return array> */ - public function datePropertiesProvider(): array + static public function datePropertiesProvider(): array { return [ ['FechaInicioOperaciones', '12-01-2017'], @@ -33,11 +34,8 @@ public function datePropertiesProvider(): array ]; } - /** - * - * @return array> - */ - public function stringPropertiesProvider(): array + /** @return array> */ + static public function stringPropertiesProvider(): array { return [ ['SituacionContribuyente', 'ACTIVO'], @@ -54,18 +52,14 @@ public function stringPropertiesProvider(): array ]; } - /** - * @dataProvider stringPropertiesProvider - */ + #[DataProvider('stringPropertiesProvider')] public function test_set_and_get_string_properties(string $complementFunction, string $value): void { $result = $this->setAndGetProperty($complementFunction, $value); $this->assertSame($value, $result); } - /** - * @dataProvider datePropertiesProvider - */ + #[DataProvider('datePropertiesProvider')] public function test_set_and_get_date_properties(string $complementFunction, string $value): void { $result = $this->setAndGetProperty($complementFunction, $value); diff --git a/tests/Unit/Persona/PersonaFisicaPropertiesTest.php b/tests/Unit/Persona/PersonaFisicaPropertiesTest.php index 5761aa9..748ec14 100644 --- a/tests/Unit/Persona/PersonaFisicaPropertiesTest.php +++ b/tests/Unit/Persona/PersonaFisicaPropertiesTest.php @@ -8,6 +8,7 @@ use PhpCfdi\CsfScraper\PersonaFisica; use PhpCfdi\CsfScraper\Tests\TestCase; use PhpCfdi\CsfScraper\Tests\Unit\Persona\Traits\PersonaTrait; +use PHPUnit\Framework\Attributes\DataProvider; class PersonaFisicaPropertiesTest extends TestCase { @@ -25,18 +26,15 @@ public function setUp(): void * * @return array> */ - public function datePropertiesProvider(): array + static public function datePropertiesProvider(): array { return [ ['FechaNacimiento', '16-05-1996'], ]; } - /** - * - * @return array> - */ - public function stringPropertiesProvider(): array + /** @return array> */ + static public function stringPropertiesProvider(): array { return [ ['Curp', 'MI CURP'], @@ -46,18 +44,14 @@ public function stringPropertiesProvider(): array ]; } - /** - * @dataProvider stringPropertiesProvider - */ + #[DataProvider('stringPropertiesProvider')] public function test_set_and_get_string_properties(string $complementFunction, string $value): void { $result = $this->setAndGetProperty($complementFunction, $value); $this->assertSame($value, $result); } - /** - * @dataProvider datePropertiesProvider - */ + #[DataProvider('datePropertiesProvider')] public function test_set_and_get_date_properties(string $complementFunction, string $value): void { $result = $this->setAndGetProperty($complementFunction, $value); diff --git a/tests/Unit/Persona/PersonaMoralPropertiesTest.php b/tests/Unit/Persona/PersonaMoralPropertiesTest.php index a49d96c..9e3c5a1 100644 --- a/tests/Unit/Persona/PersonaMoralPropertiesTest.php +++ b/tests/Unit/Persona/PersonaMoralPropertiesTest.php @@ -8,6 +8,7 @@ use PhpCfdi\CsfScraper\PersonaMoral; use PhpCfdi\CsfScraper\Tests\TestCase; use PhpCfdi\CsfScraper\Tests\Unit\Persona\Traits\PersonaTrait; +use PHPUnit\Framework\Attributes\DataProvider; class PersonaMoralPropertiesTest extends TestCase { @@ -25,18 +26,15 @@ public function setUp(): void * * @return array> */ - public function datePropertiesProvider(): array + static public function datePropertiesProvider(): array { return [ ['fechaConstitucion', '16-05-1996'], ]; } - /** - * - * @return array> - */ - public function stringPropertiesProvider(): array + /** @return array> */ + static public function stringPropertiesProvider(): array { return [ ['RazonSocial', 'MI TIENDITA'], @@ -44,18 +42,14 @@ public function stringPropertiesProvider(): array ]; } - /** - * @dataProvider stringPropertiesProvider - */ + #[DataProvider('stringPropertiesProvider')] public function test_set_and_get_string_properties(string $complementFunction, string $value): void { $result = $this->setAndGetProperty($complementFunction, $value); $this->assertSame($value, $result); } - /** - * @dataProvider datePropertiesProvider - */ + #[DataProvider('datePropertiesProvider')] public function test_set_and_get_date_properties(string $complementFunction, string $value): void { $result = $this->setAndGetProperty($complementFunction, $value); diff --git a/tests/Unit/Regimen/SetRegimenTest.php b/tests/Unit/Regimen/SetRegimenTest.php index 5b43177..a4657b9 100644 --- a/tests/Unit/Regimen/SetRegimenTest.php +++ b/tests/Unit/Regimen/SetRegimenTest.php @@ -6,6 +6,7 @@ use PhpCfdi\CsfScraper\Regimen; use PhpCfdi\CsfScraper\Tests\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; class SetRegimenTest extends TestCase { @@ -13,7 +14,7 @@ class SetRegimenTest extends TestCase * * @return array> */ - public function regimenesProvider(): array + static public function regimenesProvider(): array { return [ ['General de Ley Personas Morales', '601'], @@ -40,7 +41,7 @@ public function regimenesProvider(): array ]; } - /** @dataProvider regimenesProvider */ + #[DataProvider('regimenesProvider')] public function test_check_regimenes_are_well_assigned(string $regimenText, string $regimenIdExpected): void { $regimen = new Regimen(); @@ -92,7 +93,7 @@ public function test_fecha_alta_with_empty_value(): void } /** @return array */ - public function provider_fecha_alta_with_invalid_value(): array + static public function provider_fecha_alta_with_invalid_value(): array { return [ 'empty' => [''], @@ -101,7 +102,7 @@ public function provider_fecha_alta_with_invalid_value(): array ]; } - /** @dataProvider provider_fecha_alta_with_invalid_value */ + #[DataProvider('provider_fecha_alta_with_invalid_value')] public function test_fecha_alta_with_invalid_value(string $input): void { $regimen = new Regimen(); From 1672eb4686735e7a934fbcaf71a283f27b95160d Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 21:36:14 -0600 Subject: [PATCH 27/34] Review docblocks --- .github/workflows/build.yml | 2 +- .github/workflows/sonarqube-cloud.yml | 2 +- composer.json | 2 +- src/DataExtractor.php | 5 +---- src/Exceptions/PdfReader/PdfToTextConvertException.php | 4 +--- src/Interfaces/ScraperInterface.php | 5 +---- src/PdfReader/CsfExtractor.php | 4 +--- src/PersonaFisica.php | 5 +---- src/PersonaMoral.php | 5 +---- tests/Unit/Persona/CommonPersonaPropertiesTest.php | 10 +++------- tests/Unit/Persona/PersonaFisicaPropertiesTest.php | 9 +++------ tests/Unit/Persona/PersonaMoralPropertiesTest.php | 9 +++------ tests/Unit/Regimen/SetRegimenTest.php | 9 +++------ tests/Unit/ScraperTest.php | 3 --- 14 files changed, 21 insertions(+), 53 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d22d0c3..ee4fc23 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -158,4 +158,4 @@ jobs: - name: Install project dependencies run: composer upgrade --no-interaction --no-progress --prefer-dist - name: Tests (phpunit) - run: vendor/bin/phpunit --testdox --verbose + run: vendor/bin/phpunit --testdox diff --git a/.github/workflows/sonarqube-cloud.yml b/.github/workflows/sonarqube-cloud.yml index ffd67c2..9abdcbf 100644 --- a/.github/workflows/sonarqube-cloud.yml +++ b/.github/workflows/sonarqube-cloud.yml @@ -46,7 +46,7 @@ jobs: - name: Install project dependencies run: composer upgrade --no-interaction --no-progress --prefer-dist - name: Create code coverage - run: vendor/bin/phpunit --testdox --verbose --coverage-xml=build/coverage --coverage-clover=build/coverage/clover.xml --log-junit=build/coverage/junit.xml + run: vendor/bin/phpunit --testdox --coverage-xml=build/coverage --coverage-clover=build/coverage/clover.xml --log-junit=build/coverage/junit.xml - name: Prepare SonarCloud Code Coverage Files run: | sed 's#'$GITHUB_WORKSPACE'#/github/workspace#g' build/coverage/junit.xml > build/sonar-junit.xml diff --git a/composer.json b/composer.json index 65110b6..5d30dbc 100644 --- a/composer.json +++ b/composer.json @@ -78,7 +78,7 @@ ], "dev:test": [ "@dev:check-style", - "@php vendor/bin/phpunit --testdox --verbose --stop-on-failure", + "@php vendor/bin/phpunit --testdox --stop-on-failure", "@php tools/phpstan analyse --no-interaction --no-progress", "@php tools/composer-require-checker" ] diff --git a/src/DataExtractor.php b/src/DataExtractor.php index 5878b66..b47b591 100644 --- a/src/DataExtractor.php +++ b/src/DataExtractor.php @@ -15,9 +15,7 @@ public function __construct(private string $html) { } - /** - * @throws CifNotFoundException - */ + /** @throws CifNotFoundException */ public function extract(bool $isFisica): PersonaMoral|PersonaFisica { $html = $this->clearHtml($this->html); @@ -62,7 +60,6 @@ private function clearHtml(string $html): string } /** - * * @return Regimen[] * @throws RuntimeException */ diff --git a/src/Exceptions/PdfReader/PdfToTextConvertException.php b/src/Exceptions/PdfReader/PdfToTextConvertException.php index 5825f12..7424642 100644 --- a/src/Exceptions/PdfReader/PdfToTextConvertException.php +++ b/src/Exceptions/PdfReader/PdfToTextConvertException.php @@ -9,9 +9,7 @@ final class PdfToTextConvertException extends RuntimeException implements CsfScraperException { - /** - * @param string[] $command - */ + /** @param string[] $command */ public function __construct( string $message, private readonly array $command, diff --git a/src/Interfaces/ScraperInterface.php b/src/Interfaces/ScraperInterface.php index 733e306..a63684f 100644 --- a/src/Interfaces/ScraperInterface.php +++ b/src/Interfaces/ScraperInterface.php @@ -10,10 +10,7 @@ interface ScraperInterface { - /** - * Obtain a PersonaMoral or PersonaFisica object with the information from SAT website - * - */ + /** Obtain a PersonaMoral or PersonaFisica object with the information from SAT website */ public function obtainFromRfcAndCif(Rfc $rfc, string $idCIF): PersonaMoral|PersonaFisica; /** diff --git a/src/PdfReader/CsfExtractor.php b/src/PdfReader/CsfExtractor.php index 98449f0..6edc146 100644 --- a/src/PdfReader/CsfExtractor.php +++ b/src/PdfReader/CsfExtractor.php @@ -12,9 +12,7 @@ /** @var list */ private array $lines; - /** - * @throws EmptyPdfContentException - */ + /** @throws EmptyPdfContentException */ public function __construct(string $contents) { if ('' === $contents) { diff --git a/src/PersonaFisica.php b/src/PersonaFisica.php index ac3ef26..1822eba 100644 --- a/src/PersonaFisica.php +++ b/src/PersonaFisica.php @@ -69,10 +69,7 @@ public function setFechaNacimiento(string $fechaNacimiento): void $this->fechaNacimiento = false !== $date ? $date : null; } - /** - * - * @return array - */ + /** @return array */ public function getTdTitlesTextToSearch(): array { return [ diff --git a/src/PersonaMoral.php b/src/PersonaMoral.php index 817e945..e340004 100644 --- a/src/PersonaMoral.php +++ b/src/PersonaMoral.php @@ -45,10 +45,7 @@ public function setFechaConstitucion(string $fechaConstitucion): void $this->fechaConstitucion = false !== $date ? $date : null; } - /** - * - * @return array - */ + /** @return array */ public function getTdTitlesTextToSearch(): array { return [ diff --git a/tests/Unit/Persona/CommonPersonaPropertiesTest.php b/tests/Unit/Persona/CommonPersonaPropertiesTest.php index 104b9c3..fc53bd3 100644 --- a/tests/Unit/Persona/CommonPersonaPropertiesTest.php +++ b/tests/Unit/Persona/CommonPersonaPropertiesTest.php @@ -22,11 +22,8 @@ public function setUp(): void $this->person = new PersonaMoral(); } - /** - * - * @return array> - */ - static public function datePropertiesProvider(): array + /** @return array> */ + public static function datePropertiesProvider(): array { return [ ['FechaInicioOperaciones', '12-01-2017'], @@ -35,7 +32,7 @@ static public function datePropertiesProvider(): array } /** @return array> */ - static public function stringPropertiesProvider(): array + public static function stringPropertiesProvider(): array { return [ ['SituacionContribuyente', 'ACTIVO'], @@ -67,7 +64,6 @@ public function test_set_and_get_date_properties(string $complementFunction, str } /** - * * test to check if new property not contained in Persona is found is assigned and value can be retrieved * its goal is not to be used but to prevent unexpected exceptions * */ diff --git a/tests/Unit/Persona/PersonaFisicaPropertiesTest.php b/tests/Unit/Persona/PersonaFisicaPropertiesTest.php index 748ec14..4f12ace 100644 --- a/tests/Unit/Persona/PersonaFisicaPropertiesTest.php +++ b/tests/Unit/Persona/PersonaFisicaPropertiesTest.php @@ -22,11 +22,8 @@ public function setUp(): void $this->person = new PersonaFisica(); } - /** - * - * @return array> - */ - static public function datePropertiesProvider(): array + /** @return array> */ + public static function datePropertiesProvider(): array { return [ ['FechaNacimiento', '16-05-1996'], @@ -34,7 +31,7 @@ static public function datePropertiesProvider(): array } /** @return array> */ - static public function stringPropertiesProvider(): array + public static function stringPropertiesProvider(): array { return [ ['Curp', 'MI CURP'], diff --git a/tests/Unit/Persona/PersonaMoralPropertiesTest.php b/tests/Unit/Persona/PersonaMoralPropertiesTest.php index 9e3c5a1..947e772 100644 --- a/tests/Unit/Persona/PersonaMoralPropertiesTest.php +++ b/tests/Unit/Persona/PersonaMoralPropertiesTest.php @@ -22,11 +22,8 @@ public function setUp(): void $this->person = new PersonaMoral(); } - /** - * - * @return array> - */ - static public function datePropertiesProvider(): array + /** @return array> */ + public static function datePropertiesProvider(): array { return [ ['fechaConstitucion', '16-05-1996'], @@ -34,7 +31,7 @@ static public function datePropertiesProvider(): array } /** @return array> */ - static public function stringPropertiesProvider(): array + public static function stringPropertiesProvider(): array { return [ ['RazonSocial', 'MI TIENDITA'], diff --git a/tests/Unit/Regimen/SetRegimenTest.php b/tests/Unit/Regimen/SetRegimenTest.php index a4657b9..d6aae0c 100644 --- a/tests/Unit/Regimen/SetRegimenTest.php +++ b/tests/Unit/Regimen/SetRegimenTest.php @@ -10,11 +10,8 @@ class SetRegimenTest extends TestCase { - /** - * - * @return array> - */ - static public function regimenesProvider(): array + /** @return array> */ + public static function regimenesProvider(): array { return [ ['General de Ley Personas Morales', '601'], @@ -93,7 +90,7 @@ public function test_fecha_alta_with_empty_value(): void } /** @return array */ - static public function provider_fecha_alta_with_invalid_value(): array + public static function provider_fecha_alta_with_invalid_value(): array { return [ 'empty' => [''], diff --git a/tests/Unit/ScraperTest.php b/tests/Unit/ScraperTest.php index 723a69c..eda7abb 100644 --- a/tests/Unit/ScraperTest.php +++ b/tests/Unit/ScraperTest.php @@ -14,9 +14,6 @@ final class ScraperTest extends TestCase { public function test_create_with_specific_openssl_cipher_list(): void { - /** - * Problem: The scraper does not have a method to get the client, obtained by reflection - */ $scraper = Scraper::create(); $client = $scraper->getClient(); $this->assertInstanceOf(Client::class, $client); From 110a2189d843d9f7683e29e1db69c920bae31974 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 21:40:35 -0600 Subject: [PATCH 28/34] Use operating-system variable (singular) --- .github/workflows/build.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ee4fc23..f817611 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -123,11 +123,11 @@ jobs: run: phpstan analyse --no-progress --verbose tests: - name: PHP ${{ matrix.php-version }} on ${{ matrix.operating-systems }} - runs-on: ${{ matrix.operating-systems }} + name: PHP ${{ matrix.php-version }} on ${{ matrix.operating-system }} + runs-on: ${{ matrix.operating-system }} strategy: matrix: - operating-systems: ["windows-latest", "ubuntu-latest"] + operating-system: ["windows-latest", "ubuntu-latest"] php-version: ['8.2', '8.3', '8.4'] steps: - name: Checkout @@ -141,7 +141,7 @@ jobs: env: fail-fast: true - name: Install poppler-utils - if: matrix.operating-systems == 'ubuntu-latest' + if: matrix.operating-system == 'ubuntu-latest' run: | sudo apt-get update -y -qq sudo apt-get install -y poppler-utils From 295e6bb9c97e6bab0df0fd5e3788585661d42037 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 21:41:47 -0600 Subject: [PATCH 29/34] Prepare version 0.2.0 --- docs/CHANGELOG.md | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2fed717..39eca01 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,14 +9,34 @@ 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. -### Mantenimiento 2023-06-17 +## Listado de cambios -Sí, el mismo día de un *release*. +### Versión 0.2.0 2025-11-10 + +- Se asegura la compatibilidad con PHP 8.3 y PHP 8.4. +- Se elimina la compatibilidad con PHP 8.0 y PHP 8.1. +- Se actualiza el año de la licencia a 2025. + +Cambios al entorno de desarrollo: + +- Se corrige la integración con SonarQube Cloud. +- Se actualiza a PHPUnit 11.5. +- Se actualizan las configuraciones de estándar de código para `phpcs` y `php-cs-fixer`. +- Se agrega `composer-normalize` a las herramientas de desarrollo. +- En los flujos de trabajo: + - Se ejecutan los trabajos en PHP 8.4. + - Se agrega PHP 8.3 y PHP 8.4 a la matriz de pruebas. + - Se agrega el trabajo `composer-normalize`. + - Se ejecutan las acciones en la versión 4. + - Se usa la variable `php-version` en singular en la matriz de pruebas. + - Se usa la variable `operating-system` en singular en la matriz de pruebas. + - Se usa una única configuración para Linux o Windows al configurar PHP. +- Se actualizan las herramientas de desarrollo. -- Se agrega un último test para alcanzar el 100% de cobertura de código. -- Se corrige en este archivo, que "los flujos de trabajo corren en PHP 8.2", decía "PHP 8.0". +#### Mantenimiento 2023-06-17 -## Listado de cambios +- Se agrega un último test para alcanzar el 100% de cobertura de código. +- Se corrige en este archivo, que "los flujos de trabajo corren en PHP 8.2", decía "PHP 8.0". ### Versión 0.1.7 2024-01-10 From 7e8e4cd1b628154799183f01da4bd48d44ac2361 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 22:05:57 -0600 Subject: [PATCH 30/34] Catch `ClientExceptionInterface` instead of `GuzzleException` --- composer.json | 1 + docs/CHANGELOG.md | 3 +++ src/Scraper.php | 4 ++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 5d30dbc..3479612 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,7 @@ "ext-mbstring": "*", "guzzlehttp/guzzle": "^7.4", "phpcfdi/rfc": "^1.1", + "psr/http-client": "^1.0", "symfony/css-selector": "^7.0", "symfony/dom-crawler": "^7.0", "symfony/process": "^7.0" diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 39eca01..4c8f56d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -16,6 +16,9 @@ versión, aunque sí su incorporación en la rama principal de trabajo, generalm - Se asegura la compatibilidad con PHP 8.3 y PHP 8.4. - Se elimina la compatibilidad con PHP 8.0 y PHP 8.1. - Se actualiza el año de la licencia a 2025. +- No se estaban capturando correctamente las extensiones al intentar descargar la información de identificación fiscal, + se estaba atrapando la excepción `GuzzleHttp\Exception\GuzzleException` en lugar de la excepción estándar + `Psr\Http\Client\ClientExceptionInterface`. Cambios al entorno de desarrollo: diff --git a/src/Scraper.php b/src/Scraper.php index 1abef9d..b99d858 100644 --- a/src/Scraper.php +++ b/src/Scraper.php @@ -6,7 +6,6 @@ use GuzzleHttp\Client; use GuzzleHttp\ClientInterface; -use GuzzleHttp\Exception\GuzzleException; use PhpCfdi\CsfScraper\Exceptions\PdfReader\CifFromPdfNotFoundException; use PhpCfdi\CsfScraper\Exceptions\PdfReader\RfcFromPdfNotFoundException; use PhpCfdi\CsfScraper\Interfaces\ScraperInterface; @@ -14,6 +13,7 @@ use PhpCfdi\CsfScraper\PdfReader\PdfToText; use PhpCfdi\Rfc\Exceptions\InvalidExpressionToParseException; use PhpCfdi\Rfc\Rfc; +use Psr\Http\Client\ClientExceptionInterface; /** * Main class to obtain the data from a "Persona Moral" or a "Persona Física" from SAT website @@ -103,7 +103,7 @@ protected function obtainHtml(string $uri): string { try { $request = $this->client->request('GET', $uri); - } catch (GuzzleException $exception) { + } catch (ClientExceptionInterface $exception) { throw new Exceptions\CifDownloadException($uri, $exception); } return (string) $request->getBody(); From 8d9dcaae111e6436080847c41a252033ed5d5cac Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 22:14:30 -0600 Subject: [PATCH 31/34] Use Scraper::create() When use new Scraper(new Client()) it could return an invalid error. --- tests/Integration/ScrapFromCsfFileTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Integration/ScrapFromCsfFileTest.php b/tests/Integration/ScrapFromCsfFileTest.php index 9d8c17f..51d6276 100644 --- a/tests/Integration/ScrapFromCsfFileTest.php +++ b/tests/Integration/ScrapFromCsfFileTest.php @@ -71,7 +71,7 @@ public function test_scrap_from_idcif_and_rfc_by_moral(): void public function test_obtain_from_pdf_with_invalid_data(): void { - $csfScrap = new Scraper(new Client()); + $csfScrap = Scraper::create(); $this->expectException(CifDownloadException::class); @@ -81,7 +81,7 @@ public function test_obtain_from_pdf_with_invalid_data(): void #[RequiresOperatingSystem('Linux')] public function test_obtain_from_pdf_without_rfc(): void { - $csfScrap = new Scraper(new Client()); + $csfScrap = Scraper::create(); $this->expectException(RfcFromPdfNotFoundException::class); @@ -91,7 +91,7 @@ public function test_obtain_from_pdf_without_rfc(): void #[RequiresOperatingSystem('Linux')] public function test_obtain_from_pdf_without_cif(): void { - $csfScrap = new Scraper(new Client()); + $csfScrap = Scraper::create(); $this->expectException(CifFromPdfNotFoundException::class); From 5c68197256f2c77873e9622ae4aee1b0e95ccbcc Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 22:16:59 -0600 Subject: [PATCH 32/34] Use correct variable name `$response` --- src/Scraper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Scraper.php b/src/Scraper.php index b99d858..3e46d55 100644 --- a/src/Scraper.php +++ b/src/Scraper.php @@ -102,10 +102,10 @@ protected function pdfToTextContent(string $path): string protected function obtainHtml(string $uri): string { try { - $request = $this->client->request('GET', $uri); + $response = $this->client->request('GET', $uri); } catch (ClientExceptionInterface $exception) { throw new Exceptions\CifDownloadException($uri, $exception); } - return (string) $request->getBody(); + return (string) $response->getBody(); } } From 5e4542690c91c36fbb5de79fa401130c838d3735 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 22:22:43 -0600 Subject: [PATCH 33/34] Expect correct exception CfdiNotFoundException It was not CfdiDownloadException --- tests/Integration/ScrapFromCsfFileTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Integration/ScrapFromCsfFileTest.php b/tests/Integration/ScrapFromCsfFileTest.php index 51d6276..163fb3f 100644 --- a/tests/Integration/ScrapFromCsfFileTest.php +++ b/tests/Integration/ScrapFromCsfFileTest.php @@ -9,6 +9,7 @@ use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\Psr7\Response; use PhpCfdi\CsfScraper\Exceptions\CifDownloadException; +use PhpCfdi\CsfScraper\Exceptions\CifNotFoundException; use PhpCfdi\CsfScraper\Exceptions\PdfReader\CifFromPdfNotFoundException; use PhpCfdi\CsfScraper\Exceptions\PdfReader\RfcFromPdfNotFoundException; use PhpCfdi\CsfScraper\Scraper; @@ -73,7 +74,7 @@ public function test_obtain_from_pdf_with_invalid_data(): void { $csfScrap = Scraper::create(); - $this->expectException(CifDownloadException::class); + $this->expectException(CifNotFoundException::class); $csfScrap->obtainFromPdfPath($this->filePath('csf-correct-but-invalid.pdf')); } From d30383ad6686e3c6c24ec06231c954b47889c609 Mon Sep 17 00:00:00 2001 From: Carlos C Soto Date: Mon, 10 Nov 2025 22:23:54 -0600 Subject: [PATCH 34/34] Test CifDownloadException --- src/Scraper.php | 1 + tests/Integration/ScrapFromCsfFileTest.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Scraper.php b/src/Scraper.php index 3e46d55..8d28be3 100644 --- a/src/Scraper.php +++ b/src/Scraper.php @@ -61,6 +61,7 @@ public function obtainFromRfcAndCif(Rfc $rfc, string $idCIF): PersonaMoral|Perso * Obtain a PersonaMoral or PersonaFisica object with the information from SAT website * The RFC and CIF is taken from the "Constancia de Situación Fiscal" PDF file * + * @throws Exceptions\CifDownloadException * @throws Exceptions\CifNotFoundException * @throws CifFromPdfNotFoundException * @throws Exceptions\PdfReader\EmptyPdfContentException diff --git a/tests/Integration/ScrapFromCsfFileTest.php b/tests/Integration/ScrapFromCsfFileTest.php index 163fb3f..a363dee 100644 --- a/tests/Integration/ScrapFromCsfFileTest.php +++ b/tests/Integration/ScrapFromCsfFileTest.php @@ -70,6 +70,20 @@ public function test_scrap_from_idcif_and_rfc_by_moral(): void $this->assertEquals($expectedData, $data); } + public function test_obtain_from_pdf_with_invalid_url(): void + { + $previousUrl = Scraper::$url; + Scraper::$url = str_replace('siat.sat.gob.mx', 'sat.gob.mx', $previousUrl); + + try { + $csfScrap = Scraper::create(); + $this->expectException(CifDownloadException::class); + $csfScrap->obtainFromPdfPath($this->filePath('csf-correct-but-invalid.pdf')); + } finally { + Scraper::$url = $previousUrl; + } + } + public function test_obtain_from_pdf_with_invalid_data(): void { $csfScrap = Scraper::create();