<?php
class Number
{
/**
* Assert if a number can be validate using Luhn Checksum
*
* Applies to :
* Can be applid to : Siren, Siret, Credit card number, IMEI Number
* Modulo can be overrided for custom control
* simpleSum just sum all digits...
*
* @todo est-ce que l'on garde la somme simple au milieu de luhn...
*
* @param string|int $number
* @param int $modulo
* @param boolean $simpleSum
* @return bool
*/
public static function assertLuhn($number, $modulo = 10, $simpleSum = false)
{
// Must be numeric and not a float
if (!is_numeric($number) || is_float($number)) {
return false;
}
// Begin Luhn Check
$digits = array_reverse(str_split((string) $number));
$count = count($digits);
$total = 0;
for ($i = 0; $i < $count; ++$i) {
if (($i + 1) % 2 !== 0 || $simpleSum) {
$total += (int) $digits[$i];
} else {
$total += array_sum(str_split((string) ((int) $digits[$i] * 2)));
}
}
return $total % $modulo === 0;
}
/**
* Assert if a number is a valid siren
*
* @param string|int $number
* @return bool
*/
public static function assertSiren($number)
{
if (!self::assertLuhn($number)) {
return false;
}
if (strlen($number) > 9 || strlen($number) < 5) {
return false;
}
if (substr($number, 0, 5) === '00000') {
return false;
}
return true;
}
/**
* Assert if a number is a valid siren
*
* @param string|int $number
* @return bool
*/
public static function assertSiret($number)
{
// @todo : extraction siren à mettre ailleurs
$siren = substr($number, 0, 9);
$modulo = 10;
$simpleSum = false;
// Le cas de "la poste", il y a plus de 10 000 etablissement, le modulo 10 ne fonctionne pas
// Le modulo 5 est utilisé à la place
// Sauf pour 35600000000048 qui est un siret validé avec luhn
if ((int) $siren === 356000000 && (int) $number !== 35600000000048) {
$modulo = 5;
$simpleSum = true;
}
if (!self::assertSiren($siren) || !self::assertLuhn($number, $modulo, $simpleSum)) {
return false;
}
if (strlen($number) > 14 || strlen($number) < 10) {
return false;
}
return true;
}
}
// (FR)?[0-9A-Z]{2}[0-9]{9}
preg_match('/(FR)?[0-9A-Z]{2}[0-9]{9}/', 'FR 52 056800659', $matches);
var_export(Number::assertSiret(str_replace(' ', '', '056 800 659 00155')));
var_export($matches);