reducktion / socrates Goto Github PK
View Code? Open in Web Editor NEWPHP package to Validate and Extract information from National Identification Numbers.
License: MIT License
PHP package to Validate and Extract information from National Identification Numbers.
License: MIT License
This is a pilot task for the upcoming release: v1.3.0 - The New World.
You can check out the other countries to have an idea on how to implement a country. It's fairly easy from the technical point of view but needs to be backed up with an investigation about the national identifier.
As a rough guide:
As I'm working on the JS/TS/npm port, I'm striving to keep dependencies to a minimum - something that the npm ecosystem is plagued with.
However we ourselves are forcing a dependency on a DateTime
wrapper library that, no matter how great it is, not all projects will use.
PHP's DateTime
class is fine and we should refactor our date handling to it, including Citizen
's return type.
Pretty self explanatory. No reason for these classes to be instantiatable.
No solid leads or good official information was found on how to validate the German Personal Identification Number.
Help is needed to implement it, if possible.
As this repository gets more attention and more people want to contribute, it's more important to make sure we have a robust document explaining what our standards of quality and code style are.
The CONTRIBUTING.md file should have examples on how to properly implement a country, put a PR up and what tools can be used to help verify the code before pushing to the repository.
No solid leads or good official information was found on how to validate the Austrian Personal Identification Number.
Help is needed to implement it, if possible.
Using the Socrates
Facade is extremely convenient; however it does not support autocompletion due to its "static proxy" nature.
We should add method annotations to the Facade to allow IDE autocompletion and provide a better Developer Experience.
InvalidLengthException
is a good example of am internal exception with a nice DX for people contributing to the codebase.
Clearly, our recent contributors know how to use it:
We can go a bit further though and document the constructor with each parameter being described in the constructor, rather than what we have now:
socrates/src/Exceptions/InvalidLengthException.php
Lines 28 to 35 in 1278365
Additionally, we don't need a $designation
field in the class, as it is not being used anywhere else.
These lines of code are a hacky way of detecting if we are pulled in a Laravel project for the purpose of detecting the locale using the framework's App::getLocale()
method:
Lines 72 to 90 in 6b7df4c
The idea was to have a default behaviour in which we would assume that if no country code was passed, then the user was referencing whatever country corresponds to the application's locale (see #84)
However, as mentioned above, not only this is hacky but sort of gimmicky. There's no use for this, so let's remove it.
This problem was found thanks to #57:
public function test_validation_behaviour(): void
{
foreach ($this->validIds as $id) {
$this->assertTrue(
Socrates::validateId($id, 'PT')
);
}
// Here be dragons...
$this->expectException(InvalidLengthException::class);
Socrates::validateId('11084129 8 ZX', 'PT');
// Everything here passes...
$this->assertFalse(
Socrates::validateId('14897475 4 ZY5', 'PT')
);
}
Not only some countries test for a single invalid ID - which isn't ideal - but even those that test with multiple of those have that same problem.
The correct order of assertions should be:
public function test_validation_behaviour(): void
{
foreach ($this->validIds as $id) {
$this->assertTrue(
Socrates::validateId($id, 'PT')
);
}
foreach ($this->invalidIds as $invalidId) {
$this->assertFalse(
Socrates::validateId($invalidId, 'PT')
);
}
$this->expectException(InvalidLengthException::class);
Socrates::validateId('11084129 8 ZX', 'PT');
}
So we need to ahead and fix these tests for all countries.
No solid leads or good official information was found on how to validate the Luxembourger Personal Identification Number.
Help is needed to implement it, if possible.
This is a pilot task for the upcoming release (surprise surprise 🎉 North America is the next addition)..
You can check out the other countries to have an idea on how to implement a country. It's fairly easy from the technical point fo view, but needs to be backed up with an investigation about the national identifier.
As a rough guide:
src/Config/Countries.php
fileCore
directoryIdValidator
or CitizenInformationExtractor
interfaceThere are duplicated cells, as well as erroneous information about which countries support extraction.
Let's fix the table, and move it to the project root for easy access (for lazy people who skim through the docs).
@JoaoFSCruz Would it be possible to relate the issue to the hacktoberfest label? xD
According to this documentation and this wikipedia page, the Luxembourg ID validation is performed by:
This is not what is happening in:
I've been trying to get some real ID's to test it, but I wasn't successful.
Can you check?
The algorithms from this library are specified by national authorities of each country.
For example, for Portugal, one can find the official documents in the Portuguese government official website.
You should add a link to the official document (and the date) you based your calculation on, either in the respective country file or somewhere in the documentation. I think this will be very helpful when using the library, either to identify possible bugs or to simply have additional documentation to check for a particular country.
List of documentation links:
The request validator is currently implemented like so:
// socrates/src/Laravel/SocratesServiceProvider.php
Validator::extend('national_id', function ($attribute, $value, $parameters, $validator) {
$countryCode = strtoupper($parameters[0]);
if (! in_array($countryCode, Countries::$all, true)) {
return false;
}
try {
return app('socrates')->validateId($value, $countryCode);
} catch (\Exception $e) {
return false;
}
}, 'National ID number is invalid.');
This however silences the exception, and doesn't let the framework gracefully handle a ValidationException
like it should.
Most Exceptions in the codebase are very similar and use the same format or messages.
For the sake of simplicity and future maintainability, we should standardise them.
No solid leads or good official information was found on how to validate the Cypriot Personal Identification Number.
Help is needed to implement it, if possible.
Sections which we could/should have:
Related to #75, I see some problems with the current implementation:
See https://github.com/reducktion/socrates-java/pull/36/files for an implementation in the Java fork that does take these things into account.
I'm up for fixing it if you want, please confirm.
This is a pilot task for the upcoming release (surprise surprise 🎉 North America is the next addition).
You can check out the other countries to have an idea on how to implement a country. It's fairly easy from the technical point fo view, but needs to be backed up with an investigation about the national identifier.
As a rough guide:
src/Config/Countries.php
fileCore
directoryIdValidator
or CitizenInformationExtractor
interfaceLet's make a list of the countries to be implemented:
Following this reference documentation (cited in wikipedia) there is the possibility of special digits for the month section of the french national identity card number:
6.3 3 ème composante : mois de naissance (2 chiffres)
codification : de 01 (janvier) à 12 (décembre)
Les mois de naissance fictifs 20 à 30 ou 50 ou plus caractérisent le NIR d'une personne inscrite aurépertoire sur la base d'une pièce d'état civil ne mentionnant pas son mois de naissance (cf.précisions complémentaires).Les mois de naissance "pseudo-fictifs" 31 (janvier) à 42 (décembre) caractérisent le NIR d'unepersonne inscrite au répertoire sur la base d'une pièce d'état civil incomplète mais mentionnanttoutefois un mis de naissance.
from Normalisation du numéro INSEEdes personnes physiques
Which means (if google translate does not fail me) that the following options are available:
It seems to me that the current code will fail with any of the special digits:
private function getDateOfBirth(string $id): Carbon
{
$dateDigits = substr($id, 1, 4);
[$year, $month] = str_split($dateDigits, 2);
$currentYear = (int) now()->format('y');
$year = (int) $year > $currentYear ? (int) $year + 1900 : (int) $year + 2000;
return Carbon::createFromFormat('Y-m', "$year-$month");
}
The extraction should have the month of birth information, even with the 31-42 digits, and ideally not fail (rather be incomplete) on the 20-30 or 50 digits.
We have decided to step away from having Carbon
as a dependency in favor of returning native PHP DateTime
objects.
Changing the methods immediately would be a breaking change, so we have decided to deprecate the existing ones instead and have both options available. Later in another major release the old methods may be removed.
Carbon
returning public API methods{oldMethodName}Native()
methods returning a DateTime
DateTime
assertionsRelated to #86
As one can see in the Java port, it's much better to provide the user with whatever countries are supported rather than have them guess or research what countries can be used:
socrates.validateId('abcd', Country.PT);
As proud as I am of our exception handling for this case, we should create constants for each country and remove it.
e.g.:
$socrates->validateId('xpto', Country::PT);
or
$socrates->validateId('xpto', Country::PORTUGAL);
On the region digits, there is at least one case Metropolitan Lyon which has a letter in the COG.
'69M' => 'Metropolitan Lyon',
But the validation algorithm for France will throw a cast error when trying to parse an id that includes that COG.
public function validate(string $id): bool
{
$id = $this->sanitize($id);
$checksum = (int) substr($id, -2);
$id = substr($id, 0, -2);
$result = 97 - ((int) $id % 97); // cast error for an id like 1510269M02043
return $checksum === $result;
}
I can't find any documentation on how to perform the control digit calculation for a scenario like that though.
No solid leads or good official information was found on how to validate the Belarusian Personal Identification Number.
Help is needed to implement it, if possible.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.