Create "Nif" rule

Rule to validate spanish NIF (DNI/NIE/CIF).
This commit is contained in:
Julián Gutiérrez 2016-09-26 15:45:22 +02:00 committed by Henrique Moody
parent 639cfdb3c7
commit 195a8fe534
No known key found for this signature in database
GPG key ID: 221E9281655813A6
14 changed files with 330 additions and 1 deletions

View file

@ -14,3 +14,4 @@ See also:
* [Cnh](Cnh.md)
* [Cnpj](Cnpj.md)
* [Cpf](Cpf.md)
* [Nif](Nif.md)

View file

@ -11,5 +11,7 @@ v::cnh()->validate('02650306461'); // true
***
See also:
* [Bsn](Bsn.md)
* [Cnpj](Cnpj.md)
* [Cpf](Cpf.md)
* [Nif](Nif.md)

View file

@ -8,5 +8,7 @@ use `->digit()` if needed.
***
See also:
* [Cpf](Cpf.md)
* [Bsn](Bsn.md)
* [Cnh](Cnh.md)
* [Cpf](Cpf.md)
* [Nif](Nif.md)

18
docs/Nif.md Normal file
View file

@ -0,0 +1,18 @@
# NIF
- `v::nif()`
Validates Spain's fiscal identification number ([NIF](https://es.wikipedia.org/wiki/N%C3%BAmero_de_identificaci%C3%B3n_fiscal)).
```php
v::nif()->validate('49294492H'); // true
v::nif()->validate('P6437358A'); // false
```
***
See also:
* [Bsn](Bsn.md)
* [Cnh](Cnh.md)
* [Cnpj](Cnpj.md)
* [Cpf](Cpf.md)

View file

@ -183,6 +183,7 @@
* [Json](Json.md)
* [MacAddress](MacAddress.md)
* [NfeAccessKey](NfeAccessKey.md)
* [Nif](Nif.md)
* [NotBlank](NotBlank.md)
* [NotOptional](NotOptional.md)
* [Pesel](Pesel.md)
@ -279,6 +280,7 @@
* [Multiple](Multiple.md)
* [Negative](Negative.md)
* [NfeAccessKey](NfeAccessKey.md)
* [Nif](Nif.md)
* [No](No.md)
* [NoWhitespace](NoWhitespace.md)
* [NoneOf](NoneOf.md)

View file

@ -0,0 +1,27 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
namespace Respect\Validation\Exceptions;
/**
* @author Julián Gutiérrez <juliangut@gmail.com>
*/
final class NifException extends ValidationException
{
public static $defaultTemplates = [
self::MODE_DEFAULT => [
self::STANDARD => '{{name}} must be a NIF',
],
self::MODE_NEGATIVE => [
self::STANDARD => '{{name}} must not be a NIF',
],
];
}

102
library/Rules/Nif.php Normal file
View file

@ -0,0 +1,102 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
namespace Respect\Validation\Rules;
/**
* Validates Spain's fiscal identification number (NIF).
*
* @author Julián Gutiérrez <juliangut@gmail.com>
*
* @see https://es.wikipedia.org/wiki/N%C3%BAmero_de_identificaci%C3%B3n_fiscal
*/
final class Nif extends AbstractRule
{
/**
* {@inheritdoc}
*/
public function validate($input)
{
if (!is_string($input)) {
return false;
}
if (preg_match('/^(\d{8})([A-Z])$/', $input, $matches)) {
return $this->validateDni($matches[1], $matches[2]);
}
if (preg_match('/^([KLMXYZ])(\d{7})([A-Z])$/', $input, $matches)) {
return $this->validateNie($matches[1], $matches[2], $matches[3]);
}
if (preg_match('/^([A-HJNP-SUVW])(\d{7})([0-9A-Z])$/', $input, $matches)) {
return $this->validateCif($matches[2], $matches[3]);
}
return false;
}
/**
* @param int $number
* @param int $control
*/
private function validateDni($number, $control)
{
return substr('TRWAGMYFPDXBNJZSQVHLCKE', ($number % 23), 1) === $control;
}
/**
* @param string $prefix
* @param int $number
* @param int $control
*/
private function validateNie($prefix, $number, $control)
{
if ($prefix === 'Y') {
return $this->validateDni('1'.$number, $control);
}
if ($prefix === 'Z') {
return $this->validateDni('2'.$number, $control);
}
return $this->validateDni($number, $control);
}
/**
* @param int $number
* @param string $control
*/
private function validateCif($number, $control)
{
$code = 0;
$position = 1;
foreach (str_split($number) as $digit) {
$increaser = $digit;
if ($position % 2 !== 0) {
$increaser = array_sum(str_split($digit * 2));
}
$code += $increaser;
++$position;
}
$digits = str_split($code);
$lastDigit = array_pop($digits);
$key = $lastDigit === 0 ? 0 : (10 - $lastDigit);
if (is_numeric($control)) {
return (int) $key === (int) $control;
}
return substr('JABCDEFGHI', ($key % 10), 1) === $control;
}
}

View file

@ -100,6 +100,7 @@ use Respect\Validation\Rules\Key;
* @method static Validator minimumAge(int $age)
* @method static Validator multiple(int $multipleOf)
* @method static Validator negative()
* @method static Validator nif()
* @method static Validator no($useLocale = false)
* @method static Validator noneOf()
* @method static Validator not(Validatable $rule)

View file

@ -0,0 +1,10 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Validator as v;
v::nif()->check('43333207B');
?>
--EXPECTF--

View file

@ -0,0 +1,16 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Exceptions\NifException;
use Respect\Validation\Validator as v;
try {
v::nif()->check('06357771Q');
} catch (NifException $e) {
echo $e->getMainMessage();
}
?>
--EXPECTF--
"06357771Q" must be a NIF

View file

@ -0,0 +1,16 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Exceptions\AllOfException;
use Respect\Validation\Validator as v;
try {
v::nif()->assert('06357771Q');
} catch (AllOfException $e) {
echo $e->getFullMessage();
}
?>
--EXPECTF--
- "06357771Q" must be a NIF

View file

@ -0,0 +1,16 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Exceptions\NifException;
use Respect\Validation\Validator as v;
try {
v::not(v::nif())->check('71110316C');
} catch (NifException $e) {
echo $e->getMainMessage();
}
?>
--EXPECTF--
"71110316C" must not be a NIF

View file

@ -0,0 +1,16 @@
--FILE--
<?php
require 'vendor/autoload.php';
use Respect\Validation\Exceptions\AllOfException;
use Respect\Validation\Validator as v;
try {
v::not(v::nif())->assert('R1332622H');
} catch (AllOfException $e) {
echo $e->getFullMessage();
}
?>
--EXPECTF--
- "R1332622H" must not be a NIF

View file

@ -0,0 +1,100 @@
<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the "LICENSE.md"
* file that was distributed with this source code.
*/
namespace Respect\Validation\Rules;
/**
* @group rule
* @covers Respect\Validation\Rules\Nif
*
* @author Julián Gutiérrez <juliangut@gmail.com>
*/
final class NifTest extends RuleTestCase
{
/**
* {@inheritdoc}
*/
public function providerForValidInput()
{
$rule = new Nif();
return [
// DNI
[$rule, '71110316C'],
[$rule, '99977944A'],
[$rule, '70963442R'],
[$rule, '49294492H'],
[$rule, '11381116A'],
// NIE
[$rule, 'X0425894A'],
[$rule, 'Y4819664M'],
[$rule, 'Y7407711T'],
[$rule, 'Y1168744J'],
[$rule, 'Y1168744J'],
// CIF
[$rule, 'V8002614I'],
[$rule, 'R1332622H'],
[$rule, 'Q6771656C'],
[$rule, 'F3148958F'],
[$rule, 'Q8703717B'],
];
}
/**
* {@inheritdoc}
*/
public function providerForInvalidInput()
{
$rule = new Nif();
return [
// DNI
[$rule, '71110316c'],
[$rule, '36822315D'],
[$rule, '43901481F'],
[$rule, '67931854U'],
[$rule, '20890122T'],
[$rule, '28799818A'],
// NIE
[$rule, 'x0425894a'],
[$rule, 'Y3012039X'],
[$rule, 'Z2448415H'],
[$rule, 'Y7225582L'],
[$rule, 'Y9613245P'],
[$rule, 'X3155250B'],
// CIF
[$rule, 'v8002614i'],
[$rule, 'C0325664D'],
[$rule, 'R27038239'],
[$rule, 'P6437358A'],
[$rule, 'W9188340B'],
[$rule, 'E05172860'],
// No regex match
[$rule, ''],
[$rule, 'I05172860'],
[$rule, 'T2448415H'],
// Weird types
[$rule, []],
[$rule, true],
[$rule, 1],
[$rule, 0.5],
[$rule, null],
[$rule, new \stdClass()],
[$rule, stream_context_create()],
];
}
}