respect-validation/library/Rules/Iban.php
Henrique Moody 642602fd43
Update version of PHPStan packages
Some amazing features had to be ignored because it conflicts with out
coring standards. I hope to soon fix them so we can use PHPStan to its
fullest potential.

Signed-off-by: Henrique Moody <henriquemoody@gmail.com>
2020-07-25 22:50:59 +02:00

153 lines
3.3 KiB
PHP

<?php
/*
* This file is part of Respect/Validation.
*
* (c) Alexandre Gomes Gaigalas <alexandre@gaigalas.net>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/
declare(strict_types=1);
namespace Respect\Validation\Rules;
use function bcmod;
use function is_string;
use function ord;
use function preg_match;
use function preg_replace_callback;
use function str_replace;
use function strlen;
use function substr;
/**
* Validates whether the input is a valid IBAN (International Bank Account Number) or not.
*
* @author Mazen Touati <mazen_touati@hotmail.com>
*/
final class Iban extends AbstractRule
{
private const COUNTRIES_LENGTHS = [
'AL' => 28,
'AD' => 24,
'AT' => 20,
'AZ' => 28,
'BH' => 22,
'BE' => 16,
'BA' => 20,
'BR' => 29,
'BG' => 22,
'CR' => 21,
'HR' => 21,
'CY' => 28,
'CZ' => 24,
'DK' => 18,
'DO' => 28,
'EE' => 20,
'FO' => 18,
'FI' => 18,
'FR' => 27,
'GE' => 22,
'DE' => 22,
'GI' => 23,
'GR' => 27,
'GL' => 18,
'GT' => 28,
'HU' => 28,
'IS' => 26,
'IE' => 22,
'IL' => 23,
'IT' => 27,
'JO' => 30,
'KZ' => 20,
'KW' => 30,
'LV' => 21,
'LB' => 28,
'LI' => 21,
'LT' => 20,
'LU' => 20,
'MK' => 19,
'MT' => 31,
'MR' => 27,
'MU' => 30,
'MD' => 24,
'MC' => 27,
'ME' => 22,
'NL' => 18,
'NO' => 15,
'PK' => 24,
'PL' => 28,
'PS' => 29,
'PT' => 25,
'QA' => 29,
'XK' => 20,
'RO' => 24,
'LC' => 32,
'SM' => 27,
'ST' => 25,
'SA' => 24,
'RS' => 22,
'SC' => 31,
'SK' => 24,
'SI' => 19,
'ES' => 24,
'SE' => 24,
'CH' => 21,
'TL' => 23,
'TN' => 24,
'TR' => 26,
'UA' => 29,
'AE' => 23,
'GB' => 22,
'VG' => 24,
];
/**
* {@inheritDoc}
*/
public function validate($input): bool
{
if (!is_string($input)) {
return false;
}
$iban = str_replace(' ', '', $input);
if (!preg_match('/[A-Z0-9]{15,34}/', $iban)) {
return false;
}
$countryCode = substr($iban, 0, 2);
if (!$this->hasValidCountryLength($iban, $countryCode)) {
return false;
}
$checkDigits = substr($iban, 2, 2);
$bban = substr($iban, 4);
$rearranged = $bban . $countryCode . $checkDigits;
return bcmod($this->convertToInteger($rearranged), '97') === '1';
}
private function hasValidCountryLength(string $iban, string $countryCode): bool
{
if (!isset(self::COUNTRIES_LENGTHS[$countryCode])) {
return false;
}
return strlen($iban) === self::COUNTRIES_LENGTHS[$countryCode];
}
private function convertToInteger(string $reArrangedIban): string
{
return (string) preg_replace_callback(
'/[A-Z]/',
static function (array $match): int {
return ord($match[0]) - 55;
},
$reArrangedIban
);
}
}