Skip to content

[v3][cpf-dv] Create cpf-dv package for CPF check digit calculation#36

Merged
juliolmuller merged 16 commits intomainfrom
feat/cpf-dv
Mar 21, 2026
Merged

[v3][cpf-dv] Create cpf-dv package for CPF check digit calculation#36
juliolmuller merged 16 commits intomainfrom
feat/cpf-dv

Conversation

@juliolmuller
Copy link
Collaborator

@juliolmuller juliolmuller commented Mar 20, 2026

Summary by CodeRabbit

  • New Features

    • Added a new cpf-dv package to compute Brazilian CPF check digits with flexible input, sanitization, lazy/cached property access, and exposed length constants.
  • Documentation

    • Added README (EN/PT), changelog and license for the new package.
  • Tests

    • Added comprehensive test suite and test utilities validating parsing, errors, caching, and outputs.
  • Chores

    • CI updated to drop PHP 8.1 and include PHP 8.2–8.5; test matrix expanded to cover the new package.

@juliolmuller juliolmuller requested a review from a team as a code owner March 20, 2026 20:21
@coderabbitai
Copy link

coderabbitai bot commented Mar 20, 2026

📝 Walkthrough

Walkthrough

Adds a new PHP package lacus/cpf-dv providing CPF check-digit computation (class, exceptions, constants), documentation (EN/PT), tests, CI matrix update to include cpf-dv, and minor PHPStan and README CI-version adjustments.

Changes

Cohort / File(s) Summary
CI & Project Config
\.github/workflows/ci.yml, phpstan.neon
Removed PHP 8.1 from CI matrices; added cpf-dv to test package matrix; set treatPhpDocTypesAsCertain: false in PHPStan ignore config.
New Package: Source & Constants
packages/cpf-dv/src/CpfCheckDigits.php, packages/cpf-dv/src/cpf-dv.php
Added CpfCheckDigits class with string/array input parsing, sanitization, 9–11 digit validation, repeated-digit rejection, modulo‑11 check-digit calculation, lazy cached properties (first,second,both,cpf); exported CPF_MIN_LENGTH/CPF_MAX_LENGTH constants.
New Package: Exceptions
packages/cpf-dv/src/Exceptions/...
Introduced exception hierarchy: abstract base CpfCheckDigitsException, abstract CpfCheckDigitsTypeError (extends TypeError) and concrete exceptions CpfCheckDigitsInputTypeError, CpfCheckDigitsInputLengthException, CpfCheckDigitsInputInvalidException with contextual public properties and formatted messages.
Package Metadata & Test Config
packages/cpf-dv/composer.json, packages/cpf-dv/phpunit.xml
Added Composer manifest (PSR‑4 autoload, php ^8.2, dependency on lacus/utils), Pest/PHPUnit scripts and PHPUnit config for test discovery and coverage.
Documentation & License
packages/cpf-dv/README.md, packages/cpf-dv/README.pt.md, packages/cpf-dv/CHANGELOG.md, packages/cpf-dv/LICENSE
Added English and Portuguese READMEs, changelog (1.0.0), and MIT license file documenting usage, inputs, errors, constants, and algorithm.
Tests & Test Helpers
packages/cpf-dv/tests/...
Added comprehensive Pest specs covering constructor validation, exceptions, computed check digits, caching (spy), constants exposure, and package surface; included test spy and Pest bootstrap.
Docs Badge Update
packages/utils/README.md
Added PHP 8.5 badge/status to utils README test table.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Poem

🐰 I hop through digits, nine then two,

I strip the dots and find what's true.
I cache the sums, compute with glee,
First and second — all eleven, see!
A tiny rabbit, happy with CPF.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately describes the primary change: creating a new cpf-dv package for CPF check digit calculation, which is the main focus of this changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cpf-dv

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can scan for known vulnerabilities in your dependencies using OSV Scanner.

OSV Scanner will automatically detect and report security vulnerabilities in your project's dependencies. No additional configuration is required.

@juliolmuller juliolmuller linked an issue Mar 20, 2026 that may be closed by this pull request
6 tasks
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cpf-dv/README.pt.md`:
- Around line 1-5: Add a top-level H1 heading to the README before the existing
image to satisfy markdownlint MD041 and improve navigability; update the
README.pt.md by inserting an H1 (e.g., "# cpf-dv para PHP" or similar Portuguese
title) at the top so the file begins with a heading rather than an image.

In `@packages/cpf-dv/src/cpf-dv.php`:
- Around line 11-17: Remove the duplicated namespace constants CPF_MIN_LENGTH
and CPF_MAX_LENGTH and update any code in this file to reference the canonical
class constants on CpfCheckDigits (use CpfCheckDigits::CPF_MIN_LENGTH and
CpfCheckDigits::CPF_MAX_LENGTH) so the values can’t drift; locate the constants
defined in this file and all usages and replace them with references to the
CpfCheckDigits class constants.

In `@packages/cpf-dv/src/CpfCheckDigits.php`:
- Around line 163-166: The thrown CpfCheckDigitsInputTypeError inside the
foreach over $cpfArray currently passes 'string' as the expected type but should
indicate an array of strings; update the error construction in the loop (where
foreach ($cpfArray as $item) triggers throw new
CpfCheckDigitsInputTypeError($cpfArray, 'string')) to pass 'string[]' instead so
the error accurately reflects that array members must be strings.

In `@packages/cpf-dv/src/Exceptions/CpfCheckDigitsInputInvalidException.php`:
- Around line 22-24: Align the indentation for the ternary assignment to match
the project's 4-space style: update the lines that set $fmtActual (the ternary
using is_string($actualInput) ? "\"{$actualInput}\"" : json_encode($actualInput,
JSON_THROW_ON_ERROR);) so the continuation line(s) use 4-space indentation
instead of 2-space, ensuring the formatting of the $fmtActual assignment in
CpfCheckDigitsInputInvalidException is consistent with the rest of the file.

In `@packages/cpf-dv/src/Exceptions/CpfCheckDigitsInputLengthException.php`:
- Around line 29-31: The indentation in CpfCheckDigitsInputLengthException
around the $fmtActual assignment is inconsistent; update the block in the
CpfCheckDigitsInputLengthException class (the ternary assignment that sets
$fmtActual using is_string($actualInput) ? "\"{$actualInput}\"" :
json_encode(...)) to match the project's 4-space indentation style used in
CpfCheckDigitsInputInvalidException so the lines align consistently with
surrounding code.

In `@packages/cpf-dv/tests/Mocks/CpfCheckDigitsWithCalculateSpy.php`:
- Around line 13-16: Remove the no-op constructor from the
CpfCheckDigitsWithCalculateSpy class: the __construct(mixed $cpfInput) method
only calls parent::__construct($cpfInput) and adds no behavior, so delete this
constructor so the spy inherits the parent's constructor directly; update any
instantiation calls if they rely on type hints (they shouldn't) and run the
tests to ensure no regressions.

In `@packages/cpf-dv/tests/Pest.php`:
- Line 13: The Pest bootstrap uses the wrong constant when building the specs
path: in the uses(TestCase::class)->in(__DIR__ . PATH_SEPARATOR . 'Specs') call
replace PATH_SEPARATOR with DIRECTORY_SEPARATOR so the filesystem path is
constructed correctly (uses(TestCase::class)->in(__DIR__ . DIRECTORY_SEPARATOR .
'Specs')), ensuring Pest can discover specs across platforms.

In `@packages/cpf-dv/tests/Specs/CpfCheckDigits.spec.php`:
- Around line 324-342: Add a spec that asserts CpfCheckDigits->__get throws when
an unknown magic property is accessed: create a new it() under the existing
"edge cases" describe block which instantiates new CpfCheckDigits('123456789')
and then wraps an access like $cpfCheckDigits->nonexistentProperty in a closure
and expects that invoking the closure throws an exception (matching whatever
exception type CpfCheckDigits::__get currently throws); reference the
CpfCheckDigits class and its __get method in the test so the behavior is
explicitly covered.

In `@packages/utils/README.md`:
- Around line 12-14: The README's test status table still lists a "PHP 8.1"
column as Passing, but the CI matrix key php-versions no longer includes 8.1;
update to keep them consistent by either removing the PHP 8.1 column from the
test status table in the README or re-adding "8.1" to the php-versions matrix in
the CI workflow (adjust the test badges/row entries accordingly so the table
accurately reflects the CI matrix).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ea8f4376-e84a-4019-a49d-c6a191b1e3ec

📥 Commits

Reviewing files that changed from the base of the PR and between 071c6da and 8c96008.

📒 Files selected for processing (21)
  • .github/workflows/ci.yml
  • packages/cpf-dv/CHANGELOG.md
  • packages/cpf-dv/LICENSE
  • packages/cpf-dv/README.md
  • packages/cpf-dv/README.pt.md
  • packages/cpf-dv/composer.json
  • packages/cpf-dv/phpunit.xml
  • packages/cpf-dv/src/CpfCheckDigits.php
  • packages/cpf-dv/src/Exceptions/CpfCheckDigitsException.php
  • packages/cpf-dv/src/Exceptions/CpfCheckDigitsInputInvalidException.php
  • packages/cpf-dv/src/Exceptions/CpfCheckDigitsInputLengthException.php
  • packages/cpf-dv/src/Exceptions/CpfCheckDigitsInputTypeError.php
  • packages/cpf-dv/src/Exceptions/CpfCheckDigitsTypeError.php
  • packages/cpf-dv/src/cpf-dv.php
  • packages/cpf-dv/tests/Mocks/CpfCheckDigitsWithCalculateSpy.php
  • packages/cpf-dv/tests/Pest.php
  • packages/cpf-dv/tests/Specs/CpfCheckDigits.spec.php
  • packages/cpf-dv/tests/Specs/Exceptions.spec.php
  • packages/cpf-dv/tests/Specs/Package.spec.php
  • packages/utils/README.md
  • phpstan.neon

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packages/cpf-dv/src/CpfCheckDigits.php (1)

163-166: ⚠️ Potential issue | 🟡 Minor

Use string[] as expected type for invalid array members.

On Line 165, this branch is validating array elements, so reporting expected type as string[] is more accurate than string or string[].

Proposed fix
-                throw new CpfCheckDigitsInputTypeError($cpfArray, 'string or string[]');
+                throw new CpfCheckDigitsInputTypeError($cpfArray, 'string[]');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cpf-dv/src/CpfCheckDigits.php` around lines 163 - 166, The error
message passed to CpfCheckDigitsInputTypeError inside the foreach validation
loop is incorrect: update the expected-type string argument from 'string or
string[]' to 'string[]' where CpfCheckDigitsInputTypeError($cpfArray, 'string or
string[]') is thrown in the foreach ($cpfArray as $item) block so the reported
expected type reflects that array members must be strings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/cpf-dv/src/CpfCheckDigits.php`:
- Around line 163-166: The error message passed to CpfCheckDigitsInputTypeError
inside the foreach validation loop is incorrect: update the expected-type string
argument from 'string or string[]' to 'string[]' where
CpfCheckDigitsInputTypeError($cpfArray, 'string or string[]') is thrown in the
foreach ($cpfArray as $item) block so the reported expected type reflects that
array members must be strings.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 811a4237-5a99-4ebf-b125-1c87beab1ab8

📥 Commits

Reviewing files that changed from the base of the PR and between 8c96008 and fec5272.

📒 Files selected for processing (5)
  • packages/cpf-dv/src/CpfCheckDigits.php
  • packages/cpf-dv/src/Exceptions/CpfCheckDigitsInputInvalidException.php
  • packages/cpf-dv/src/Exceptions/CpfCheckDigitsInputLengthException.php
  • packages/cpf-dv/tests/Mocks/CpfCheckDigitsWithCalculateSpy.php
  • packages/cpf-dv/tests/Pest.php

@juliolmuller juliolmuller merged commit ae7be7e into main Mar 21, 2026
98 of 99 checks passed
@juliolmuller juliolmuller deleted the feat/cpf-dv branch March 21, 2026 14:03
juliolmuller added a commit that referenced this pull request Mar 21, 2026
juliolmuller added a commit that referenced this pull request Mar 21, 2026
juliolmuller added a commit that referenced this pull request Mar 21, 2026
juliolmuller added a commit that referenced this pull request Mar 21, 2026
juliolmuller added a commit that referenced this pull request Mar 21, 2026
@juliolmuller juliolmuller added the enhancement New minor or major features. label Mar 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New minor or major features.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create cpf-dv

1 participant