From a28b5e6a68149a246a5a4073330dc8270735e586 Mon Sep 17 00:00:00 2001 From: Maximilian Beckers Date: Wed, 15 May 2024 09:10:53 +0200 Subject: [PATCH] [Validator] BicValidator add strict mode to validate bics in strict mode --- .../Component/Validator/Constraints/Bic.php | 30 ++++++++++++++++-- .../Validator/Constraints/BicValidator.php | 7 +++-- .../Tests/Constraints/BicValidatorTest.php | 31 +++++++++++++++++++ .../Tests/Constraints/IbanValidatorTest.php | 1 + 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/Bic.php b/src/Symfony/Component/Validator/Constraints/Bic.php index 625fb72132418..22640bedfc795 100644 --- a/src/Symfony/Component/Validator/Constraints/Bic.php +++ b/src/Symfony/Component/Validator/Constraints/Bic.php @@ -15,6 +15,7 @@ use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\LogicException; /** @@ -27,6 +28,14 @@ #[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)] class Bic extends Constraint { + public const VALIDATION_MODE_STRICT = 'strict'; + public const VALIDATION_MODE_CASE_INSENSITIVE = 'case-insensitive'; + + public const VALIDATION_MODES = [ + self::VALIDATION_MODE_STRICT, + self::VALIDATION_MODE_CASE_INSENSITIVE, + ]; + public const INVALID_LENGTH_ERROR = '66dad313-af0b-4214-8566-6c799be9789c'; public const INVALID_CHARACTERS_ERROR = 'f424c529-7add-4417-8f2d-4b656e4833e2'; /** @@ -49,18 +58,34 @@ class Bic extends Constraint public string $ibanMessage = 'This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.'; public ?string $iban = null; public ?string $ibanPropertyPath = null; + public ?string $mode = self::VALIDATION_MODE_STRICT; /** * @param array|null $options * @param string|null $iban An IBAN value to validate that its country code is the same as the BIC's one * @param string|null $ibanPropertyPath Property path to the IBAN value when validating objects * @param string[]|null $groups + * @param string|null $mode The mode used to validate the BIC; pass null to use the default mode (strict) */ - public function __construct(?array $options = null, ?string $message = null, ?string $iban = null, ?string $ibanPropertyPath = null, ?string $ibanMessage = null, ?array $groups = null, mixed $payload = null) - { + public function __construct( + ?array $options = null, + ?string $message = null, + ?string $iban = null, + ?string $ibanPropertyPath = null, + ?string $ibanMessage = null, + ?array $groups = null, + mixed $payload = null, + ?string $mode = null, + ) { if (!class_exists(Countries::class)) { throw new LogicException('The Intl component is required to use the Bic constraint. Try running "composer require symfony/intl".'); } + if (\is_array($options) && \array_key_exists('mode', $options) && !\in_array($options['mode'], self::VALIDATION_MODES, true)) { + throw new InvalidArgumentException('The "mode" parameter value is not valid.'); + } + if (null !== $mode && !\in_array($mode, self::VALIDATION_MODES, true)) { + throw new InvalidArgumentException('The "mode" parameter value is not valid.'); + } parent::__construct($options, $groups, $payload); @@ -68,6 +93,7 @@ public function __construct(?array $options = null, ?string $message = null, ?st $this->ibanMessage = $ibanMessage ?? $this->ibanMessage; $this->iban = $iban ?? $this->iban; $this->ibanPropertyPath = $ibanPropertyPath ?? $this->ibanPropertyPath; + $this->mode = $mode ?? $this->mode; if (null !== $this->iban && null !== $this->ibanPropertyPath) { throw new ConstraintDefinitionException('The "iban" and "ibanPropertyPath" options of the Iban constraint cannot be used at the same time.'); diff --git a/src/Symfony/Component/Validator/Constraints/BicValidator.php b/src/Symfony/Component/Validator/Constraints/BicValidator.php index 19b88b68937aa..d0d1b50841858 100644 --- a/src/Symfony/Component/Validator/Constraints/BicValidator.php +++ b/src/Symfony/Component/Validator/Constraints/BicValidator.php @@ -100,6 +100,9 @@ public function validate(mixed $value, Constraint $constraint): void } $bicCountryCode = substr($canonicalize, 4, 2); + if (Bic::VALIDATION_MODE_CASE_INSENSITIVE === $constraint->mode) { + $bicCountryCode = strtoupper($bicCountryCode); + } if (!isset(self::BIC_COUNTRY_TO_IBAN_COUNTRY_MAP[$bicCountryCode]) && !Countries::exists($bicCountryCode)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) @@ -109,8 +112,8 @@ public function validate(mixed $value, Constraint $constraint): void return; } - // should contain uppercase characters only - if (strtoupper($canonicalize) !== $canonicalize) { + // should contain uppercase characters only in strict mode + if (Bic::VALIDATION_MODE_STRICT === $constraint->mode && strtoupper($canonicalize) !== $canonicalize) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Bic::INVALID_CASE_ERROR) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php index 8b3c815423a48..b71c7dac52726 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php @@ -14,6 +14,7 @@ use Symfony\Component\Validator\Constraints\Bic; use Symfony\Component\Validator\Constraints\BicValidator; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; +use Symfony\Component\Validator\Exception\InvalidArgumentException; use Symfony\Component\Validator\Exception\UnexpectedValueException; use Symfony\Component\Validator\Mapping\ClassMetadata; use Symfony\Component\Validator\Mapping\Loader\AttributeLoader; @@ -301,6 +302,36 @@ public static function getValidBicSpecialCases() yield ['CAIXICBBXXX', 'ES79 2100 0813 6101 2345 6789']; yield ['CAIXEABBXXX', 'ES79 2100 0813 6101 2345 6789']; } + + /** + * @dataProvider getValidBicsWithNormalizerToUpper + */ + public function testValidBicsWithNormalizerToUpper($bic) + { + $this->validator->validate($bic, new Bic(mode: Bic::VALIDATION_MODE_CASE_INSENSITIVE)); + + $this->assertNoViolation(); + } + + public static function getValidBicsWithNormalizerToUpper() + { + return [ + ['ASPKAT2LXXX'], + ['ASPKat2LXXX'], + ['ASPKaT2LXXX'], + ['ASPKAt2LXXX'], + ['aspkat2lxxx'], + ]; + } + + public function testFailOnInvalidMode() + { + $this->expectException(InvalidArgumentException::class); + $this->validator->validate('ASPKAT2LXXX', new Bic(mode: 'invalid')); + + $this->expectException(InvalidArgumentException::class); + $this->validator->validate('ASPKAT2LXXX', new Bic(options: ['mode' => 'invalid'])); + } } class BicComparisonTestClass diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php index 212d5329f44af..390f106df5646 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php @@ -53,6 +53,7 @@ public static function getValidIbans() return [ ['CH9300762011623852957'], // Switzerland without spaces ['CH93 0076 2011 6238 5295 7'], // Switzerland with multiple spaces + ['ch93 0076 2011 6238 5295 7'], // Switzerland lower case // Country list // http://www.rbs.co.uk/corporate/international/g0/guide-to-international-business/regulatory-information/iban/iban-example.ashx pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy