feat: new v4 version (#5)
This commit is contained in:
1
.dev/.gitignore
vendored
Normal file
1
.dev/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
coverage
|
||||||
50
.dev/docker/php/Dockerfile
Normal file
50
.dev/docker/php/Dockerfile
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
FROM alpine:3.18 as base
|
||||||
|
|
||||||
|
ARG UID=1000
|
||||||
|
ARG USER=mnavarro
|
||||||
|
ARG COMPOSER_VERSION=2.7.0
|
||||||
|
|
||||||
|
# Create a development user
|
||||||
|
RUN adduser $USER --disabled-password --home /$USER --uid $UID
|
||||||
|
|
||||||
|
# Install PHP Extensions
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
php82-cli \
|
||||||
|
php82-phar \
|
||||||
|
php82-mbstring \
|
||||||
|
php82-json \
|
||||||
|
php82-zip \
|
||||||
|
php82-openssl \
|
||||||
|
php82-dom \
|
||||||
|
php82-xml \
|
||||||
|
php82-soap \
|
||||||
|
php82-session \
|
||||||
|
php82-xmlwriter \
|
||||||
|
php82-sockets \
|
||||||
|
php82-simplexml \
|
||||||
|
php82-bcmath \
|
||||||
|
php82-xmlreader \
|
||||||
|
php82-tokenizer \
|
||||||
|
php82-iconv \
|
||||||
|
php82-sodium \
|
||||||
|
php82-fileinfo \
|
||||||
|
php82-curl \
|
||||||
|
php82-ctype \
|
||||||
|
php82-pcntl \
|
||||||
|
php82-posix
|
||||||
|
|
||||||
|
# Link php82 to php
|
||||||
|
RUN ln -s /usr/bin/php82 /usr/bin/php
|
||||||
|
|
||||||
|
# Add wget to make requests
|
||||||
|
RUN apk add --no-cache wget
|
||||||
|
|
||||||
|
# Download and install composer
|
||||||
|
RUN wget -O /usr/bin/composer https://github.com/composer/composer/releases/download/$COMPOSER_VERSION/composer.phar && \
|
||||||
|
chmod +x /usr/bin/composer
|
||||||
|
|
||||||
|
FROM base as dev
|
||||||
|
|
||||||
|
# Install and Configure XDebug
|
||||||
|
RUN apk add --no-cache php82-pecl-xdebug
|
||||||
|
COPY ./xdebug.ini /etc/php82/conf.d/60_xdebug.ini
|
||||||
6
.dev/docker/php/xdebug.ini
Normal file
6
.dev/docker/php/xdebug.ini
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
zend_extension=xdebug.so
|
||||||
|
|
||||||
|
[xdebug]
|
||||||
|
xdebug.mode=debug,develop,coverage
|
||||||
|
xdebug.client_host=host.docker.internal
|
||||||
|
xdebug.output_dir=/castor/context/.dev/debug
|
||||||
7
.dev/init
Executable file
7
.dev/init
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
mkdir -p .dev/coverage
|
||||||
|
|
||||||
|
composer install
|
||||||
12
.gitattributes
vendored
Normal file
12
.gitattributes
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/.idea export-ignore
|
||||||
|
/vendor export-ignore
|
||||||
|
/tests export-ignore
|
||||||
|
/.dev export-ignore
|
||||||
|
/.php-cs-fixer.dist.php export-ignore
|
||||||
|
/compose.yml export-ignore
|
||||||
|
/composer.lock export-ignore
|
||||||
|
/phpunit.xml export-ignore
|
||||||
|
/psalm.xml export-ignore
|
||||||
|
/psalm-baseline.xml export-ignore
|
||||||
|
/.gitignore export-ignore
|
||||||
|
/README.md export-ignore
|
||||||
39
.github/workflows/ci.yml
vendored
Normal file
39
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
name: "Chilean Rut CI"
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: ['master']
|
||||||
|
paths:
|
||||||
|
- '**.php'
|
||||||
|
- 'composer.json'
|
||||||
|
- '.github/workflows/ci.yml'
|
||||||
|
- '.github/workflows/php.yml'
|
||||||
|
push:
|
||||||
|
branches: ['master']
|
||||||
|
paths:
|
||||||
|
- '**.php'
|
||||||
|
- 'composer.json'
|
||||||
|
- '.github/workflows/ci.yml'
|
||||||
|
- '.github/workflows/php.yml'
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
name: 'CI'
|
||||||
|
uses: ./.github/workflows/php.yml
|
||||||
|
with:
|
||||||
|
php-version: 8.2
|
||||||
|
composer-cmd: install --ansi --no-interaction --no-progress --no-suggest --prefer-dist
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
# Publishes code coverage report
|
||||||
|
publish-coverage:
|
||||||
|
name: "Publish Coverage"
|
||||||
|
needs: ['ci']
|
||||||
|
if: ${{ github.ref_name == 'master' }}
|
||||||
|
environment:
|
||||||
|
name: github-pages
|
||||||
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Deploy to GitHub Pages
|
||||||
|
id: deployment
|
||||||
|
uses: actions/deploy-pages@v4
|
||||||
51
.github/workflows/php.yml
vendored
Normal file
51
.github/workflows/php.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: "PHP Checks"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
php-version:
|
||||||
|
description: 'The version of PHP to use'
|
||||||
|
default: '8.2'
|
||||||
|
type: string
|
||||||
|
composer-cmd:
|
||||||
|
description: 'Command to install dependencies'
|
||||||
|
type: string
|
||||||
|
default: 'install --ansi --no-interaction --no-progress --no-suggest --prefer-dist'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
php-checks:
|
||||||
|
name: "PHP Checks"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: "Checkout Code"
|
||||||
|
uses: "actions/checkout@v2"
|
||||||
|
- name: "Install PHP"
|
||||||
|
uses: "shivammathur/setup-php@v2"
|
||||||
|
with:
|
||||||
|
coverage: "pcov"
|
||||||
|
php-version: "${{ inputs.php-version }}"
|
||||||
|
ini-values: memory_limit=-1
|
||||||
|
tools: composer:v2
|
||||||
|
- name: Get Composer Cache Directory
|
||||||
|
id: composer-cache
|
||||||
|
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||||
|
- name: "Cache dependencies"
|
||||||
|
uses: "actions/cache@v2"
|
||||||
|
with:
|
||||||
|
path: ${{ steps.composer-cache.outputs.dir }}
|
||||||
|
key: "${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}"
|
||||||
|
restore-keys: "${{ runner.os }}-composer-"
|
||||||
|
- name: "Install dependencies"
|
||||||
|
run: "composer ${{ inputs.composer-cmd }}"
|
||||||
|
- name: "Check Code Style"
|
||||||
|
run: "composer fmt:check"
|
||||||
|
- name: "Run Psalm"
|
||||||
|
run: "composer psalm:gh"
|
||||||
|
- name: "Run Test Suite"
|
||||||
|
run: "composer test"
|
||||||
|
- name: Setup Pages
|
||||||
|
uses: actions/configure-pages@v4
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-pages-artifact@v3
|
||||||
|
with:
|
||||||
|
path: '.dev/coverage'
|
||||||
122
.github/workflows/pr.yml
vendored
122
.github/workflows/pr.yml
vendored
@@ -1,122 +0,0 @@
|
|||||||
name: "Review PR"
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
|
|
||||||
env:
|
|
||||||
COMPOSER_FLAGS: "--ansi --no-interaction --no-progress --no-suggest --prefer-dist"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
|
|
||||||
# This job ensures the coding standard is followed
|
|
||||||
coding-standards:
|
|
||||||
name: "Coding Standards"
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
php-version:
|
|
||||||
- "7.4"
|
|
||||||
operating-system:
|
|
||||||
- "ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- name: "Checkout Code"
|
|
||||||
uses: "actions/checkout@v2"
|
|
||||||
- name: "Install PHP"
|
|
||||||
uses: "shivammathur/setup-php@v2"
|
|
||||||
with:
|
|
||||||
coverage: "pcov"
|
|
||||||
php-version: "${{ matrix.php-version }}"
|
|
||||||
ini-values: memory_limit=-1
|
|
||||||
tools: composer:v2
|
|
||||||
- name: Get Composer Cache Directory
|
|
||||||
id: composer-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
|
||||||
- name: "Cache dependencies"
|
|
||||||
uses: "actions/cache@v2"
|
|
||||||
with:
|
|
||||||
path: ${{ steps.composer-cache.outputs.dir }}
|
|
||||||
key: "composer-cache"
|
|
||||||
restore-keys: "composer-cache"
|
|
||||||
- name: "Install dependencies"
|
|
||||||
run: "composer install ${{ env.COMPOSER_FLAGS }}"
|
|
||||||
- name: "Coding Standard"
|
|
||||||
run: "vendor/bin/php-cs-fixer fix --dry-run -vvv"
|
|
||||||
|
|
||||||
type-analysis:
|
|
||||||
name: "Type Coverage"
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
php-version:
|
|
||||||
- "7.4"
|
|
||||||
operating-system:
|
|
||||||
- "ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- name: "Checkout Code"
|
|
||||||
uses: "actions/checkout@v2"
|
|
||||||
- name: "Install PHP"
|
|
||||||
uses: "shivammathur/setup-php@v2"
|
|
||||||
with:
|
|
||||||
coverage: "pcov"
|
|
||||||
php-version: "${{ matrix.php-version }}"
|
|
||||||
ini-values: memory_limit=-1
|
|
||||||
tools: composer:v2
|
|
||||||
- name: Get Composer Cache Directory
|
|
||||||
id: composer-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
|
||||||
- name: "Cache dependencies"
|
|
||||||
uses: "actions/cache@v2"
|
|
||||||
with:
|
|
||||||
path: ${{ steps.composer-cache.outputs.dir }}
|
|
||||||
key: "composer-cache"
|
|
||||||
restore-keys: "composer-cache"
|
|
||||||
- name: "Install dependencies"
|
|
||||||
run: "composer install ${{ env.COMPOSER_FLAGS }}"
|
|
||||||
- name: "Run Psalm"
|
|
||||||
run: "vendor/bin/psalm --output-format=github --shepherd --stats"
|
|
||||||
continue-on-error: true
|
|
||||||
|
|
||||||
unit-test:
|
|
||||||
name: "Unit Testing"
|
|
||||||
runs-on: ${{ matrix.operating-system }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
dependencies:
|
|
||||||
- "lowest"
|
|
||||||
- "highest"
|
|
||||||
php-version:
|
|
||||||
- "7.4"
|
|
||||||
- "8.0"
|
|
||||||
operating-system:
|
|
||||||
- "ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- name: "Checkout Code"
|
|
||||||
uses: "actions/checkout@v2"
|
|
||||||
- name: "Install PHP"
|
|
||||||
uses: "shivammathur/setup-php@v2"
|
|
||||||
with:
|
|
||||||
coverage: "pcov"
|
|
||||||
php-version: "${{ matrix.php-version }}"
|
|
||||||
ini-values: memory_limit=-1
|
|
||||||
tools: composer:v2
|
|
||||||
- name: Get Composer Cache Directory
|
|
||||||
id: composer-cache
|
|
||||||
run: |
|
|
||||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
|
||||||
- name: "Cache dependencies"
|
|
||||||
uses: "actions/cache@v2"
|
|
||||||
with:
|
|
||||||
path: ${{ steps.composer-cache.outputs.dir }}
|
|
||||||
key: "composer-cache"
|
|
||||||
restore-keys: "composer-cache"
|
|
||||||
- name: "Install lowest dependencies"
|
|
||||||
if: ${{ matrix.dependencies == 'lowest' }}
|
|
||||||
run: "composer update ${{ env.COMPOSER_FLAGS }} --prefer-lowest"
|
|
||||||
- name: "Install highest dependencies"
|
|
||||||
if: ${{ matrix.dependencies == 'highest' }}
|
|
||||||
run: "composer install ${{ env.COMPOSER_FLAGS }}"
|
|
||||||
- name: "Run PHPUnit"
|
|
||||||
run: "vendor/bin/phpunit --testdox --coverage-text"
|
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,5 +1,3 @@
|
|||||||
vendor
|
vendor
|
||||||
composer.lock
|
.env
|
||||||
.idea
|
compose.override.yml
|
||||||
.php_cs.cache
|
|
||||||
.phpunit.result.cache
|
|
||||||
36
.php-cs-fixer.dist.php
Normal file
36
.php-cs-fixer.dist.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use PhpCsFixer\Fixer\FunctionNotation\NativeFunctionInvocationFixer;
|
||||||
|
|
||||||
|
$header = <<<EOF
|
||||||
|
@project Chilean RUT
|
||||||
|
@link https://github.com/mnavarrocarter/chilean-rut
|
||||||
|
@package castor/log
|
||||||
|
@author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
|
@license MIT
|
||||||
|
@copyright 2024 Matias Navarro-Carter
|
||||||
|
|
||||||
|
For the full copyright and license information, please view the LICENSE
|
||||||
|
file that was distributed with this source code.
|
||||||
|
EOF;
|
||||||
|
|
||||||
|
return (new PhpCsFixer\Config())
|
||||||
|
->setCacheFile('/tmp/php-cs-fixer')
|
||||||
|
->setRiskyAllowed(true)
|
||||||
|
->setRules([
|
||||||
|
'@PhpCsFixer' => true,
|
||||||
|
'declare_strict_types' => true,
|
||||||
|
'header_comment' => ['header' => $header, 'comment_type' => 'PHPDoc'],
|
||||||
|
'yoda_style' => false,
|
||||||
|
'php_unit_internal_class' => false,
|
||||||
|
'php_unit_test_class_requires_covers' => false,
|
||||||
|
'native_function_invocation' => [
|
||||||
|
'include' => [NativeFunctionInvocationFixer::SET_ALL],
|
||||||
|
'scope' => 'namespaced',
|
||||||
|
]
|
||||||
|
])
|
||||||
|
->setFinder(
|
||||||
|
PhpCsFixer\Finder::create()
|
||||||
|
->in(["src", "tests"])
|
||||||
|
)
|
||||||
|
;
|
||||||
71
README.md
71
README.md
@@ -7,7 +7,7 @@ Además, posee dos *types* para `doctrine/dbal`.
|
|||||||
|
|
||||||
## Instalación
|
## Instalación
|
||||||
|
|
||||||
Esta libería funciona con composer:
|
Esta puede ser instalada mediante composer:
|
||||||
|
|
||||||
```
|
```
|
||||||
composer require mnavarrocarter/chilean-rut
|
composer require mnavarrocarter/chilean-rut
|
||||||
@@ -18,8 +18,11 @@ composer require mnavarrocarter/chilean-rut
|
|||||||
### Parseando un Rut
|
### Parseando un Rut
|
||||||
|
|
||||||
La clase Rut es capaz de parsear cualquier tipo de rut sin importar el formato usando
|
La clase Rut es capaz de parsear cualquier tipo de rut sin importar el formato usando
|
||||||
el método `Rut::parse()`. Confiadamente puedes poner el valor directamente de un
|
el método `Rut::parse()`. Confiadamente, puedes poner el valor directamente de un
|
||||||
formulario web y `parse` se encargara de sanitizar el string y ver si el RUT es valido.
|
formulario web y `parse` se encargará de sanitizar el string y ver si el RUT es válido.
|
||||||
|
|
||||||
|
> NOTA: Un Rut se considera válido cuando su dígito verificador es algorítmicamente válido
|
||||||
|
> para el número. Esta libreria no puede validar que el Rut existe realmente.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
@@ -29,50 +32,53 @@ use MNC\ChileanRut\Rut;
|
|||||||
$rut = Rut::parse('23.546.565-4');
|
$rut = Rut::parse('23.546.565-4');
|
||||||
```
|
```
|
||||||
|
|
||||||
### Validando el Rut
|
### Validando el RUT
|
||||||
|
|
||||||
> TLDR: Un objeto `Rut` siempre será valido.
|
> TLDR: Un objeto `Rut` siempre será valido.
|
||||||
|
|
||||||
Si tu RUT no es valido, el método `parse` lanzara una excepción de tipo
|
Si tu RUT no es válido, el método `parse` lanzara una excepción de tipo
|
||||||
`MNC\ChileanRut\InvalidRut`. Esto es para seguir buenos principios de *objects
|
`MNC\Rut\IsInvalid`. Esto es para seguir buenos principios de *objects
|
||||||
calisthenics*: un objeto de valor siempre se crea en un estado valido, y se mantiene
|
calisthenics*: un objeto de valor siempre se crea en un estado válido, y se mantiene
|
||||||
valido a través de todo su ciclo de vida. No se permiten mutaciones que dejen el
|
válido a través de todo su ciclo de vida. No se permiten mutaciones que dejen el
|
||||||
objeto en un estado invalido.
|
objeto en un estado inválido.
|
||||||
|
|
||||||
Por esta razón el objecto `$rut` es completamente inmutable. Esto quiere decir
|
Por esta razón el objeto `MNC\Rut\IsInvalid` es completamente inmutable. Esto quiere decir
|
||||||
que una vez creado no puedes cambiar su estado interno: solo puedes leer información.
|
que una vez creado no puedes cambiar su estado interno: solo puedes leer información.
|
||||||
Estos son los unicos métodos que puedes usar:
|
Estos son los unicos métodos que puedes usar:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use MNC\ChileanRut\Rut;
|
use MNC\Rut;
|
||||||
|
|
||||||
$rut = Rut::parse('23.546.565-4');
|
$rut = Rut::parse('23.546.565-4');
|
||||||
|
|
||||||
$rut->getNumber(); // (int) 23546565
|
$rut->number; // (int) 23546565
|
||||||
$rut->getVerifier(); // (string) 4
|
$rut->verifier; // (MNC\Rut\Verifier::Four) 4
|
||||||
```
|
```
|
||||||
|
|
||||||
### Formateando el Rut
|
### Formateando el Rut
|
||||||
|
|
||||||
Existen muchas formas distintas de formatear un rut y esta librería soporta muchas
|
Existen muchas formas distintas de formatear un RUT y esta librería soporta muchas
|
||||||
de ellas. El método format devuelve un objeto al cual puedes encadenar llamadas para
|
de ellas. El método format devuelve un objeto al cual puedes encadenar llamadas para
|
||||||
formatear el rut y luego castearlo a un string. La interfaz es encadenable para que
|
formatear el RUT y extraer su información de diversas maneras.
|
||||||
puedas combinar las opciones de formato como quieras.
|
|
||||||
|
He aquí algunos ejemplos:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use MNC\ChileanRut\Rut;
|
use MNC\Rut;
|
||||||
|
|
||||||
$rut = Rut::parse('23.546.565-4');
|
$rut = Rut::parse('23.546.565-4');
|
||||||
|
|
||||||
echo $rut->format()->hyphened(); // 23546565-4
|
echo $rut->toString(); // 235465654
|
||||||
echo $rut->format()->dotted()->hyphened(); // 23.546.565-2
|
echo $rut->toSimple(); // 23546565-4
|
||||||
echo $rut->format()->dotted()->hyphened()->obfuscated(); // **.***.565-2
|
echo $rut->toHuman(); // 23.546.565-4
|
||||||
echo $rut->format()->obfuscated()->hyphened(); // *****565-2
|
echo $rut->last(4); // 6565
|
||||||
echo $rut->format()->obfuscated(); // *****5652
|
echo $rut->last(4, pad: '*'); // ****6565
|
||||||
|
echo $rut->first(4); // 2354
|
||||||
|
echo $rut->first(4, pad: '*'); // 2354****
|
||||||
```
|
```
|
||||||
|
|
||||||
## Integraciones con Librerías de Terceros
|
## Integraciones con Librerías de Terceros
|
||||||
@@ -82,13 +88,13 @@ Esta librería provee dos [*Custom Types*](https://www.doctrine-project.org/proj
|
|||||||
para Doctrine, con el objetivo de que puedas mapear tus objetos `Rut` fácilmente
|
para Doctrine, con el objetivo de que puedas mapear tus objetos `Rut` fácilmente
|
||||||
a una base de datos relacional.
|
a una base de datos relacional.
|
||||||
|
|
||||||
El `MNC\ChileanRut\Doctrine\RutType` mapeara tu RUT a una columna VARCHAR.
|
`MNC\Rut\Doctrine\RutType` mapea tu RUT a una columna VARCHAR.
|
||||||
El string se guarda con puntos y guion. Ex: `16.894.365-2`. Es una forma no tan
|
El string se guarda con puntos y guion. Ex: `16.894.365-2`. Es una forma no tan
|
||||||
eficiente de guardar los RUTS (en términos de espacio), pero ayuda mucho cuando
|
eficiente de guardar los RUTS (en términos de espacio), pero ayuda mucho cuando
|
||||||
se visualiza o exporta la base de datos a otras fuentes.
|
se visualiza o exporta la base de datos a otras fuentes.
|
||||||
|
|
||||||
El `MNC\ChileanRut\Doctrine\NumericRutType` mapeara tu RUT a una columna INTEGER.
|
`MNC\Rut\Doctrine\NumericRutType` mapea tu RUT a una columna INTEGER.
|
||||||
El numero se guarda sin digito verificador y es recalculado cuando la columna
|
El número se guarda sin dígito verificador y es recalculado cuando la columna
|
||||||
es transformada a un valor PHP. Esta forma de guardar ruts es muy eficiente (en
|
es transformada a un valor PHP. Esta forma de guardar ruts es muy eficiente (en
|
||||||
términos de espacio), pero cuesta comparar y leer los números si visualizas o
|
términos de espacio), pero cuesta comparar y leer los números si visualizas o
|
||||||
exportas los registros en la base de datos.
|
exportas los registros en la base de datos.
|
||||||
@@ -97,18 +103,15 @@ Por supuesto, puedes elegir el `Type` que más se ajuste a tus necesidades.
|
|||||||
|
|
||||||
## FAQ
|
## FAQ
|
||||||
|
|
||||||
### ¿Cómo nació y por qué esta librería?
|
### ¿Por qué esta librería?
|
||||||
Esta librería nace de la necesidad de estandarizar una clase Rut común para todos
|
Esta librería nace de la necesidad de estandarizar una clase Rut común para todos
|
||||||
mis proyectos PHP.
|
mis proyectos PHP.
|
||||||
|
|
||||||
Si bien es cierto, hay muchas librerías con implementaciones de Rut chilenos en PHP,
|
Si bien es cierto, hay muchas librerías con implementaciones de Rut chilenos en PHP,
|
||||||
muchas de ellas tienen notorias deficiencias:
|
muchas de ellas tienen notorias deficiencias:
|
||||||
|
|
||||||
1. No están testeadas unitariamente,
|
1. No están testeadas unitariamente.
|
||||||
2. No tienen un buen diseño y sus apis tienen efectos secundarios.
|
2. No estan tipadas apropiadamente
|
||||||
3. Están acopladas a un framework (Laravel Rut y otras hierbas)
|
3. No tienen un buen diseño y sus apis tienen efectos secundarios.
|
||||||
4. No proveen herramientas ni integraciones con librerías de terceros.
|
4. Están acopladas a un framework (Laravel Rut y otras hierbas)
|
||||||
|
5. No proveen herramientas ni integraciones con librerías de terceros, como Doctrine.
|
||||||
### ¿Por qué PHP 7.4?
|
|
||||||
PHP 7.3 ya no tiene mucho tiempo de soporte y 8.0 esta ad portas de ser lanzado. Hay que
|
|
||||||
empujar el ecosistema hacia adelante.
|
|
||||||
|
|||||||
27
compose.yml
Normal file
27
compose.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: "mnavarro"
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
chilean-rut: &php
|
||||||
|
image: mnavarro/chilean-rut:dev
|
||||||
|
build:
|
||||||
|
context: .dev/docker/php
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
target: dev
|
||||||
|
args:
|
||||||
|
UID: ${UID:-1000}
|
||||||
|
user: ${UID:-1000}
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
chilean-rut-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
working_dir: /mnavarro/chilean-rut
|
||||||
|
volumes:
|
||||||
|
- ./:/mnavarro/chilean-rut
|
||||||
|
command: ["php", "-S", "0.0.0.0:8000", "-t", ".dev/coverage"]
|
||||||
|
|
||||||
|
chilean-rut-init:
|
||||||
|
<<: *php
|
||||||
|
depends_on: []
|
||||||
|
restart: no
|
||||||
|
command: [".dev/init"]
|
||||||
@@ -3,39 +3,46 @@
|
|||||||
"description": "PHP Rut Value Object with validation utilities, doctrine type, and other cool features.",
|
"description": "PHP Rut Value Object with validation utilities, doctrine type, and other cool features.",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true,
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Matias Navarro Carter",
|
"name": "Matias Navarro-Carter",
|
||||||
"email": "mnavarro@option.cl"
|
"email": "mnavarrocarter@gmail.com",
|
||||||
|
"role": "Lead Maintainer"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"minimum-stability": "stable",
|
|
||||||
"require": {
|
|
||||||
"php": "^7.4|^8.0"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"friendsofphp/php-cs-fixer": "^2.16",
|
|
||||||
"phpunit/phpunit": "^9.0",
|
|
||||||
"doctrine/dbal": "^2.10.1|^3.0",
|
|
||||||
"symfony/var-dumper": "^5.1",
|
|
||||||
"vimeo/psalm": "^4.2"
|
|
||||||
},
|
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"MNC\\ChileanRut\\": "src/"
|
"MNC\\": "src"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"MNC\\ChileanRut\\": "tests"
|
"MNC\\": "tests"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.2"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^10.5",
|
||||||
|
"friendsofphp/php-cs-fixer": "^3.49",
|
||||||
|
"vimeo/psalm": "^5.22",
|
||||||
|
"doctrine/dbal": "^2.10.1|^3.0"
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "php-cs-fixer fix --allow-risky=yes",
|
"pr": ["@fmt", "@psalm", "@test"],
|
||||||
"pr": [
|
"ci": ["@fmt:check", "@psalm:gh", "@test"],
|
||||||
"php-cs-fixer fix --dry-run -vvv",
|
"fmt": "php-cs-fixer fix --diff --ansi",
|
||||||
"phpunit --testdox --coverage-text",
|
"fmt:check": "php-cs-fixer fix --dry-run --diff --ansi",
|
||||||
"psalm --stats"
|
"test": ["phpunit --colors"],
|
||||||
]
|
"test:unit": "phpunit --colors --exclude-group=integration --exclude-group=e2e",
|
||||||
|
"test:e2e": "phpunit --colors --group=e2e",
|
||||||
|
"test:integration": "phpunit --colors --group=integration",
|
||||||
|
"psalm": "psalm --no-cache --threads=5 --use-baseline",
|
||||||
|
"psalm:gh": "psalm --no-cache --threads=5 --long-progress --output-format=github --use-baseline",
|
||||||
|
"psalm:fix": "psalm --update-baseline",
|
||||||
|
"psalm:allow": "psalm --set-baseline=psalm-baseline.xml"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4635
composer.lock
generated
Normal file
4635
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
phpunit.xml
Normal file
29
phpunit.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
|
||||||
|
bootstrap="vendor/autoload.php"
|
||||||
|
executionOrder="depends,defects"
|
||||||
|
requireCoverageMetadata="true"
|
||||||
|
beStrictAboutCoverageMetadata="true"
|
||||||
|
beStrictAboutOutputDuringTests="true"
|
||||||
|
failOnRisky="true"
|
||||||
|
cacheResultFile="/tmp/phpunit.result.cache"
|
||||||
|
failOnWarning="true">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="main">
|
||||||
|
<directory>tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
|
||||||
|
<source restrictDeprecations="true" restrictNotices="true" restrictWarnings="true">
|
||||||
|
<include>
|
||||||
|
<directory>src</directory>
|
||||||
|
</include>
|
||||||
|
</source>
|
||||||
|
|
||||||
|
<coverage>
|
||||||
|
<report>
|
||||||
|
<html outputDirectory=".dev/coverage"/>
|
||||||
|
</report>
|
||||||
|
</coverage>
|
||||||
|
</phpunit>
|
||||||
8
psalm-baseline.xml
Normal file
8
psalm-baseline.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<files psalm-version="5.22.2@d768d914152dbbf3486c36398802f74e80cfde48">
|
||||||
|
<file src="src/Rut/Doctrine/NumericRutType.php">
|
||||||
|
<ImplementedReturnTypeMismatch>
|
||||||
|
<code><![CDATA[?Rut]]></code>
|
||||||
|
</ImplementedReturnTypeMismatch>
|
||||||
|
</file>
|
||||||
|
</files>
|
||||||
17
psalm.xml
Normal file
17
psalm.xml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<psalm
|
||||||
|
errorLevel="1"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns="https://getpsalm.org/schema/config"
|
||||||
|
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||||
|
findUnusedBaselineEntry="true"
|
||||||
|
findUnusedCode="false"
|
||||||
|
errorBaseline="psalm-baseline.xml"
|
||||||
|
>
|
||||||
|
<projectFiles>
|
||||||
|
<directory name="src" />
|
||||||
|
<ignoreFiles>
|
||||||
|
<directory name="vendor" />
|
||||||
|
</ignoreFiles>
|
||||||
|
</projectFiles>
|
||||||
|
</psalm>
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @project Chilean Rut
|
|
||||||
* @link https://github.com/mnavarrocarter/chilean-rut
|
|
||||||
* @package mnavarrocarter/chilean-rut
|
|
||||||
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
|
||||||
* @license MIT
|
|
||||||
* @copyright 2020 Matias Navarro Carter
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace MNC\ChileanRut;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A FormattedRut encapsulates logic for formatting a Rut.
|
|
||||||
*/
|
|
||||||
class FormattedRut
|
|
||||||
{
|
|
||||||
private const HYPHENED = 1;
|
|
||||||
private const DOTTED = 2;
|
|
||||||
private const OBFUSCATED = 4;
|
|
||||||
|
|
||||||
private Rut $rut;
|
|
||||||
private int $flags;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FormattedRut constructor.
|
|
||||||
*/
|
|
||||||
public function __construct(Rut $rut)
|
|
||||||
{
|
|
||||||
$this->rut = $rut;
|
|
||||||
$this->flags = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hyphened(): FormattedRut
|
|
||||||
{
|
|
||||||
return $this->add(self::HYPHENED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dotted(): FormattedRut
|
|
||||||
{
|
|
||||||
return $this->add(self::DOTTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function obfuscated(): FormattedRut
|
|
||||||
{
|
|
||||||
return $this->add(self::OBFUSCATED);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function add(int $flag): FormattedRut
|
|
||||||
{
|
|
||||||
$clone = clone $this;
|
|
||||||
$clone->flags += $flag;
|
|
||||||
|
|
||||||
return $clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __toString(): string
|
|
||||||
{
|
|
||||||
$number = (string) $this->rut->getNumber();
|
|
||||||
$verifier = $this->rut->getVerifier();
|
|
||||||
if ($this->has(self::OBFUSCATED)) {
|
|
||||||
$replace = str_repeat('*', strlen($number) - 3);
|
|
||||||
$number = substr_replace($number, $replace, 0, -3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->has(self::DOTTED)) {
|
|
||||||
$number = substr_replace($number, '.', -3, 0);
|
|
||||||
$number = substr_replace($number, '.', -7, 0);
|
|
||||||
}
|
|
||||||
if ($this->has(self::HYPHENED)) {
|
|
||||||
return $number.'-'.$verifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $number.$verifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function has(int $flag): bool
|
|
||||||
{
|
|
||||||
return ($this->flags & $flag) !== 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @project Chilean Rut
|
|
||||||
* @link https://github.com/mnavarrocarter/chilean-rut
|
|
||||||
* @package mnavarrocarter/chilean-rut
|
|
||||||
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
|
||||||
* @license MIT
|
|
||||||
* @copyright 2020 Matias Navarro Carter
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace MNC\ChileanRut;
|
|
||||||
|
|
||||||
use InvalidArgumentException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class InvalidRut.
|
|
||||||
*/
|
|
||||||
class InvalidRut extends InvalidArgumentException
|
|
||||||
{
|
|
||||||
public static function number(): InvalidRut
|
|
||||||
{
|
|
||||||
return new self('Rut number cannot be greater than 999.999.999 and smaller than zero');
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function digit(string $digit): InvalidRut
|
|
||||||
{
|
|
||||||
return new self(sprintf('The verifier digit "%s" is not valid', $digit));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
186
src/Rut.php
186
src/Rut.php
@@ -3,83 +3,91 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @project Chilean Rut
|
* @project Chilean RUT
|
||||||
* @link https://github.com/mnavarrocarter/chilean-rut
|
* @link https://github.com/mnavarrocarter/chilean-rut
|
||||||
* @package mnavarrocarter/chilean-rut
|
* @package castor/log
|
||||||
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
* @license MIT
|
* @license MIT
|
||||||
* @copyright 2020 Matias Navarro Carter
|
* @copyright 2024 Matias Navarro-Carter
|
||||||
*
|
*
|
||||||
* For the full copyright and license information, please view the LICENSE
|
* For the full copyright and license information, please view the LICENSE
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace MNC\ChileanRut;
|
namespace MNC;
|
||||||
|
|
||||||
|
use MNC\Rut\Verifier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rut represents a the Chilean National ID Number.
|
* Esta clase representa un RUT.
|
||||||
*
|
*
|
||||||
* All residents of Chile are uniquely identified by one of these and it is
|
* Una vez creado, el RUT es siempre valido
|
||||||
* mainly used for tax purposes.
|
|
||||||
*/
|
*/
|
||||||
class Rut
|
final readonly class Rut
|
||||||
{
|
{
|
||||||
private const VALID_VERIFIERS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'K'];
|
private const MAX_NUMBER = 999_999_999;
|
||||||
|
private const MIN_NUMBER = 0;
|
||||||
|
|
||||||
|
private function __construct(
|
||||||
|
public int $number,
|
||||||
|
public Verifier $verifier
|
||||||
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The actual RUT number.
|
* Parsea un objeto RUT a partir de una cadena de texto.
|
||||||
|
*
|
||||||
|
* El RUT DEBE contener el digito verificador.
|
||||||
|
*
|
||||||
|
* Si no se cuenta con el verificador, el metodo create debe ser usado.
|
||||||
|
*
|
||||||
|
* @see Rut::create
|
||||||
|
*
|
||||||
|
* @throws Rut\IsInvalid si el RUT no es valido
|
||||||
*/
|
*/
|
||||||
private int $number;
|
|
||||||
/**
|
|
||||||
* The RUT verifier digit.
|
|
||||||
*/
|
|
||||||
private string $verifier;
|
|
||||||
|
|
||||||
public static function parse(string $rut): Rut
|
public static function parse(string $rut): Rut
|
||||||
{
|
{
|
||||||
// Remove space, dots and hyphens
|
// Remove space, dots and hyphens
|
||||||
$rut = str_replace([' ', '.', '-'], '', $rut);
|
$rut = \str_replace([' ', '.', '-'], '', $rut);
|
||||||
|
|
||||||
return new self(
|
return self::create(
|
||||||
(int) substr($rut, 0, -1),
|
(int) \substr($rut, 0, -1),
|
||||||
substr($rut, -1)
|
Verifier::fromString(\substr($rut, -1))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a valid rut out of a number.
|
* Crea un objeto RUT.
|
||||||
*/
|
|
||||||
public static function create(int $number): Rut
|
|
||||||
{
|
|
||||||
$verifier = self::calculateVerifier($number);
|
|
||||||
|
|
||||||
return new Rut($number, $verifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rut constructor.
|
|
||||||
*
|
*
|
||||||
* @throws InvalidRut if the verifier digit is invalid
|
* El digito verificador es opcional. Cuando es recibido, es validado.
|
||||||
|
*
|
||||||
|
* Si el digito verificador no es provisto, es generado automáticamente.
|
||||||
|
*
|
||||||
|
* @throws Rut\IsInvalid si el Rut es invalido
|
||||||
*/
|
*/
|
||||||
public function __construct(int $number, string $verifier)
|
public static function create(int $number, ?Verifier $verifier = null): self
|
||||||
{
|
{
|
||||||
$this->number = $number;
|
if ($number < self::MIN_NUMBER) {
|
||||||
$this->verifier = strtoupper($verifier);
|
throw Rut\IsInvalid::numberTooSmall($number);
|
||||||
$this->guard();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNumber(): int
|
if ($number > self::MAX_NUMBER) {
|
||||||
{
|
throw Rut\IsInvalid::numberTooBig($number);
|
||||||
return $this->number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getVerifier(): string
|
$computed = self::computeVerifier($number);
|
||||||
{
|
if ($verifier === null) {
|
||||||
return $this->verifier;
|
return new self($number, $computed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($computed !== $verifier) {
|
||||||
|
throw Rut\IsInvalid::rut($number, $verifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new self($number, $verifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares whether a Rut is equal to another or not.
|
* Compara si un RUT es igual a otro o no.
|
||||||
*/
|
*/
|
||||||
public function equals(Rut $rut): bool
|
public function equals(Rut $rut): bool
|
||||||
{
|
{
|
||||||
@@ -87,38 +95,71 @@ class Rut
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a Rut to a string.
|
* Retorna el RUT en formato "12345678K".
|
||||||
*/
|
*/
|
||||||
public function format(): FormattedRut
|
public function toString(): string
|
||||||
{
|
{
|
||||||
return new FormattedRut($this);
|
return $this->number.$this->verifier->toString();
|
||||||
}
|
|
||||||
|
|
||||||
private function guard(): void
|
|
||||||
{
|
|
||||||
// Check if rut is between zero and 999.999.999
|
|
||||||
if ($this->number < 0 || $this->number > 999_999_999) {
|
|
||||||
throw InvalidRut::number();
|
|
||||||
}
|
|
||||||
// Check if the verifier digit is in the range of valid ones
|
|
||||||
if (!in_array($this->verifier, self::VALID_VERIFIERS, true)) {
|
|
||||||
throw InvalidRut::digit($this->verifier);
|
|
||||||
}
|
|
||||||
// Check the verifier is algorithmically correct
|
|
||||||
if ($this->verifier !== self::calculateVerifier($this->number)) {
|
|
||||||
throw InvalidRut::digit($this->verifier);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates a verifier digit from a number.
|
* Retorna el RUT en formato "12345678-K".
|
||||||
*/
|
*/
|
||||||
private static function calculateVerifier(int $number): string
|
public function toSimple(): string
|
||||||
{
|
{
|
||||||
/** @var list<int> $sequence */
|
return $this->number.'-'.$this->verifier->toString();
|
||||||
$sequence = array_filter(array_reverse(str_split((string) $number)), function ($d) {
|
}
|
||||||
return preg_match('/\d/', $d);
|
|
||||||
});
|
/**
|
||||||
|
* Retorna el RUT en formato "12.345.678-K".
|
||||||
|
*/
|
||||||
|
public function toHuman(): string
|
||||||
|
{
|
||||||
|
return \number_format($this->number, 0, ',', '.').'-'.$this->verifier->toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retorna los $n ultimos numeros del RUT.
|
||||||
|
*
|
||||||
|
* El digito verificador no es considerado.
|
||||||
|
*/
|
||||||
|
public function last(int $n, string $pad = ''): string
|
||||||
|
{
|
||||||
|
$number = (string) $this->number;
|
||||||
|
$last = \substr($number, -$n);
|
||||||
|
if ($pad !== '') {
|
||||||
|
$last = \str_repeat($pad, \strlen($number) - $n).$last;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $last;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retorna los $n primeros numeros del RUT.
|
||||||
|
*
|
||||||
|
* El digito verificador no es considerado.
|
||||||
|
*/
|
||||||
|
public function first(int $n, string $pad = ''): string
|
||||||
|
{
|
||||||
|
$number = (string) $this->number;
|
||||||
|
$first = \substr($number, 0, $n);
|
||||||
|
if ($pad !== '') {
|
||||||
|
$first .= \str_repeat($pad, \strlen($number) - $n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $first;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computa el digito verificador de un RUT a partir del numero.
|
||||||
|
*/
|
||||||
|
public static function computeVerifier(int $number): Verifier
|
||||||
|
{
|
||||||
|
$sequence = \array_reverse(\array_map(
|
||||||
|
static fn (string $d): int => (int) $d,
|
||||||
|
\str_split((string) $number)
|
||||||
|
));
|
||||||
|
|
||||||
$x = 2;
|
$x = 2;
|
||||||
$s = 0;
|
$s = 0;
|
||||||
foreach ($sequence as $digit) {
|
foreach ($sequence as $digit) {
|
||||||
@@ -128,14 +169,7 @@ class Rut
|
|||||||
$s += $digit * $x;
|
$s += $digit * $x;
|
||||||
++$x;
|
++$x;
|
||||||
}
|
}
|
||||||
$dv = 11 - ($s % 11);
|
|
||||||
if ($dv === 10) {
|
|
||||||
$dv = 'K';
|
|
||||||
}
|
|
||||||
if ($dv === 11) {
|
|
||||||
$dv = '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
return (string) $dv;
|
return Verifier::from(11 - ($s % 11));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,29 +3,26 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @project Chilean Rut
|
* @project Chilean RUT
|
||||||
* @link https://github.com/mnavarrocarter/chilean-rut
|
* @link https://github.com/mnavarrocarter/chilean-rut
|
||||||
* @package mnavarrocarter/chilean-rut
|
* @package castor/log
|
||||||
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
* @license MIT
|
* @license MIT
|
||||||
* @copyright 2020 Matias Navarro Carter
|
* @copyright 2024 Matias Navarro-Carter
|
||||||
*
|
*
|
||||||
* For the full copyright and license information, please view the LICENSE
|
* For the full copyright and license information, please view the LICENSE
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace MNC\ChileanRut\Doctrine;
|
namespace MNC\Rut\Doctrine;
|
||||||
|
|
||||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
use Doctrine\DBAL\Types\ConversionException;
|
use Doctrine\DBAL\Types\ConversionException;
|
||||||
use Doctrine\DBAL\Types\IntegerType;
|
use Doctrine\DBAL\Types\IntegerType;
|
||||||
use MNC\ChileanRut\Rut;
|
use MNC\Rut;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class NumericRutType.
|
* Mapea el Rut a una columna integer.
|
||||||
*
|
|
||||||
* This type maps the rut to a number table and stores it without the verifier
|
|
||||||
* digit. This is because the digit is derived from the number.
|
|
||||||
*/
|
*/
|
||||||
class NumericRutType extends IntegerType
|
class NumericRutType extends IntegerType
|
||||||
{
|
{
|
||||||
@@ -39,18 +36,16 @@ class NumericRutType extends IntegerType
|
|||||||
/**
|
/**
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
*
|
||||||
* @return mixed
|
|
||||||
*
|
|
||||||
* @throws ConversionException
|
* @throws ConversionException
|
||||||
*/
|
*/
|
||||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
|
||||||
{
|
{
|
||||||
if ($value === null) {
|
if ($value === null) {
|
||||||
return $value;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($value instanceof Rut) {
|
if ($value instanceof Rut) {
|
||||||
return (string) $value->getNumber();
|
return (string) $value->number;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', Rut::class]);
|
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', Rut::class]);
|
||||||
@@ -59,16 +54,21 @@ class NumericRutType extends IntegerType
|
|||||||
/**
|
/**
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @throws ConversionException
|
||||||
*/
|
*/
|
||||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
public function convertToPHPValue($value, AbstractPlatform $platform): ?Rut
|
||||||
{
|
{
|
||||||
$value = parent::convertToPHPValue($value, $platform);
|
$value = parent::convertToPHPValue($value, $platform);
|
||||||
|
|
||||||
if ($value === null) {
|
if ($value === null) {
|
||||||
return $value;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Rut::create($value);
|
return Rut::create($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function requiresSQLCommentHint(AbstractPlatform $platform): true
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,29 +3,26 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @project Chilean Rut
|
* @project Chilean RUT
|
||||||
* @link https://github.com/mnavarrocarter/chilean-rut
|
* @link https://github.com/mnavarrocarter/chilean-rut
|
||||||
* @package mnavarrocarter/chilean-rut
|
* @package castor/log
|
||||||
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
* @license MIT
|
* @license MIT
|
||||||
* @copyright 2020 Matias Navarro Carter
|
* @copyright 2024 Matias Navarro-Carter
|
||||||
*
|
*
|
||||||
* For the full copyright and license information, please view the LICENSE
|
* For the full copyright and license information, please view the LICENSE
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace MNC\ChileanRut\Doctrine;
|
namespace MNC\Rut\Doctrine;
|
||||||
|
|
||||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
use Doctrine\DBAL\Types\ConversionException;
|
use Doctrine\DBAL\Types\ConversionException;
|
||||||
use Doctrine\DBAL\Types\StringType;
|
use Doctrine\DBAL\Types\StringType;
|
||||||
use MNC\ChileanRut\Rut;
|
use MNC\Rut;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RutTextType.
|
* Mapea el RUT a una columna VARCHAR.
|
||||||
*
|
|
||||||
* This type maps the rut to a string and stores it with the verifier number,
|
|
||||||
* including dots and the hyphen.
|
|
||||||
*/
|
*/
|
||||||
class RutType extends StringType
|
class RutType extends StringType
|
||||||
{
|
{
|
||||||
@@ -39,18 +36,16 @@ class RutType extends StringType
|
|||||||
/**
|
/**
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
*
|
||||||
* @return mixed
|
|
||||||
*
|
|
||||||
* @throws ConversionException
|
* @throws ConversionException
|
||||||
*/
|
*/
|
||||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
|
||||||
{
|
{
|
||||||
if ($value === null) {
|
if ($value === null) {
|
||||||
return $value;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($value instanceof Rut) {
|
if ($value instanceof Rut) {
|
||||||
return (string) $value->format()->hyphened()->dotted();
|
return $value->toHuman();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', Rut::class]);
|
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', Rut::class]);
|
||||||
@@ -59,20 +54,23 @@ class RutType extends StringType
|
|||||||
/**
|
/**
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
*
|
||||||
* @return mixed
|
|
||||||
*
|
|
||||||
* @throws ConversionException
|
* @throws ConversionException
|
||||||
*/
|
*/
|
||||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
public function convertToPHPValue($value, AbstractPlatform $platform): ?Rut
|
||||||
{
|
{
|
||||||
if ($value === null) {
|
if ($value === null) {
|
||||||
return $value;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($value)) {
|
if (\is_string($value)) {
|
||||||
return Rut::parse($value);
|
return Rut::parse($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string']);
|
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'string']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function requiresSQLCommentHint(AbstractPlatform $platform): true
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
53
src/Rut/IsInvalid.php
Normal file
53
src/Rut/IsInvalid.php
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @project Chilean RUT
|
||||||
|
* @link https://github.com/mnavarrocarter/chilean-rut
|
||||||
|
* @package castor/log
|
||||||
|
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
|
* @license MIT
|
||||||
|
* @copyright 2024 Matias Navarro-Carter
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace MNC\Rut;
|
||||||
|
|
||||||
|
class IsInvalid extends \InvalidArgumentException
|
||||||
|
{
|
||||||
|
public static function numberTooBig(int $number): IsInvalid
|
||||||
|
{
|
||||||
|
return new self(\sprintf(
|
||||||
|
'El RUT numero %d es mayor a 99.999.999',
|
||||||
|
$number
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function numberTooSmall(int $number): IsInvalid
|
||||||
|
{
|
||||||
|
return new self(\sprintf(
|
||||||
|
'El RUT numero %d es menor a cero',
|
||||||
|
$number
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function rut(int $number, Verifier $verifier): IsInvalid
|
||||||
|
{
|
||||||
|
return new self(\sprintf(
|
||||||
|
'El digito verificador %s no es valido para el rut %d',
|
||||||
|
$verifier->toString(),
|
||||||
|
$number
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function verifier(string $verifier): IsInvalid
|
||||||
|
{
|
||||||
|
return new self(\sprintf(
|
||||||
|
'Encontrado un digito verificador invalido con valor %s',
|
||||||
|
$verifier,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
78
src/Rut/Verifier.php
Normal file
78
src/Rut/Verifier.php
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @project Chilean RUT
|
||||||
|
* @link https://github.com/mnavarrocarter/chilean-rut
|
||||||
|
* @package castor/log
|
||||||
|
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
|
* @license MIT
|
||||||
|
* @copyright 2024 Matias Navarro-Carter
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace MNC\Rut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representa el digito verificador de un RUT.
|
||||||
|
*
|
||||||
|
* Internamente, se guarda el modulo del RUT, y no su valor como texto.
|
||||||
|
*/
|
||||||
|
enum Verifier: int
|
||||||
|
{
|
||||||
|
case One = 1;
|
||||||
|
case Two = 2;
|
||||||
|
case Three = 3;
|
||||||
|
case Four = 4;
|
||||||
|
case Five = 5;
|
||||||
|
case Six = 6;
|
||||||
|
case Seven = 7;
|
||||||
|
case Eight = 8;
|
||||||
|
case Nine = 9;
|
||||||
|
case K = 10;
|
||||||
|
case Zero = 11;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws IsInvalid si el verificador es invalido
|
||||||
|
*/
|
||||||
|
public static function fromString(string $v): Verifier
|
||||||
|
{
|
||||||
|
return match ($v) {
|
||||||
|
'1' => self::One,
|
||||||
|
'2' => self::Two,
|
||||||
|
'3' => self::Three,
|
||||||
|
'4' => self::Four,
|
||||||
|
'5' => self::Five,
|
||||||
|
'6' => self::Six,
|
||||||
|
'7' => self::Seven,
|
||||||
|
'8' => self::Eight,
|
||||||
|
'9' => self::Nine,
|
||||||
|
'0' => self::Zero,
|
||||||
|
'K' => self::K,
|
||||||
|
default => throw IsInvalid::verifier($v)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retorna la representacion textual del digito verificador.
|
||||||
|
*/
|
||||||
|
public function toString(): string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::One => '1',
|
||||||
|
self::Two => '2',
|
||||||
|
self::Three => '3',
|
||||||
|
self::Four => '4',
|
||||||
|
self::Five => '5',
|
||||||
|
self::Six => '6',
|
||||||
|
self::Seven => '7',
|
||||||
|
self::Eight => '8',
|
||||||
|
self::Nine => '9',
|
||||||
|
self::K => 'K',
|
||||||
|
self::Zero => '0',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace MNC\ChileanRut;
|
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class FormattedRutTest
|
|
||||||
* @package MNC\ChileanRut
|
|
||||||
*/
|
|
||||||
class FormattedRutTest extends TestCase
|
|
||||||
{
|
|
||||||
public function testItFormatsHyphened(): void
|
|
||||||
{
|
|
||||||
$formatted = (string) Rut::parse('168943652')->format()->hyphened();
|
|
||||||
self::assertSame('16894365-2', $formatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItFormatsDotted(): void
|
|
||||||
{
|
|
||||||
$formatted = (string) Rut::parse('168943652')->format()->dotted();
|
|
||||||
self::assertSame('16.894.3652', $formatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItFormatsHyphenedAndDotted(): void
|
|
||||||
{
|
|
||||||
$formatted = (string) Rut::parse('168943652')->format()->hyphened()->dotted();
|
|
||||||
self::assertSame('16.894.365-2', $formatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItFormatsObfuscated(): void
|
|
||||||
{
|
|
||||||
$formatted = (string) Rut::parse('168943652')->format()->obfuscated();
|
|
||||||
self::assertSame('*****3652', $formatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItFormatsObfuscatedAndHyphened(): void
|
|
||||||
{
|
|
||||||
$formatted = (string) Rut::parse('168943652')->format()->hyphened()->obfuscated();
|
|
||||||
self::assertSame('*****365-2', $formatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItFormatsObfuscatedAndDotted(): void
|
|
||||||
{
|
|
||||||
$formatted = (string) Rut::parse('168943652')->format()->obfuscated()->dotted();
|
|
||||||
self::assertSame('**.***.3652', $formatted);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItFormatsWithAll(): void
|
|
||||||
{
|
|
||||||
$formatted = (string) Rut::parse('168943652')->format()->hyphened()->dotted()->obfuscated();
|
|
||||||
self::assertSame('**.***.365-2', $formatted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace MNC\ChileanRut\Doctrine;
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @project Chilean RUT
|
||||||
|
* @link https://github.com/mnavarrocarter/chilean-rut
|
||||||
|
* @package castor/log
|
||||||
|
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
|
* @license MIT
|
||||||
|
* @copyright 2024 Matias Navarro-Carter
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace MNC\Rut\Doctrine;
|
||||||
|
|
||||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
use Doctrine\DBAL\Types\ConversionException;
|
use Doctrine\DBAL\Types\ConversionException;
|
||||||
use Doctrine\DBAL\Types\Type;
|
use Doctrine\DBAL\Types\Type;
|
||||||
use MNC\ChileanRut\Rut;
|
use MNC\Rut;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
#[CoversClass(NumericRutType::class)]
|
||||||
|
#[CoversClass(Rut::class)]
|
||||||
|
#[CoversClass(Rut\Verifier::class)]
|
||||||
class NumericRutTypeTest extends TestCase
|
class NumericRutTypeTest extends TestCase
|
||||||
{
|
{
|
||||||
public static function setUpBeforeClass(): void
|
public static function setUpBeforeClass(): void
|
||||||
@@ -54,4 +73,11 @@ class NumericRutTypeTest extends TestCase
|
|||||||
$this->expectException(ConversionException::class);
|
$this->expectException(ConversionException::class);
|
||||||
$type->convertToDatabaseValue(new \DateTime(), $platform);
|
$type->convertToDatabaseValue(new \DateTime(), $platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function it_returns_true_for_comment(): void
|
||||||
|
{
|
||||||
|
$platform = $this->createMock(AbstractPlatform::class);
|
||||||
|
$this->assertTrue(Type::getType(NumericRutType::NAME)->requiresSQLCommentHint($platform));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,32 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace MNC\ChileanRut\Doctrine;
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @project Chilean RUT
|
||||||
|
* @link https://github.com/mnavarrocarter/chilean-rut
|
||||||
|
* @package castor/log
|
||||||
|
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
|
* @license MIT
|
||||||
|
* @copyright 2024 Matias Navarro-Carter
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace MNC\Rut\Doctrine;
|
||||||
|
|
||||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||||
use Doctrine\DBAL\Types\ConversionException;
|
use Doctrine\DBAL\Types\ConversionException;
|
||||||
use Doctrine\DBAL\Types\Type;
|
use Doctrine\DBAL\Types\Type;
|
||||||
use MNC\ChileanRut\Rut;
|
use MNC\Rut;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
#[CoversClass(RutType::class)]
|
||||||
|
#[CoversClass(Rut::class)]
|
||||||
|
#[CoversClass(Rut\Verifier::class)]
|
||||||
class RutTypeTest extends TestCase
|
class RutTypeTest extends TestCase
|
||||||
{
|
{
|
||||||
public static function setUpBeforeClass(): void
|
public static function setUpBeforeClass(): void
|
||||||
@@ -62,4 +81,11 @@ class RutTypeTest extends TestCase
|
|||||||
$this->expectException(ConversionException::class);
|
$this->expectException(ConversionException::class);
|
||||||
$type->convertToDatabaseValue(new \DateTime(), $platform);
|
$type->convertToDatabaseValue(new \DateTime(), $platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Test]
|
||||||
|
public function it_returns_true_for_comment(): void
|
||||||
|
{
|
||||||
|
$platform = $this->createMock(AbstractPlatform::class);
|
||||||
|
$this->assertTrue(Type::getType(RutType::NAME)->requiresSQLCommentHint($platform));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,87 +1,107 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
declare(strict_types=1);
|
||||||
* This file is part of the MNC\ChileanRut library.
|
|
||||||
|
/**
|
||||||
|
* @project Chilean RUT
|
||||||
|
* @link https://github.com/mnavarrocarter/chilean-rut
|
||||||
|
* @package castor/log
|
||||||
|
* @author Matias Navarro-Carter mnavarrocarter@gmail.com
|
||||||
|
* @license MIT
|
||||||
|
* @copyright 2024 Matias Navarro-Carter
|
||||||
*
|
*
|
||||||
* (c) Matías Navarro Carter <mnavarrocarter@gmail.com>
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
* For the full copyright and license information, please view the LICENSE
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace MNC\ChileanRut;
|
namespace MNC;
|
||||||
|
|
||||||
|
use MNC\Rut\IsInvalid;
|
||||||
|
use MNC\Rut\Verifier;
|
||||||
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
|
use PHPUnit\Framework\Attributes\DataProvider;
|
||||||
|
use PHPUnit\Framework\Attributes\Test;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
/**
|
#[CoversClass(Rut::class)]
|
||||||
* Class RutTest
|
#[CoversClass(IsInvalid::class)]
|
||||||
* @package MNC\ChileanRut\Tests\Rut
|
#[CoversClass(Verifier::class)]
|
||||||
*/
|
|
||||||
class RutTest extends TestCase
|
class RutTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
#[Test]
|
||||||
* @dataProvider getRutDataset
|
#[DataProvider('getParseData')]
|
||||||
* @param string $raw
|
public function it_parses_ruts(string $raw, int $expectedNumber, Verifier $expectedVerifier): void
|
||||||
* @param int $expectedNumber
|
|
||||||
* @param string $expectedVerifier
|
|
||||||
*/
|
|
||||||
public function testItParsesRuts(string $raw, int $expectedNumber, string $expectedVerifier): void
|
|
||||||
{
|
{
|
||||||
$rut = Rut::parse($raw);
|
$rut = Rut::parse($raw);
|
||||||
self::assertSame($expectedNumber, $rut->getNumber());
|
$this->assertSame($expectedNumber, $rut->number);
|
||||||
self::assertSame($expectedVerifier, $rut->getVerifier());
|
$this->assertSame($expectedVerifier, $rut->verifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItDetectsOutOfRangeVerifier(): void
|
#[Test]
|
||||||
|
#[DataProvider('getParseWithErrorData')]
|
||||||
|
public function it_parses_with_error(string $raw, string $expectedError): void
|
||||||
{
|
{
|
||||||
$this->expectException(InvalidRut::class);
|
$this->expectException(IsInvalid::class);
|
||||||
Rut::parse('16894365F');
|
$this->expectExceptionMessage($expectedError);
|
||||||
|
Rut::parse($raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItDetectsInvalidVerifier(): void
|
#[Test]
|
||||||
|
public function it_cannot_be_negative(): void
|
||||||
{
|
{
|
||||||
$this->expectException(InvalidRut::class);
|
$this->expectException(IsInvalid::class);
|
||||||
Rut::parse('16894365K');
|
$this->expectExceptionMessage('El RUT numero -22224525 es menor a cero');
|
||||||
|
Rut::create(-22_224_525);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testItDetectsRutTooBig(): void
|
#[Test]
|
||||||
{
|
public function it_checks_for_equality(): void
|
||||||
$this->expectException(InvalidRut::class);
|
|
||||||
Rut::create(3_355_535_353);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testItComparesToEqual(): void
|
|
||||||
{
|
{
|
||||||
$rut1 = Rut::parse('168943652');
|
$rut1 = Rut::parse('168943652');
|
||||||
$rut2 = Rut::parse('16.894.365-2');
|
$rut2 = Rut::parse('16.894.365-2');
|
||||||
$rut3 = Rut::create(22_224_525);
|
$rut3 = Rut::create(22_224_525);
|
||||||
self::assertTrue($rut1->equals($rut2));
|
$this->assertTrue($rut1->equals($rut2));
|
||||||
self::assertFalse($rut1->equals($rut3));
|
$this->assertFalse($rut1->equals($rut3));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function testItCreatesARut(): void
|
#[Test]
|
||||||
|
public function it_creates_with_no_verifier(): void
|
||||||
{
|
{
|
||||||
$rut = Rut::create(22_457_309);
|
$rut = Rut::create(22_457_309);
|
||||||
self::assertSame(22_457_309, $rut->getNumber());
|
$this->assertSame(22_457_309, $rut->number);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function testItCanFormatRut(): void
|
#[Test]
|
||||||
|
public function it_formats(): void
|
||||||
{
|
{
|
||||||
$rut = (string) Rut::create(22_457_309)->format();
|
$rut = Rut::create(22_457_309);
|
||||||
self::assertSame('22457309K', $rut);
|
$this->assertSame('22457309K', $rut->toString());
|
||||||
|
$this->assertSame('22457309-K', $rut->toSimple());
|
||||||
|
$this->assertSame('22.457.309-K', $rut->toHuman());
|
||||||
|
$this->assertSame('7309', $rut->last(4));
|
||||||
|
$this->assertSame('****7309', $rut->last(4, '*'));
|
||||||
|
$this->assertSame('2245', $rut->first(4));
|
||||||
|
$this->assertSame('2245****', $rut->first(4, '*'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static function getParseData(): array
|
||||||
* @return array[]
|
|
||||||
*/
|
|
||||||
public function getRutDataset(): array
|
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
['16.894.365-2', 16_894_365, '2'],
|
['16.894.365-2', 16_894_365, Verifier::Two],
|
||||||
['24 736.7322', 24_736_732, '2'],
|
['24 736.7322', 24_736_732, Verifier::Two],
|
||||||
[' 24 232.. 442 -- 0', 24_232_442, '0'],
|
[' 24 232.. 442 -- 0', 24_232_442, Verifier::Zero],
|
||||||
['35323325', 3_532_332, '5'],
|
['35323325', 3_532_332, Verifier::Five],
|
||||||
['22.457.309K', 22_457_309, 'K'],
|
['22.457.309K', 22_457_309, Verifier::K],
|
||||||
['15450088K', 15450088, 'K']
|
['15450088K', 15_450_088, Verifier::K],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getParseWithErrorData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
['212321312321-1', 'El RUT numero 212321312321 es mayor a 99.999.999'],
|
||||||
|
['23.232.123-K', 'El digito verificador K no es valido para el rut 23232123'],
|
||||||
|
['12.2324.232-P', 'Encontrado un digito verificador invalido con valor P'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user