Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. IbanValidator.php

function IbanValidator::validate

Overrides ConstraintValidatorInterface::validate

File

vendor/symfony/validator/Constraints/IbanValidator.php, line 170

Class

IbanValidator
@author Manuel Reinhard <manu@sprain.ch> @author Michael Schummel @author Bernhard Schussek <bschussek@gmail.com>

Namespace

Symfony\Component\Validator\Constraints

Code

public function validate(mixed $value, Constraint $constraint) : void {
    if (!$constraint instanceof Iban) {
        throw new UnexpectedTypeException($constraint, Iban::class);
    }
    if (null === $value || '' === $value) {
        return;
    }
    if (!\is_scalar($value) && !$value instanceof \Stringable) {
        throw new UnexpectedValueException($value, 'string');
    }
    $value = (string) $value;
    // Remove spaces (regular, non-breaking, and narrow non-breaking) and convert to uppercase
    $canonicalized = str_replace([
        ' ',
        " ",
        " ",
    ], '', strtoupper($value));
    // The IBAN must contain only digits and characters...
    if (!ctype_alnum($canonicalized)) {
        $this->context
            ->buildViolation($constraint->message)
            ->setParameter('{{ value }}', $this->formatValue($value))
            ->setCode(Iban::INVALID_CHARACTERS_ERROR)
            ->addViolation();
        return;
    }
    // ...start with a two-letter country code
    $countryCode = substr($canonicalized, 0, 2);
    if (!ctype_alpha($countryCode)) {
        $this->context
            ->buildViolation($constraint->message)
            ->setParameter('{{ value }}', $this->formatValue($value))
            ->setCode(Iban::INVALID_COUNTRY_CODE_ERROR)
            ->addViolation();
        return;
    }
    // ...have a format available
    if (!\array_key_exists($countryCode, self::FORMATS)) {
        $this->context
            ->buildViolation($constraint->message)
            ->setParameter('{{ value }}', $this->formatValue($value))
            ->setCode(Iban::NOT_SUPPORTED_COUNTRY_CODE_ERROR)
            ->addViolation();
        return;
    }
    // ...and have a valid format
    if (!preg_match('/^' . self::FORMATS[$countryCode] . '$/', $canonicalized)) {
        $this->context
            ->buildViolation($constraint->message)
            ->setParameter('{{ value }}', $this->formatValue($value))
            ->setCode(Iban::INVALID_FORMAT_ERROR)
            ->addViolation();
        return;
    }
    // Check digits should always between 2 and 98
    // A ECBS document (https://www.ecbs.org/Download/EBS204_V3.PDF) replicates part of the ISO/IEC 7064:2003 standard as a method for generating check digits in the range 02 to 98.
    $checkDigits = (int) substr($canonicalized, 2, 2);
    if ($checkDigits < 2 || $checkDigits > 98) {
        $this->context
            ->buildViolation($constraint->message)
            ->setParameter('{{ value }}', $this->formatValue($value))
            ->setCode(Iban::CHECKSUM_FAILED_ERROR)
            ->addViolation();
        return;
    }
    // Move the first four characters to the end
    // e.g. CH93 0076 2011 6238 5295 7
    //   -> 0076 2011 6238 5295 7 CH93
    $canonicalized = substr($canonicalized, 4) . substr($canonicalized, 0, 4);
    // Convert all remaining letters to their ordinals
    // The result is an integer, which is too large for PHP's int
    // data type, so we store it in a string instead.
    // e.g. 0076 2011 6238 5295 7 CH93
    //   -> 0076 2011 6238 5295 7 121893
    $checkSum = self::toBigInt($canonicalized);
    // Do a modulo-97 operation on the large integer
    // We cannot use PHP's modulo operator, so we calculate the
    // modulo step-wisely instead
    if (1 !== self::bigModulo97($checkSum)) {
        $this->context
            ->buildViolation($constraint->message)
            ->setParameter('{{ value }}', $this->formatValue($value))
            ->setCode(Iban::CHECKSUM_FAILED_ERROR)
            ->addViolation();
    }
}

API Navigation

  • Drupal Core 11.1.x
  • Topics
  • Classes
  • Functions
  • Constants
  • Globals
  • Files
  • Namespaces
  • Deprecated
  • Services
RSS feed
Powered by Drupal