diff --git a/CHANGELOG.md b/CHANGELOG.md index 78d7371..e710f38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ A partir da versão 3.5.1 nosso modelo de logs é baseado em [mantenha um changelog](https://keepachangelog.com/pt-BR/1.0.0/) e o nosso versionamento continua sendo [versionamento semântico](https://semver.org/lang/pt-BR/). +## [3.7.0](https://github.com/geekcom/validator-docs/compare/3.6.0...3.7.0) + +## Novidades + +- Atualizado: + - As regras de validação de RENAVAM foram reescritas; + - Os testes de validação de RENAVAM foram atualizados. + + ## [3.6.0](https://github.com/geekcom/validator-docs/compare/3.5.3...3.6.0) ## Novidades diff --git a/README.md b/README.md index 120b5ae..92ae655 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ _Biblioteca PHP para validação de documentos do Brasil usando **Laravel**_ ![Build Status](https://github.com/geekcom/validator-docs/actions/workflows/proposing-changes.yml/badge.svg) -[![Coverage Status](https://coveralls.io/repos/github/geekcom/validator-docs/badge.svg?branch=master)](https://coveralls.io/github/geekcom/validator-docs?branch=master) +[![Coverage Status](https://coveralls.io/repos/github/geekcom/validator-docs/badge.svg)](https://coveralls.io/github/geekcom/validator-docs) [![PHPStan](https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat)](https://github.com/phpstan/phpstan) [![Total Downloads](https://poser.pugx.org/geekcom/validator-docs/downloads)](https://packagist.org/packages/geekcom/validator-docs) [![License](https://poser.pugx.org/geekcom/validator-docs/license)](https://packagist.org/packages/geekcom/validator-docs) diff --git a/composer.json b/composer.json index 34a9c9a..4acf468 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "geekcom/validator-docs", - "description": "Biblioteca para validação de Título de Eleitor, CPF, CNPJ, NIS e CNH", + "description": "Biblioteca PHP para validação de documentos do Brasil usando Laravel", "license": "MIT", "authors": [ { diff --git a/src/validator-docs/Rules/Renavam.php b/src/validator-docs/Rules/Renavam.php index aa7a682..7e8ccd1 100644 --- a/src/validator-docs/Rules/Renavam.php +++ b/src/validator-docs/Rules/Renavam.php @@ -6,27 +6,112 @@ class Renavam extends Sanitization { + /** + * The renavam string size. + */ + protected const RENAVAM_SIZE = 11; + + /** + * Validate the renavam. + * + * @param $attribute + * @param $renavam + * @return bool + */ public function validateRenavam($attribute, $renavam): bool { $renavam = $this->sanitize((string) $renavam); - $renavamArray = str_split($renavam); - $digit = $this->determinarDigito($renavamArray); + if (!$this->renavamHasCorrectLength($renavam)) { + return false; + } + + $realLastDigit = $this->getRealLastDigit($renavam); + $informedLastDigit = (int) substr($renavam, strlen($renavam) - 1, strlen($renavam)); + + return $realLastDigit === $informedLastDigit; + } + + + /** + * Sanitize the renavam value. + * + * @param $value + * @return string + */ + public function sanitize($value): string + { + $renavam = parent::sanitize((string) $value); + if (preg_match("/^([0-9]{9})$/", $renavam)) { + $renavam = '00' . $renavam; + } + + if (preg_match("/^([0-9]{10})$/", $renavam)) { + $renavam = '0' . $renavam; + } + + return $renavam; + } + + /** + * Check if renavam has correct length. + * + * @param string $renavam + * @return bool + */ + protected function renavamHasCorrectLength(string $renavam): bool + { + return !!preg_match("/[0-9]{11}/", $renavam); + } + + /** + * Get the real last digit calculated. + * + * @param string $renavam + * @return int + */ + private function getRealLastDigit(string $renavam): int + { + $renavamReverseWithoutDigit = $this->sanitizeToReverseWithoutDigit($renavam); + $sum = $this->calcSumByRenavamReverseWithoutDigit($renavamReverseWithoutDigit); + + $mod11 = $sum % self::RENAVAM_SIZE; + $lastDigitCalculated = self::RENAVAM_SIZE - $mod11; + + return $lastDigitCalculated >= 10 ? 0 : $lastDigitCalculated; + } + + /** + * Sanitize the renavam to without digit. + * + * @param string $renavam + * @return string + */ + protected function sanitizeToReverseWithoutDigit(string $renavam): string + { + $renavamWithoutDigit = substr($renavam, 0, 10); - return $digit === (int) $renavamArray[4]; + return strrev($renavamWithoutDigit); } - public function determinarDigito($renavam): int + /** + * Calculate the sum value by renavam reverse without digit. + * + * @param string $renavamReverseWithoutDigit + * @return int + */ + protected function calcSumByRenavamReverseWithoutDigit(string $renavamReverseWithoutDigit): int { - $resultante = 0; - $contador = 0; + $sum = 0; - for ($indice = 5; $indice >= 2; $indice--) { - $resultante += $renavam[$contador] * $indice; - $contador++; + for ($i = 0; $i < 8; $i++) { + $numeral = (int) substr($renavamReverseWithoutDigit, $i, 1); + $multiplier = $i + 2; + $sum += $numeral * $multiplier; } - $verificador = $resultante % 11; + $sum += $renavamReverseWithoutDigit[8] * 2; + $sum += $renavamReverseWithoutDigit[9] * 3; - return $verificador >= 10 ? 0 : $verificador; + return $sum; } } diff --git a/tests/Rules/RenavamTest.php b/tests/Rules/RenavamTest.php index d98d212..7531f88 100644 --- a/tests/Rules/RenavamTest.php +++ b/tests/Rules/RenavamTest.php @@ -18,20 +18,24 @@ public function renavamValido($renavam, $esperado): void $atual = $instance->validateRenavam('', $renavam); - $this->assertSame($esperado, $atual); + $this->assertSame($esperado, $atual, $renavam); } public function renavamProvider(): array { - return [ - 'Input correto' => [ - 'renavam' => 639884962, - 'esperado' => true, - ], - 'Input incorreto' => [ - 'renavam' => 11111111111, - 'esperado' => false - ], - ]; + $correctValues = [32094074362, 23478829239, 34145742746, 41833820181, 639884962]; + $wrongValues = [11111111111, 32094074212, 62128843267]; + + return array_reduce( + array_merge($correctValues, $wrongValues), + function ($acc, $value) use ($correctValues) { + $key = "Renavam " . $value; + $testProperties = ['renavam' => $value, 'esperado' => in_array($value, $correctValues)]; + + $acc[$key] = $testProperties; + return $acc; + }, + [] + ); } }