From d6471b33389f716329b1978b41639148f790bf8f Mon Sep 17 00:00:00 2001 From: Michael Hirschler Date: Wed, 12 Aug 2015 15:22:27 +0200 Subject: [PATCH] [Validator] added BIC (SWIFT-BIC) validation constraint --- src/Symfony/Component/Validator/CHANGELOG.md | 5 + .../Component/Validator/Constraints/Bic.php | 32 ++++++ .../Validator/Constraints/BicValidator.php | 68 +++++++++++++ .../Resources/translations/validators.de.xlf | 4 + .../Resources/translations/validators.en.xlf | 4 + .../Tests/Constraints/BicValidatorTest.php | 97 +++++++++++++++++++ 6 files changed, 210 insertions(+) create mode 100644 src/Symfony/Component/Validator/Constraints/Bic.php create mode 100644 src/Symfony/Component/Validator/Constraints/BicValidator.php create mode 100644 src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 4531286fdb..0ff667b770 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +2.8.0 +----- + + * added the BIC (SWIFT-Code) validator + 2.7.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/Bic.php b/src/Symfony/Component/Validator/Constraints/Bic.php new file mode 100644 index 0000000000..0cf32d6227 --- /dev/null +++ b/src/Symfony/Component/Validator/Constraints/Bic.php @@ -0,0 +1,32 @@ + + * + * @api + */ +class Bic extends Constraint +{ + const INVALID_LENGTH_ERROR = '66dad313-af0b-4214-8566-6c799be9789c'; + const INVALID_CHARACTERS_ERROR = 'f424c529-7add-4417-8f2d-4b656e4833e2'; + const INVALID_BANK_CODE_ERROR = '00559357-6170-4f29-aebd-d19330aa19cf'; + const INVALID_COUNTRY_CODE_ERROR = '1ce76f8d-3c1f-451c-9e62-fe9c3ed486ae'; + const INVALID_CASE_ERROR = '11884038-3312-4ae5-9d04-699f782130c7'; + + protected static $errorNames = array( + self::INVALID_LENGTH_ERROR => 'INVALID_LENGTH_ERROR', + self::INVALID_CHARACTERS_ERROR => 'INVALID_CHARACTERS_ERROR', + self::INVALID_BANK_CODE_ERROR => 'INVALID_BANK_CODE_ERROR', + self::INVALID_COUNTRY_CODE_ERROR => 'INVALID_COUNTRY_CODE_ERROR', + self::INVALID_CASE_ERROR => 'INVALID_CASE_ERROR', + ); + + public $message = 'This is not a valid Business Identifier Code (BIC).'; +} diff --git a/src/Symfony/Component/Validator/Constraints/BicValidator.php b/src/Symfony/Component/Validator/Constraints/BicValidator.php new file mode 100644 index 0000000000..63b0996923 --- /dev/null +++ b/src/Symfony/Component/Validator/Constraints/BicValidator.php @@ -0,0 +1,68 @@ + + * + * @link https://en.wikipedia.org/wiki/ISO_9362#Structure + * + * @api + */ +class BicValidator extends ConstraintValidator +{ + /** + * {@inheritdoc} + */ + public function validate($value, Constraint $constraint) + { + if (null === $value || '' === $value) { + return; + } + + $canonicalize = str_replace(' ', '', $value); + + // the bic must be either 8 or 11 characters long + if (!in_array(strlen($canonicalize), array(8, 11))) { + $this->context->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->setCode(Bic::INVALID_LENGTH_ERROR) + ->addViolation(); + } + + // must contain alphanumeric values only + if (!ctype_alnum($canonicalize)) { + $this->context->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->setCode(Bic::INVALID_CHARACTERS_ERROR) + ->addViolation(); + } + + // first 4 letters must be alphabetic (bank code) + if (!ctype_alpha(substr($canonicalize, 0, 4))) { + $this->context->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->setCode(Bic::INVALID_BANK_CODE_ERROR) + ->addViolation(); + } + + // next 2 letters must be alphabetic (country code) + if (!ctype_alpha(substr($canonicalize, 4, 2))) { + $this->context->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->setCode(Bic::INVALID_COUNTRY_CODE_ERROR) + ->addViolation(); + } + + // should contain uppercase characters only + if (strtoupper($canonicalize) !== $canonicalize) { + $this->context->buildViolation($constraint->message) + ->setParameter('{{ value }}', $this->formatValue($value)) + ->setCode(Bic::INVALID_CASE_ERROR) + ->addViolation(); + } + } +} diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf index c79cb94031..6abe8b75ea 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.de.xlf @@ -310,6 +310,10 @@ This value does not match the expected {{ charset }} charset. Dieser Wert entspricht nicht dem erwarteten Zeichensatz {{ charset }}. + + This is not a valid Business Identifier Code (BIC). + Dieser Wert ist kein gültiger BIC. + diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf index e666c793c9..ec072eb716 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.en.xlf @@ -310,6 +310,10 @@ This value does not match the expected {{ charset }} charset. This value does not match the expected {{ charset }} charset. + + This is not a valid Business Identifier Code (BIC). + This is not a valid Business Identifier Code (BIC). + diff --git a/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php new file mode 100644 index 0000000000..07fee88ea1 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php @@ -0,0 +1,97 @@ +validator->validate(null, new Bic()); + + $this->assertNoViolation(); + } + + public function testEmptyStringIsValid() + { + $this->validator->validate('', new Bic()); + + $this->assertNoViolation(); + } + + /** + * @dataProvider getValidBics + */ + public function testValidBics($bic) + { + $this->validator->validate($bic, new Bic()); + + $this->assertNoViolation(); + } + + public function getValidBics() + { + // http://formvalidation.io/validators/bic/ + return array( + array('ASPKAT2LXXX'), + array('ASPKAT2L'), + array('DSBACNBXSHA'), + array('UNCRIT2B912'), + array('DABADKKK'), + array('RZOOAT2L303'), + ); + } + + /** + * @dataProvider getInvalidBics + */ + public function testInvalidBics($bic, $code) + { + $constraint = new Bic(array( + 'message' => 'myMessage', + )); + + $this->validator->validate($bic, $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', '"'.$bic.'"') + ->setCode($code) + ->assertRaised(); + } + + public function getInvalidBics() + { + return array( + array('DEUTD', Bic::INVALID_LENGTH_ERROR), + array('ASPKAT2LXX', Bic::INVALID_LENGTH_ERROR), + array('ASPKAT2LX', Bic::INVALID_LENGTH_ERROR), + array('ASPKAT2LXXX1', Bic::INVALID_LENGTH_ERROR), + array('DABADKK', Bic::INVALID_LENGTH_ERROR), + array('1SBACNBXSHA', Bic::INVALID_BANK_CODE_ERROR), + array('RZ00AT2L303', Bic::INVALID_BANK_CODE_ERROR), + array('D2BACNBXSHA', Bic::INVALID_BANK_CODE_ERROR), + array('DS3ACNBXSHA', Bic::INVALID_BANK_CODE_ERROR), + array('DSB4CNBXSHA', Bic::INVALID_BANK_CODE_ERROR), + array('DEUT12HH', Bic::INVALID_COUNTRY_CODE_ERROR), + array('DSBAC6BXSHA', Bic::INVALID_COUNTRY_CODE_ERROR), + array('DSBA5NBXSHA', Bic::INVALID_COUNTRY_CODE_ERROR), + + // branch code error + array('THISSVAL1D]', Bic::INVALID_CHARACTERS_ERROR), + + // location code error + array('DEUTDEF]', Bic::INVALID_CHARACTERS_ERROR), + + // lower case values are invalid + array('DeutAT2LXXX', Bic::INVALID_CASE_ERROR), + array('DEUTAT2lxxx', Bic::INVALID_CASE_ERROR), + ); + } +}