Initial commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
vendor
|
||||||
|
composer.lock
|
||||||
|
.idea
|
||||||
28
README.md
Normal file
28
README.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
Rut Chileno
|
||||||
|
===========
|
||||||
|
|
||||||
|
Esta librería implementa una clase Rut como un *value object* inmutable, incluyendo
|
||||||
|
una api de validación flexible y extendible.
|
||||||
|
|
||||||
|
Además, posee un validador para `symfony/validator`, un *form type* para `symfony/form`
|
||||||
|
y un *type* para `doctrine/dbal`.
|
||||||
|
|
||||||
|
Sólo es compatible con PHP 7.1 o superior.
|
||||||
|
|
||||||
|
## ¿Cómo nació y por qué esta librería?
|
||||||
|
Esta libería nace de la necesidad de estandarizar una clase Rut común para todos mis proyectos
|
||||||
|
PHP.
|
||||||
|
Si bien es cierto, hay muchas liberías con implementaciones de Rut chilenos en PHP,
|
||||||
|
muchas de ellas tienen notorias deficiencias:
|
||||||
|
|
||||||
|
1. No están testeadas unitariamente,
|
||||||
|
2. No separan bien responsabilidades, como la lógica de validación con la de instanciación.
|
||||||
|
3. No proveen validación extensible por medio de interfaces, limitando la validación
|
||||||
|
solo a ser algorítmica.
|
||||||
|
4. Están acopladas a un framework
|
||||||
|
5. No proveen herramientas ni integraciones con librerías de terceros.
|
||||||
|
|
||||||
|
## ¿Por qué PHP 7.1?
|
||||||
|
El fin del soporte de PHP 5.6 será a fines de 2018. PHP 7.1 es una de las últimas
|
||||||
|
versiones estables, y me beneficio mucho de su sistema de tipado estricto en esta libería.
|
||||||
|
|
||||||
33
composer.json
Normal file
33
composer.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "mnavarrocarter/chilean-rut",
|
||||||
|
"description": "PHP Rut Value Object with validation utilities, doctrine type, and other cool features.",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Matias Navarro Carter",
|
||||||
|
"email": "mnavarro@option.cl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"require": {
|
||||||
|
"php": "^7.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"friendsofphp/php-cs-fixer": "^2.12",
|
||||||
|
"phpunit/phpunit": "^7.3",
|
||||||
|
"doctrine/dbal": "^2.5",
|
||||||
|
"symfony/form": "^3.4|^4.0",
|
||||||
|
"symfony/validator": "^3.4|^4.0"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"MNC\\ChileanRut\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload-dev": {
|
||||||
|
"psr-4": {
|
||||||
|
"MNC\\ChileanRut\\Tests\\": "tests"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
phpunit.xml.dist
Normal file
25
phpunit.xml.dist
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<phpunit backupGlobals="false"
|
||||||
|
backupStaticAttributes="false"
|
||||||
|
colors="true"
|
||||||
|
convertErrorsToExceptions="true"
|
||||||
|
convertNoticesToExceptions="true"
|
||||||
|
convertWarningsToExceptions="true"
|
||||||
|
processIsolation="false"
|
||||||
|
stopOnFailure="false"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="Test Suite">
|
||||||
|
<directory suffix="Test.php">./tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory>./src</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
</phpunit>
|
||||||
60
src/Bridge/Doctrine/DBAL/Types/RutType.php
Normal file
60
src/Bridge/Doctrine/DBAL/Types/RutType.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Bridge\Doctrine\DBAL\Types;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
|
use Doctrine\DBAL\Types\ConversionException;
|
||||||
|
use Doctrine\DBAL\Types\StringType;
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RutType
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
class RutType extends StringType
|
||||||
|
{
|
||||||
|
public const NAME = 'rut';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName(): string
|
||||||
|
{
|
||||||
|
return self::NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
* @param AbstractPlatform $platform
|
||||||
|
* @return mixed
|
||||||
|
* @throws ConversionException
|
||||||
|
*/
|
||||||
|
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
||||||
|
{
|
||||||
|
if (null === $value) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value instanceof Rut) {
|
||||||
|
return parent::convertToDatabaseValue($value->format(), $platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'Rut']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
* @param AbstractPlatform $platform
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function convertToPHPValue($value, AbstractPlatform $platform)
|
||||||
|
{
|
||||||
|
$value = parent::convertToPHPValue($value, $platform);
|
||||||
|
|
||||||
|
if ($value === null || $value instanceof Rut) {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Rut($value);
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/Bridge/Symfony/Form/RutType.php
Normal file
27
src/Bridge/Symfony/Form/RutType.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Bridge\Symfony\Form;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RutType
|
||||||
|
* @package MNC\ChileanRut\Bridge\Symfony\Form
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
class RutType extends TextType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param OptionsResolver $resolver
|
||||||
|
*/
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => Rut::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/Bridge/Symfony/Validator/IsValidRut.php
Normal file
13
src/Bridge/Symfony/Validator/IsValidRut.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Bridge\Symfony\Validator;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\Constraint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Annotation
|
||||||
|
*/
|
||||||
|
class IsValidRut extends Constraint
|
||||||
|
{
|
||||||
|
public $message = 'The rut "{{value}}" is not valid.';
|
||||||
|
}
|
||||||
52
src/Bridge/Symfony/Validator/IsValidRutValidator.php
Normal file
52
src/Bridge/Symfony/Validator/IsValidRutValidator.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Bridge\Symfony\Validator;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Exception\InvalidRutException;
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
use MNC\ChileanRut\Validator\RutValidator;
|
||||||
|
use MNC\ChileanRut\Validator\SimpleRutValidator;
|
||||||
|
use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
||||||
|
use Symfony\Component\Validator\Constraint;
|
||||||
|
use Symfony\Component\Validator\ConstraintValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IsValidRutValidator
|
||||||
|
* @package MNC\ChileanRut\Bridge\Symfony\Validator
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
class IsValidRutValidator extends ConstraintValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var RutValidator
|
||||||
|
*/
|
||||||
|
private $validator;
|
||||||
|
|
||||||
|
public function __construct(RutValidator $validator = null)
|
||||||
|
{
|
||||||
|
$this->validator = $validator ?? new SimpleRutValidator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $value
|
||||||
|
* @param Constraint $constraint
|
||||||
|
*/
|
||||||
|
public function validate($value, Constraint $constraint): void
|
||||||
|
{
|
||||||
|
if (null === $value || '' === $value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$value instanceof Rut) {
|
||||||
|
throw new UnexpectedTypeException($value, Rut::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->validator->validate($value);
|
||||||
|
} catch (InvalidRutException $exception) {
|
||||||
|
$this->context->buildViolation($constraint->message)
|
||||||
|
->setParameter('{{ value }}', $value->format(Rut::FORMAT_CLEAR))
|
||||||
|
->addViolation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/Exception/InvalidRutException.php
Normal file
37
src/Exception/InvalidRutException.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Exception;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class InvalidRutException
|
||||||
|
* @package MNC\ChileanRut\Rut
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
class InvalidRutException extends \LogicException
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Rut
|
||||||
|
*/
|
||||||
|
private $rut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InvalidRutException constructor.
|
||||||
|
* @param Rut $rut
|
||||||
|
*/
|
||||||
|
public function __construct(Rut $rut)
|
||||||
|
{
|
||||||
|
$message = sprintf('Rut %s is not a valid rut.', $rut->format(Rut::FORMAT_READABLE));
|
||||||
|
$this->rut = $rut;
|
||||||
|
parent::__construct($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Rut
|
||||||
|
*/
|
||||||
|
public function getRut(): Rut
|
||||||
|
{
|
||||||
|
return $this->rut;
|
||||||
|
}
|
||||||
|
}
|
||||||
131
src/Rut/Rut.php
Normal file
131
src/Rut/Rut.php
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Rut;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Validator\RutValidator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Rut
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
class Rut
|
||||||
|
{
|
||||||
|
public const FORMAT_HYPHENED = 0; // 14533535-5
|
||||||
|
public const FORMAT_CLEAR = 1; // 145335355
|
||||||
|
public const FORMAT_READABLE = 2; // 14.533.535-5
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $value;
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $dv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rut constructor.
|
||||||
|
* @param string $rut
|
||||||
|
* @param RutValidator|null $validator if provided validates the Rut.
|
||||||
|
*/
|
||||||
|
public function __construct(string $rut, RutValidator $validator = null)
|
||||||
|
{
|
||||||
|
$sanitized = $this->sanitize($rut);
|
||||||
|
$this->value = substr($sanitized, 0, -1);
|
||||||
|
$this->dv = $sanitized[\strlen($sanitized) - 1];
|
||||||
|
|
||||||
|
if (null !== $validator) {
|
||||||
|
$validator->validate($this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $correlative
|
||||||
|
* @param string $verifierDigit
|
||||||
|
* @return Rut
|
||||||
|
*/
|
||||||
|
public static function fromParts(string $correlative, string $verifierDigit): Rut
|
||||||
|
{
|
||||||
|
return new self($correlative.$verifierDigit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $rut
|
||||||
|
* @return Rut
|
||||||
|
*/
|
||||||
|
public static function fromString(string $rut): Rut
|
||||||
|
{
|
||||||
|
return new self($rut);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Rut $rut
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isEqualTo(Rut $rut): bool
|
||||||
|
{
|
||||||
|
return $this->format() === $rut->format();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function sanitize(string $value): string
|
||||||
|
{
|
||||||
|
$value = trim($value);
|
||||||
|
$value = strtoupper($value);
|
||||||
|
return str_replace(['.', ',', '-'], '', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $format One of the FORMAT_ constants.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function format(int $format = 0): string
|
||||||
|
{
|
||||||
|
switch ($format) {
|
||||||
|
case self::FORMAT_HYPHENED:
|
||||||
|
return $this->value . '-' . $this->dv;
|
||||||
|
break;
|
||||||
|
case self::FORMAT_CLEAR:
|
||||||
|
return $this->value . $this->dv;
|
||||||
|
break;
|
||||||
|
case self::FORMAT_READABLE:
|
||||||
|
return sprintf('%s-%s', number_format($this->value, 0, '', '.'), $this->dv);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new \InvalidArgumentException(
|
||||||
|
sprintf(
|
||||||
|
'Argument provided for %s method of class %s is invalid.',
|
||||||
|
__METHOD__,
|
||||||
|
__CLASS__
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCorrelative(): string
|
||||||
|
{
|
||||||
|
return $this->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getVerifierDigit(): string
|
||||||
|
{
|
||||||
|
return $this->dv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return $this->format(self::FORMAT_READABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
56
src/Util/Correlative.php
Normal file
56
src/Util/Correlative.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Util;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides utils for a Rut correlative.
|
||||||
|
*
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
class Correlative
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Finds the verifier digit of a correlative.
|
||||||
|
*
|
||||||
|
* @param string $correlative
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function findVerifierDigit(string $correlative): string
|
||||||
|
{
|
||||||
|
$x = 2;
|
||||||
|
$s = 0;
|
||||||
|
|
||||||
|
for ($i = \strlen($correlative) - 1; $i >= 0; $i--) {
|
||||||
|
if ($x > 7) {
|
||||||
|
$x = 2;
|
||||||
|
}
|
||||||
|
$s += $correlative[$i] * $x;
|
||||||
|
$x++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dv = 11 - ($s % 11);
|
||||||
|
|
||||||
|
if ($dv === 10) {
|
||||||
|
$dv = 'K';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dv === 11) {
|
||||||
|
$dv = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string) $dv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a valid Rut object just providing a correlative.
|
||||||
|
*
|
||||||
|
* @param string $correlative
|
||||||
|
* @return Rut
|
||||||
|
*/
|
||||||
|
public static function createValidRutOnlyFromCorrelative(string $correlative): Rut
|
||||||
|
{
|
||||||
|
return Rut::fromParts($correlative, static::findVerifierDigit($correlative));
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/Validator/ChainRutValidator.php
Normal file
51
src/Validator/ChainRutValidator.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Validator;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Exception\InvalidRutException;
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ChainRutValidator
|
||||||
|
*
|
||||||
|
* Use this implementation when you want to validate a Rut against multiple
|
||||||
|
* validators. Add the validators in order by calling addValidator().
|
||||||
|
*
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
class ChainRutValidator implements RutValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var RutValidator[]
|
||||||
|
*/
|
||||||
|
private $validators;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ChainRutValidator constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->validators = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param RutValidator $validator
|
||||||
|
* @return ChainRutValidator
|
||||||
|
*/
|
||||||
|
public function addValidator(RutValidator $validator): ChainRutValidator
|
||||||
|
{
|
||||||
|
$this->validators[] = $validator;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Rut $rut
|
||||||
|
* @throws InvalidRutException on invalid Rut.
|
||||||
|
*/
|
||||||
|
public function validate(Rut $rut): void
|
||||||
|
{
|
||||||
|
foreach ($this->validators as $validator) {
|
||||||
|
$validator->validate($rut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/Validator/RutValidator.php
Normal file
35
src/Validator/RutValidator.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Validator;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Exception\InvalidRutException;
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the base contract for a Rut validator.
|
||||||
|
*
|
||||||
|
* You can implement any logic here that you can use to validate a Rut.
|
||||||
|
* For example, the SimpleRutValidator only validates that a Rut is algorithmically
|
||||||
|
* correct, but not that it actually exists.
|
||||||
|
*
|
||||||
|
* You could create a HTTPRutValidator that performs a request to validate that a
|
||||||
|
* Rut exists against a Rest Api or a third party service.
|
||||||
|
*
|
||||||
|
* @package MNC\ChileanRut\Validator
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
interface RutValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Validates a Rut.
|
||||||
|
*
|
||||||
|
* The implementation MUST throw an InvalidRutException if validation fails.
|
||||||
|
*
|
||||||
|
* The different clients CAN catch that exception and handle the validation
|
||||||
|
* error according to their business rules.
|
||||||
|
*
|
||||||
|
* @param Rut $rut
|
||||||
|
* @throws InvalidRutException on invalid Rut.
|
||||||
|
*/
|
||||||
|
public function validate(Rut $rut): void;
|
||||||
|
}
|
||||||
27
src/Validator/SimpleRutValidator.php
Normal file
27
src/Validator/SimpleRutValidator.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Validator;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Exception\InvalidRutException;
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
use MNC\ChileanRut\Util\Correlative;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the Rut using the Module 11 algorithm.
|
||||||
|
*
|
||||||
|
* @author Matías Navarro Carter <mnavarro@option.cl>
|
||||||
|
*/
|
||||||
|
class SimpleRutValidator implements RutValidator
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Rut $rut
|
||||||
|
*/
|
||||||
|
public function validate(Rut $rut): void
|
||||||
|
{
|
||||||
|
$digit = Correlative::findVerifierDigit($rut->getCorrelative());
|
||||||
|
|
||||||
|
if ($digit !== $rut->getVerifierDigit()) {
|
||||||
|
throw new InvalidRutException($rut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
66
tests/Rut/RutTest.php
Normal file
66
tests/Rut/RutTest.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Created by PhpStorm.
|
||||||
|
* User: mnavarro
|
||||||
|
* Date: 07-08-18
|
||||||
|
* Time: 23:45
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Tests\Rut;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Exception\InvalidRutException;
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
use MNC\ChileanRut\Validator\SimpleRutValidator;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class RutTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testThatRutIsSanitizedProperlyOnInstantiation()
|
||||||
|
{
|
||||||
|
$rut = Rut::fromString('16.894.365-2');
|
||||||
|
|
||||||
|
$this->assertEquals('16894365', $rut->getCorrelative());
|
||||||
|
$this->assertEquals('2', $rut->getVerifierDigit());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatRutsInstantiatedDifferentFormatButWithEqualValueAreIndeedEqual()
|
||||||
|
{
|
||||||
|
$rut1 = new Rut('16.894.365-2');
|
||||||
|
$rut2 = new Rut('16894365-2');
|
||||||
|
$this->assertTrue($rut1->isEqualTo($rut2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatFormatClearWorks()
|
||||||
|
{
|
||||||
|
$rut = new Rut('16.894.365-2');
|
||||||
|
$this->assertEquals('168943652', $rut->format(Rut::FORMAT_CLEAR));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatFormatWithHyphenWorks()
|
||||||
|
{
|
||||||
|
$rut = new Rut('16.894.365-2');
|
||||||
|
$this->assertEquals('16894365-2', $rut->format(Rut::FORMAT_HYPHENED));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatFormatReadableWorks()
|
||||||
|
{
|
||||||
|
$rut = new Rut('168943652');
|
||||||
|
$this->assertEquals('16.894.365-2', $rut->format(Rut::FORMAT_READABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatIntegratedValidationThrowsExceptionOnInvalidRut()
|
||||||
|
{
|
||||||
|
$this->expectException(InvalidRutException::class);
|
||||||
|
|
||||||
|
$validator = new SimpleRutValidator();
|
||||||
|
$rut = new Rut('4444444-2', $validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testThatIntegratedValidationDoesNotThrowExceptionOnValidRut()
|
||||||
|
{
|
||||||
|
$validator = new SimpleRutValidator();
|
||||||
|
$rut = new Rut('16.894.365-2', $validator);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Rut::class, $rut);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
tests/Validator/SimpleRutValidatorTest.php
Normal file
31
tests/Validator/SimpleRutValidatorTest.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MNC\ChileanRut\Tests\Validator;
|
||||||
|
|
||||||
|
use MNC\ChileanRut\Exception\InvalidRutException;
|
||||||
|
use MNC\ChileanRut\Rut\Rut;
|
||||||
|
use MNC\ChileanRut\Validator\SimpleRutValidator;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class SimpleRutValidatorTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testValidationPassesOnValidRut()
|
||||||
|
{
|
||||||
|
$rut = new Rut('16.894.365-2');
|
||||||
|
$validator = new SimpleRutValidator();
|
||||||
|
|
||||||
|
$validator->validate($rut);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Rut::class, $rut);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testValidationFailsOnInvalidRut()
|
||||||
|
{
|
||||||
|
$this->expectException(InvalidRutException::class);
|
||||||
|
|
||||||
|
$rut = new Rut('34.4534.353-1');
|
||||||
|
$validator = new SimpleRutValidator();
|
||||||
|
|
||||||
|
$validator->validate($rut);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user