Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/validators.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ In this page you will find a list of validators by their category.
[Charset]: validators/Charset.md "Validates if a string is in a specific charset."
[Circuit]: validators/Circuit.md "Validates the input against a series of validators until the first fails."
[Cnh]: validators/Cnh.md "Validates a Brazilian driver's license."
[Cnpj]: validators/Cnpj.md "Validates if the input is a Brazilian National Registry of Legal Entities (CNPJ) number."
[Cnpj]: validators/Cnpj.md "Validates the structure and mathematical integrity of Brazilian CNPJ identifiers."
[Consonant]: validators/Consonant.md "Validates if the input contains only consonants."
[Contains]: validators/Contains.md "Validates if the input contains some value."
[ContainsAny]: validators/ContainsAny.md "Validates if the input contains at least one of defined values"
Expand Down
5 changes: 4 additions & 1 deletion docs/validators/Cnpj.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ SPDX-License-Identifier: MIT

- `Cnpj()`

Validates if the input is a Brazilian National Registry of Legal Entities (CNPJ) number.
Validates the structure and mathematical integrity of Brazilian [CNPJ](https://pt.wikipedia.org/wiki/Cadastro_Nacional_da_Pessoa_Jur%C3%ADdica) identifiers.
Ignores non-digit chars, so use `->digit()` if needed.

```php
v::cnpj()->assert('00394460005887');
// Validation passes successfully

v::cnpj()->assert('12ABC34501DE35');
// Validation passes successfully
```

## Templates
Expand Down
27 changes: 20 additions & 7 deletions src/Validators/Cnpj.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
use function array_sum;
use function count;
use function is_scalar;
use function ord;
use function preg_replace;
use function str_split;
use function strtoupper;

#[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)]
#[Template(
Expand All @@ -34,6 +36,8 @@
)]
final class Cnpj extends Simple
{
private const int BASE_ASCII = 48;

public function isValid(mixed $input): bool
{
if (!is_scalar($input)) {
Expand All @@ -42,7 +46,8 @@ public function isValid(mixed $input): bool

// Code ported from jsfromhell.com
$bases = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
$digits = $this->getDigits((string) $input);
$chars = $this->getChars((string) $input);
$digits = $this->transformToAscii($chars);

if (array_sum($digits) < 1) {
return false;
Expand Down Expand Up @@ -71,14 +76,22 @@ public function isValid(mixed $input): bool
return $digits[13] == $check;
}

/** @return int[] */
private function getDigits(string $input): array
/** @return string[] */
private function getChars(string $input): array
{
return str_split((string) preg_replace('/[\W_]/', '', strtoupper($input)));
}

/**
* @param array<string> $input
*
* @return int[]
*/
private function transformToAscii(array $input): array
{
return array_map(
'intval',
str_split(
(string) preg_replace('/\D/', '', $input),
),
static fn(string $character) => ord($character) - self::BASE_ASCII,
$input,
);
}
}
5 changes: 5 additions & 0 deletions tests/unit/Validators/CnpjTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ public static function providerForValidInput(): iterable
[$validator, '24.760.428/0001-09'],
[$validator, '27.355.204/0001-00'],
[$validator, '36.310.327/0001-07'],
[$validator, '12.ABC.345/01DE-35'],
[$validator, '12.ABC.345/01DE_35'],
[$validator, '38175021000110'],
[$validator, '37550610000179'],
[$validator, '12774546000189'],
[$validator, '77456211000168'],
[$validator, '02023077000102'],
[$validator, '12ABC34501DE35'],
];
}

Expand Down Expand Up @@ -75,6 +78,8 @@ public static function providerForInvalidInput(): iterable
[$validator, '992999999999929384'],
[$validator, '99-010-0.'],
[$validator, null],
[$validator, '12ABC34501DE00'],
[$validator, '12ABC34501DEFG'],
];
}
}