diff --git a/README.md b/README.md index cd73fa7..8e206a1 100644 --- a/README.md +++ b/README.md @@ -32,11 +32,14 @@ $ php artisan vendor:publish --provider="Matmper\Providers\ValidationProvider" # Usage -| Name | Validation | Description | -|---|---|---| -| DOCUMENT| document | validate CPF or CNPJ value, ignore non numeric char | -| - | document:cpf | validate CPF value, ignore non numeric char | -| - | document:cpf,mask | validate CPF value and format (000.000.000-00) | +| Validation | Description | +|---|---| +| cep | validates CEP value, ignore non numeric char | +| cep:mask | validates CEP value and format (00000-000) | +| document | validates CPF or CNPJ value, ignore non numeric char | +| document:cpf | validates CPF value, ignore non numeric char | +| document:cpf,mask | validates CPF value and format (000.000.000-00) | +| not_html | validates that the string does not contain html | **Example** ```php @@ -45,7 +48,7 @@ $ php artisan vendor:publish --provider="Matmper\Providers\ValidationProvider" // 00000000000000 -> true // 00.000.000/0000-00 -> true return ['document_number' => 'document']; -return ['document_number' => 'document:cpf|cnpj']; +return ['document_number' => 'document:cpf.cnpj']; // 00000000000 -> true // 000.000.000-00 -> true @@ -58,6 +61,10 @@ return ['cpf' => 'document:cpf']; // 00000000000000 -> false // 00.000.000/0000-00 -> true return ['cnpj' => 'document:cnpj,mask']; + +// hello world -> true +//

hello world

-> false +return ['content' => 'string|not_html']; ``` | laravel-brazil-validation version | Laravel versions | diff --git a/src/Exceptions/InvalidDocumentTypeException.php b/src/Exceptions/InvalidDocumentTypeException.php index 9ce18c1..ecd01d2 100644 --- a/src/Exceptions/InvalidDocumentTypeException.php +++ b/src/Exceptions/InvalidDocumentTypeException.php @@ -10,18 +10,17 @@ class InvalidDocumentTypeException extends Exception { -/** - * @param string|null $message - * @param int $code - * @param Throwable|null $previous - */ + /** + * @param string|null $message + * @param int $code + * @param Throwable|null $previous + */ public function __construct( string $message = null, - int $code = 0, + int $code = Response::HTTP_NOT_FOUND, Throwable $previous = null, ) { $message = "Invalid document type for validation: {$message}"; - $code = $code ? $code : Response::HTTP_NOT_FOUND; parent::__construct($message, $code, $previous); } diff --git a/src/Exceptions/InvalidValidationParameterException.php b/src/Exceptions/InvalidValidationParameterException.php index 726517f..42b8055 100644 --- a/src/Exceptions/InvalidValidationParameterException.php +++ b/src/Exceptions/InvalidValidationParameterException.php @@ -10,18 +10,17 @@ class InvalidValidationParameterException extends Exception { -/** - * @param string|null $message - * @param int $code - * @param Throwable|null $previous - */ + /** + * @param string|null $message + * @param int $code + * @param Throwable|null $previous + */ public function __construct( string $message = null, - int $code = 0, + int $code = Response::HTTP_NOT_ACCEPTABLE, Throwable $previous = null, ) { $message = "Validation parameter is invalid: {$message}"; - $code = $code ? $code : Response::HTTP_NOT_ACCEPTABLE; parent::__construct($message, $code, $previous); } diff --git a/src/Exceptions/ValueIsNotStringException.php b/src/Exceptions/ValueIsNotStringException.php new file mode 100644 index 0000000..44d67b4 --- /dev/null +++ b/src/Exceptions/ValueIsNotStringException.php @@ -0,0 +1,27 @@ + \Matmper\Rules\CepRule::class, 'document' => \Matmper\Rules\DocumentNumberRule::class, + 'not_html' => \Matmper\Rules\NotHtmlRule::class, ]; foreach ($services as $name => $service) { diff --git a/src/Rules/CepRule.php b/src/Rules/CepRule.php new file mode 100644 index 0000000..a868656 --- /dev/null +++ b/src/Rules/CepRule.php @@ -0,0 +1,68 @@ +setMask($params[0] ?? 'value'); + + return $this; + } + + /** + * Determine if the validation rule passes. + * + * @param string $attribute + * @param mixed $value + * @return bool + */ + public function passes($attribute, $value): bool + { + if ($this->checkMask && !preg_match('/\d{5}\-\d{3}/', $value)) { + return false; + } + + return strlen(preg_replace("/[^\d]/", "", $value)) === 8; + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return ':attribute não é um CEP válido'; + } + + /** + * Validate type and set $this->setMask + * + * @param string $type + * @return void + */ + private function setMask(string $type): void + { + if (!in_array($type, ['value', 'mask'])) { + throw new \Matmper\Exceptions\InvalidValidationParameterException($type); + } + + $this->checkMask = $type === 'mask'; + } +} diff --git a/src/Rules/DocumentNumberRule.php b/src/Rules/DocumentNumberRule.php index 79b34e3..2cf7ff5 100644 --- a/src/Rules/DocumentNumberRule.php +++ b/src/Rules/DocumentNumberRule.php @@ -28,7 +28,7 @@ class DocumentNumberRule implements Rule */ public function params(array $params): self { - $this->setDocuments($params[0] ?? 'cpf|cnpj'); + $this->setDocuments($params[0] ?? 'cpf.cnpj'); $this->setMask($params[1] ?? 'value'); return $this; @@ -71,12 +71,12 @@ public function message() /** * Validate document list and set in $this->documents * - * @param string $documents cpf|cnpj + * @param string $documents cpf.cnpj * @return void */ private function setDocuments(string $documents): void { - $this->documents = explode('|', $documents); + $this->documents = explode('.', $documents); $validDocumentTypes = [DocumentType::CPF, DocumentType::CNPJ]; diff --git a/src/Rules/NotHtmlRule.php b/src/Rules/NotHtmlRule.php new file mode 100644 index 0000000..86e277f --- /dev/null +++ b/src/Rules/NotHtmlRule.php @@ -0,0 +1,48 @@ +]*\/?\s?>/i', $value)) { + return false; + } + + return true; + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return ':attribute não deve conter código HTML'; + } +} diff --git a/src/Services/DocumentCnpjService.php b/src/Services/DocumentCnpjService.php index 29c33b9..9780520 100644 --- a/src/Services/DocumentCnpjService.php +++ b/src/Services/DocumentCnpjService.php @@ -31,7 +31,7 @@ public function passes(mixed $value, bool $checkMask): bool */ private function validate(string $cnpj): bool { - if (strlen($cnpj) <> 14 || (int) $cnpj <= 0) { + if (strlen($cnpj) <> 14 || substr_count($cnpj, substr($cnpj, 0, 1)) === strlen($cnpj)) { return false; } diff --git a/src/Services/DocumentCpfService.php b/src/Services/DocumentCpfService.php index 14ac5f7..81c884b 100644 --- a/src/Services/DocumentCpfService.php +++ b/src/Services/DocumentCpfService.php @@ -31,7 +31,7 @@ public function passes(mixed $value, bool $checkMask): bool */ private function validate(string $cpf): bool { - if (strlen($cpf) <> 11 || (int) $cpf <= 0) { + if (strlen($cpf) <> 11 || substr_count($cpf, substr($cpf, 0, 1)) === strlen($cpf)) { return false; } diff --git a/tests/Unit/CepRuleTest.php b/tests/Unit/CepRuleTest.php new file mode 100644 index 0000000..bd437cd --- /dev/null +++ b/tests/Unit/CepRuleTest.php @@ -0,0 +1,51 @@ +expectException(\Matmper\Exceptions\InvalidValidationParameterException::class); + + $rule = app(\Matmper\Rules\CepRule::class); + $rule->params(['wrong_value']); + } + + /** + * @test + * @dataProvider testCepDataProvider + */ + public function test_document_number(string $type, string $cep, bool $assert): void + { + $rule = app(\Matmper\Rules\CepRule::class); + + $rule->params([$type]); + $passes = $rule->passes(fake()->word(), $cep); + + $this->assertEquals($passes, $assert); + } + + /** + * Data Provider: test_document_number + * + * @return array + */ + public function testCepDataProvider(): array + { + return [ + 'cep_true' => ['value', FakeCepHelper::cep(), true], + 'cep_true_mask' => ['value', FakeCepHelper::cep(true), true], + 'cep_false' => ['value', FakeCepHelper::cep() . fake()->randomDigit(), false], + + 'cep_mask_true' => ['mask', FakeCepHelper::cep(true), true], + 'cep_mask_false_value' => ['mask', FakeCepHelper::cep(), false], + 'cep_mask_false' => ['mask', FakeCepHelper::cep(true) . fake()->randomDigit(), false], + ]; + } +} diff --git a/tests/Unit/DocumentNumberRuleTest.php b/tests/Unit/DocumentNumberRuleTest.php index 8b851e8..2e4268a 100644 --- a/tests/Unit/DocumentNumberRuleTest.php +++ b/tests/Unit/DocumentNumberRuleTest.php @@ -50,9 +50,9 @@ public function test_document_number(string $type, string $mask, string $documen public function testDocumentNumberDataProvider(): array { return [ - 'cpf_cnpj_true_cpf' => ['cpf|cnpj', 'value', FakeDocumentHelper::cpf(), true], - 'cpf_cnpj_true_cnpj' => ['cpf|cnpj', 'value', FakeDocumentHelper::cnpj(), true], - 'cpf_cnpj_false' => ['cpf|cnpj', 'value', fake()->word(), false], + 'cpf_cnpj_true_cpf' => ['cpf.cnpj', 'value', FakeDocumentHelper::cpf(), true], + 'cpf_cnpj_true_cnpj' => ['cpf.cnpj', 'value', FakeDocumentHelper::cnpj(), true], + 'cpf_cnpj_false' => ['cpf.cnpj', 'value', fake()->word(), false], 'cpf_true' => ['cpf', 'value', FakeDocumentHelper::cpf(), true], 'cpf_true_mask' => ['cpf', 'mask', FakeDocumentHelper::cpf(true), true], diff --git a/tests/Unit/Helpers/FakeCepHelper.php b/tests/Unit/Helpers/FakeCepHelper.php new file mode 100644 index 0000000..ab86219 --- /dev/null +++ b/tests/Unit/Helpers/FakeCepHelper.php @@ -0,0 +1,21 @@ +passes(fake()->word(), $value); + + $this->assertEquals($passes, $assert); + } + + /** + * Data Provider: test_not_html + * + * @return array + */ + public function testNotHtmlDataProvider(): array + { + return [ + 'true_string' => [$value = fake()->text(100), true], + 'false_string_01' => ["
{$value}
", false], + 'false_string_02' => ["
", false], + 'false_string_03' => ["
", false], + 'false_string_04' => ["

", false], + 'false_string_05' => ["$value
", false], + 'false_string_05' => ["
$value", false], + ]; + } + + /** + * @test + * @dataProvider testNotHtmlExceptionDataProvider + */ + public function test_not_html_string_exception(mixed $value): void + { + $this->expectException(\Matmper\Exceptions\ValueIsNotStringException::class); + + $rule = app(\Matmper\Rules\NotHtmlRule::class); + $rule->passes(fake()->word(), $value); + } + + /** + * Data Provider: test_not_html_string_exception + * + * @return array + */ + public function testNotHtmlExceptionDataProvider(): array + { + return [ + 'false_int' => [fake()->randomDigitNotZero()], + 'false_float' => [fake()->randomFloat(2)], + 'false_array' => [[1, 2, 3]], + ]; + } +}