Skip to content

Commit

Permalink
Add faker
Browse files Browse the repository at this point in the history
  • Loading branch information
robertogallea committed Jun 14, 2024
1 parent 2ac8a8a commit 15e67f2
Show file tree
Hide file tree
Showing 18 changed files with 341 additions and 122 deletions.
94 changes: 72 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,39 @@
[![Sponsor me!][ico-sponsor]][link-sponsor]
[![Packagist Downloads][ico-downloads]][link-downloads]

laravel-codicefiscale is a package for the management of the Italian `CodiceFiscale` (i.e. tax code).
The package allows easy validation and parsing of the CodiceFiscale. It is also suited for Laravel since it provides a
laravel-codicefiscale is a package for the management of the Italian `CodiceFiscale` (i.e. tax code).
The package allows easy validation and parsing of the CodiceFiscale. It is also suited for Laravel since it provides a
convenient custom validator for request validation.

> **Important update**: now you can dynamically load city codes from ISTAT using the non-default `IstatRemoteCSVList` city decoder.
## Laravel Version Compatibility

| Laravel | Package |
|---------|---------|
| 11.x | 2.x |
| 10.x | 1.x |
| 9.x | 1.x |
| 8.x | 1.x |
| 7.x | 1.x |
| 6.x | 1.x |

> **Important update**: now you can dynamically load city codes from ISTAT using the non-default `IstatRemoteCSVList`
> city decoder.
- [Installation](#installation)
- [Configuration](#configuration)
- [Validation](#validation)
- [Utility CodiceFiscale class](#utility-codicefiscale-class)
- [Codice fiscale Generation](#codice-fiscale-generation)
- [Faker integration](#faker-integration)
- [City code parsing](#city-code-parsing)
- [Integrate your own cities](#integrate-your-own-cities)



## Installation

Run the following command to install the latest applicable version of the package:

```bash
composer require robertogallea/laravel-codicefiscale
composer require robertogallea/laravel-codicefiscale:^2
```

### Laravel
Expand All @@ -44,7 +55,8 @@ In your app config, add the Service Provider to the `$providers` array *(only fo
],
```

The validation error messages are translated in `it` and `en` languages, if you want to add new language please send me a PR.
The validation error messages are translated in `it` and `en` languages, if you want to add new language please send me
a PR.

### Lumen

Expand All @@ -66,14 +78,15 @@ php artisan vendor:publish --provider="robertogallea\LaravelCodiceFiscale\Codice

You can configure the following parameters:

- `city-decoder`: the class used for decoding city codes (see [City code parsing](#city-code-parsing)), default to
- `city-decoder`: the class used for decoding city codes (see [City code parsing](#city-code-parsing)), default to
`InternationalCitiesStaticList`.
- `date-format`: the date format used for parsing birthdates, default to `'Y-m-d'`.
- `labels`: the labels used for `male` and `female` persons, defaults to `'M'` and `'F'`.

## Language Files

You can customize the validation messages publishing the validation translations with this command:

```
php artisan vendor:publish --provider="robertogallea\LaravelCodiceFiscale\CodiceFiscaleServiceProvider" --tag="lang"
```
Expand All @@ -93,7 +106,7 @@ To validate a codice fiscale, use the `codice_fiscale` keyword in your validatio
}
```

From version **1.9.0** you can validate your codice fiscale against other form fields to check whether there is a match
From version **1.9.0** you can validate your codice fiscale against other form fields to check whether there is a match
or not.

You must specify all of the required fields:
Expand Down Expand Up @@ -128,8 +141,8 @@ Validation fails if the provided codicefiscale and the one generated from the in

## Utility CodiceFiscale class

A codice fiscale can be wrapped in the `robertogallea\LaravelCodiceFiscale\CodiceFiscale` class to enhance it with
useful utility methods.
A codice fiscale can be wrapped in the `robertogallea\LaravelCodiceFiscale\CodiceFiscale` class to enhance it with
useful utility methods.

```php
use robertogallea\LaravelCodiceFiscale\CodiceFiscale;
Expand Down Expand Up @@ -160,8 +173,8 @@ In case of a valid codicefiscale it produces the following result:
]
```


in case of an error, `CodiceFiscale::parse()` throws an `CodiceFiscaleValidationException`, which returns one of the defined constants with `$exception->getCode()`:
in case of an error, `CodiceFiscale::parse()` throws an `CodiceFiscaleValidationException`, which returns one of the
defined constants with `$exception->getCode()`:

- `CodiceFiscaleException::NO_ERROR`
- `CodiceFiscaleException::NO_CODE`
Expand All @@ -171,7 +184,6 @@ in case of an error, `CodiceFiscale::parse()` throws an `CodiceFiscaleValidation
- `CodiceFiscaleException::WRONG_CODE`
- `CodiceFiscaleException::MISSING_CITY_CODE`


If you rather not want to catch exceptions, you can use `CodiceFiscale::tryParse()`:

```php
Expand All @@ -187,8 +199,10 @@ if ($result) {
}
```

which returns the same values as above, you can use `$cf->isValid()` to check if the codicefiscale is valid and `$cf->getError()` to get the error.
which returns the same values as above, you can use `$cf->isValid()` to check if the codicefiscale is valid and
`$cf->getError()` to get the error.
This is especially useful in a blade template:

```php
@php($cf = new robertogallea\LaravelCodiceFiscale\CodiceFiscale())
@if($cf->tryParse($codicefiscale))
Expand All @@ -199,7 +213,9 @@ This is especially useful in a blade template:
```

## Codice fiscale Generation

Class <code>CodiceFiscale</code> could be used to generate codice fiscale strings from input values:

```php
$first_name = 'Mario';
$last_name = 'Rossi';
Expand All @@ -210,24 +226,47 @@ $gender = 'M';
$cf_string = CodiceFiscale::generate($first_name, $last_name, $birth_date, $birth_place, $gender);
```

## Faker integration

You can generate fake codice fiscale in your factories using the provided faker extension:

```php
class PersonFactory extends Factory
{

public function definition(): array
{
return [
'first_name' => $firstName = fake()->firstName(),
'last_name' => $lastName = fake()->lastName(),
'fiscal_number' => fake()->fiscalNumber(firstName: $firstName, lastName: $lastName),
];
}
```

**Note**: you can provide some, all or none of the information required for the generation of codice fiscale
(`firstName`, `lastName`, `birthDate`, `birthPlace`, `gender`)

## City code parsing

There are three strategies for decoding the city code:

- `InternationalCitiesStaticList`: a static list of Italian cities;
- `ItalianCitiesStaticList`: a static list of International cities;
- `IstatRemoteCSVList`: a dynamic (loaded from web) list of Italian cities loaded from official ISTAT csv file.
- `IstatRemoteCSVList`: a dynamic (loaded from web) list of Italian cities loaded from official ISTAT csv file.
Please note that the list is cached (one day by default, see config to change).
- `CompositeCitiesList`: merge the results from two `CityDecoderInterface` classes (for example `IstatRemoteCSVList` and
`InternationalCitiesStaticList`) using the base `CityDecoderInterface` in the config key
`InternationalCitiesStaticList`) using the base `CityDecoderInterface` in the config key
`codicefiscale.cities-decoder-list`.

By default, the package uses the class `InternationalCitiesStaticList` to lookup the city from the code and viceversa.
However you could use your own class to change the strategy used.
However you could use your own class to change the strategy used.

You just need to implement the `CityDecoderInterface` and its `getList()` method.
Then, to use it, just pass an istance to the `CodiceFiscale` class.
Then, to use it, just pass an istance to the `CodiceFiscale` class.

For example:

```php
class MyCityList implements CityDecoderInterface
{
Expand All @@ -248,7 +287,7 @@ $cf = new CodiceFiscale(new MyCityList)

_Note_: if you find missing cities, please make a PR!

If you want to integrate the cities list, you can use the `CompositeCitiesList` by merging the results of one of the
If you want to integrate the cities list, you can use the `CompositeCitiesList` by merging the results of one of the
decoders provided and a custom decoder.

For example:
Expand Down Expand Up @@ -284,17 +323,28 @@ class MyCustomList implements CityDecoderInterface
}
```

[ico-author]: https://img.shields.io/static/v1?label=author&message=robgallea&color=50ABF1&logo=twitter&style=flat-square
[ico-author]: https://img.shields.io/static/v1?label=author&message=robgallea&color=50ABF1&logo=twitter&style=flat-square

[ico-release]: https://img.shields.io/github/v/release/robertogallea/laravel-codicefiscale

[ico-downloads]: https://img.shields.io/packagist/dt/robertogallea/laravel-codicefiscale

[ico-laravel]: https://img.shields.io/static/v1?label=laravel&message=%E2%89%A56.0&color=ff2d20&logo=laravel&style=flat-square

[ico-sponsor]: https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&link=https://github.com/sponsors/robertogallea

[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square

[ico-styleci]: https://styleci.io/repos/177130582/shield

[link-author]: https://twitter.com/robgallea

[link-release]: https://github.com/robertogallea/laravel-codicefiscale

[link-downloads]: https://packagist.org/packages/robertogallea/laravel-codicefiscale

[link-laravel]: https://laravel.com

[link-sponsor]: https://github.com/sponsors/robertogallea

[link-styleci]: https://styleci.io/repos/17713058s2/
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
}
],
"require": {
"php": ">=7.4",
"illuminate/support": ">=6.0",
"illuminate/validation": ">=6.0",
"nesbot/carbon": "^2.16",
"php": "^8.2",
"illuminate/support": "^11.0",
"illuminate/validation": "^11.0",
"nesbot/carbon": "^3.5",
"guzzlehttp/guzzle": "^7.3"
},
"require-dev": {
"phpunit/phpunit": ">=9.0",
"orchestra/testbench": ">=6.0",
"orchestra/testbench": "^9.1",
"friendsofphp/php-cs-fixer": "^3.0"
},
"autoload": {
Expand Down
36 changes: 19 additions & 17 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage>
<include>
<directory suffix=".php">./src</directory>
</include>
<report>
<html outputDirectory="./_coverage" lowUpperBound="35" highLowerBound="70"/>
<text outputFile="php://stdout" showUncoveredFiles="true"/>
</report>
</coverage>
<testsuites>
<testsuite name="main">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<logging/>
</phpunit>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.1/phpunit.xsd">
<coverage>
<report>
<html outputDirectory="./_coverage" lowUpperBound="35" highLowerBound="70"/>
<text outputFile="php://stdout" showUncoveredFiles="true"/>
</report>
</coverage>
<testsuites>
<testsuite name="main">
<directory suffix="Test.php">./tests</directory>
</testsuite>
</testsuites>
<logging/>
<source>
<include>
<directory suffix=".php">./src</directory>
</include>
</source>
</phpunit>
32 changes: 16 additions & 16 deletions src/CodiceFiscale.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public function __construct(CityDecoderInterface $cityDecoder = null, CodiceFisc
];
}

public static function generate(string $first_name, string $last_name, $birth_date, string $place, string $gender, CodiceFiscaleConfig $config = null): string
public static function generate(string $first_name, string $last_name, Carbon|string $birth_date, string $place, string $gender, CodiceFiscaleConfig $config = null): string
{
$config = $config ?: resolve(CodiceFiscaleConfig::class);

Expand All @@ -125,7 +125,7 @@ public static function generate(string $first_name, string $last_name, $birth_da
/**
* @returns bool
*/
public function tryParse($cf): bool
public function tryParse(string $cf): bool
{
try {
$this->parse($cf);
Expand All @@ -143,7 +143,7 @@ public function tryParse($cf): bool
*
* @throws CodiceFiscaleValidationException
*/
public function parse($cf): array
public function parse(?string $cf): array
{
$cf = strtoupper($cf);
$this->cf = $cf;
Expand Down Expand Up @@ -191,30 +191,30 @@ public function parse($cf): array
return $this->asArray();
}

public function isValid()
public function isValid(): bool
{
return $this->isValid;
return $this->isValid ?? false;
}

public function getError()
public function getError(): ?\Exception
{
return $this->error;
}

public function getGender()
public function getGender(): ?string
{
return $this->gender;
}

public function getBirthPlace()
public function getBirthPlace(): ?string
{
return $this->birthPlace;
}

public function getBirthPlaceComplete()
public function getBirthPlaceComplete(): ?string
{
if ($this->getBirthPlace() === null) {
return;
return null;
}

if (! array_key_exists($this->getBirthPlace(), $this->cityDecoder->getList())) {
Expand All @@ -236,7 +236,7 @@ public function getBirthdate(): Carbon
}
}

public function getYear()
public function getYear(): ?string
{
$current_year = Carbon::today()->year;
if (2000 + $this->year < $current_year) {
Expand All @@ -246,27 +246,27 @@ public function getYear()
return '19'.$this->year;
}

public function getMonth()
public function getMonth(): ?string
{
return $this->month;
}

public function getDay()
public function getDay(): ?string
{
return $this->day;
}

public function getCodiceFiscale()
public function getCodiceFiscale(): ?string
{
return $this->cf;
}

public function getFirstName()
public function getFirstName(): ?string
{
return substr($this->cf, 3, 3);
}

public function getLastName()
public function getLastName(): ?string
{
return substr($this->cf, 0, 3);
}
Expand Down
Loading

0 comments on commit 15e67f2

Please sign in to comment.