Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 435489b

Browse files
committed
[Validator] Checking a BIC along with an IBAN
Fix #28166
1 parent 4bc1cc7 commit 435489b

File tree

6 files changed

+197
-1
lines changed

6 files changed

+197
-1
lines changed

src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ CHANGELOG
1515
* deprecated using the `Bic`, `Country`, `Currency`, `Language` and `Locale` constraints without `symfony/intl`
1616
* deprecated using the `Email` constraint without `egulias/email-validator`
1717
* deprecated using the `Expression` constraint without `symfony/expression-language`
18+
* added options `iban` and `ibanPropertyPath` to Bic constraint
1819

1920
4.1.0
2021
-----

src/Symfony/Component/Validator/Constraints/Bic.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
namespace Symfony\Component\Validator\Constraints;
1313

1414
use Symfony\Component\Intl\Intl;
15+
use Symfony\Component\PropertyAccess\PropertyAccess;
1516
use Symfony\Component\Validator\Constraint;
17+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
1618
use Symfony\Component\Validator\Exception\LogicException;
1719

1820
/**
@@ -28,6 +30,7 @@ class Bic extends Constraint
2830
const INVALID_BANK_CODE_ERROR = '00559357-6170-4f29-aebd-d19330aa19cf';
2931
const INVALID_COUNTRY_CODE_ERROR = '1ce76f8d-3c1f-451c-9e62-fe9c3ed486ae';
3032
const INVALID_CASE_ERROR = '11884038-3312-4ae5-9d04-699f782130c7';
33+
const INVALID_IBAN_COUNTRY_CODE_ERROR = '29a2c3bb-587b-4996-b6f5-53081364cea5';
3134

3235
protected static $errorNames = array(
3336
self::INVALID_LENGTH_ERROR => 'INVALID_LENGTH_ERROR',
@@ -38,14 +41,25 @@ class Bic extends Constraint
3841
);
3942

4043
public $message = 'This is not a valid Business Identifier Code (BIC).';
44+
public $ibanMessage = 'This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.';
45+
public $iban;
46+
public $ibanPropertyPath;
4147

42-
public function __construct($options = null)
48+
public function __construct(array $options = null)
4349
{
4450
if (!class_exists(Intl::class)) {
4551
// throw new LogicException(sprintf('The "symfony/intl" component is required to use the "%s" constraint.', __CLASS__));
4652
@trigger_error(sprintf('Using the "%s" constraint without the "symfony/intl" component installed is deprecated since Symfony 4.2.', __CLASS__), E_USER_DEPRECATED);
4753
}
4854

55+
if (isset($options['iban']) && isset($options['ibanPropertyPath'])) {
56+
throw new ConstraintDefinitionException(sprintf('The "iban" and "ibanPropertyPath" options of the Iban constraint cannot be used at the same time.', \get_class($this)));
57+
}
58+
59+
if (isset($options['ibanPropertyPath']) && !class_exists(PropertyAccess::class)) {
60+
throw new LogicException(sprintf('The "symfony/property-access" component is required to use the "%s" constraint with the "ibanPropertyPath" option.', \get_class($this)));
61+
}
62+
4963
parent::__construct($options);
5064
}
5165
}

src/Symfony/Component/Validator/Constraints/BicValidator.php

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
namespace Symfony\Component\Validator\Constraints;
1313

1414
use Symfony\Component\Intl\Intl;
15+
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
16+
use Symfony\Component\PropertyAccess\PropertyAccess;
17+
use Symfony\Component\PropertyAccess\PropertyAccessor;
1518
use Symfony\Component\Validator\Constraint;
1619
use Symfony\Component\Validator\ConstraintValidator;
20+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
1721
use Symfony\Component\Validator\Exception\LogicException;
1822
use Symfony\Component\Validator\Exception\UnexpectedValueException;
1923

@@ -24,6 +28,13 @@
2428
*/
2529
class BicValidator extends ConstraintValidator
2630
{
31+
private $propertyAccessor;
32+
33+
public function __construct(PropertyAccessor $propertyAccessor = null)
34+
{
35+
$this->propertyAccessor = $propertyAccessor;
36+
}
37+
2738
/**
2839
* {@inheritdoc}
2940
*/
@@ -95,5 +106,39 @@ public function validate($value, Constraint $constraint)
95106

96107
return;
97108
}
109+
110+
// check against an IBAN
111+
$iban = $constraint->iban;
112+
$path = $constraint->ibanPropertyPath;
113+
if ($path && null !== $object = $this->context->getObject()) {
114+
try {
115+
$iban = $this->getPropertyAccessor()->getValue($object, $path);
116+
} catch (NoSuchPropertyException $e) {
117+
throw new ConstraintDefinitionException(sprintf('Invalid property path "%s" provided to "%s" constraint: %s', $path, \get_class($constraint), $e->getMessage()), 0, $e);
118+
}
119+
}
120+
if (!$iban) {
121+
return;
122+
}
123+
$ibanCountryCode = substr($iban, 0, 2);
124+
if (ctype_alpha($ibanCountryCode) && substr($canonicalize, 4, 2) !== $ibanCountryCode) {
125+
$this->context->buildViolation($constraint->ibanMessage)
126+
->setParameter('{{ value }}', $this->formatValue($value))
127+
->setParameter('{{ iban }}', $iban)
128+
->setCode(Bic::INVALID_IBAN_COUNTRY_CODE_ERROR)
129+
->addViolation();
130+
}
131+
}
132+
133+
private function getPropertyAccessor(): PropertyAccessor
134+
{
135+
if (null === $this->propertyAccessor) {
136+
if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) {
137+
throw new LogicException('Unable to use property path as the Symfony PropertyAccess component is not installed.');
138+
}
139+
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
140+
}
141+
142+
return $this->propertyAccessor;
98143
}
99144
}

src/Symfony/Component/Validator/Resources/translations/validators.en.xlf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,10 @@
326326
<source>This value should be a multiple of {{ compared_value }}.</source>
327327
<target>This value should be a multiple of {{ compared_value }}.</target>
328328
</trans-unit>
329+
<trans-unit id="85">
330+
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
331+
<target>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</target>
332+
</trans-unit>
329333
</body>
330334
</file>
331335
</xliff>

src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,10 @@
326326
<source>This value should be a multiple of {{ compared_value }}.</source>
327327
<target>Cette valeur doit être un multiple de {{ compared_value }}.</target>
328328
</trans-unit>
329+
<trans-unit id="85">
330+
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
331+
<target>Ce BIC n'est pas associé à l'IBAN {{ iban }}.</target>
332+
</trans-unit>
329333
</body>
330334
</file>
331335
</xliff>

src/Symfony/Component/Validator/Tests/Constraints/BicValidatorTest.php

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Validator\Constraints\Bic;
1515
use Symfony\Component\Validator\Constraints\BicValidator;
16+
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
1617
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
1718

1819
class BicValidatorTest extends ConstraintValidatorTestCase
@@ -36,6 +37,113 @@ public function testEmptyStringIsValid()
3637
$this->assertNoViolation();
3738
}
3839

40+
public function testValidComparisonToPropertyPath()
41+
{
42+
$constraint = new Bic(array('ibanPropertyPath' => 'value'));
43+
44+
$object = new BicComparisonTestClass('FR14 2004 1010 0505 0001 3M02 606');
45+
46+
$this->setObject($object);
47+
48+
$this->validator->validate('SOGEFRPP', $constraint);
49+
50+
$this->assertNoViolation();
51+
}
52+
53+
public function testValidComparisonToPropertyPathOnArray()
54+
{
55+
$constraint = new Bic(array('ibanPropertyPath' => '[root][value]'));
56+
57+
$this->setObject(array('root' => array('value' => 'FR14 2004 1010 0505 0001 3M02 606')));
58+
59+
$this->validator->validate('SOGEFRPP', $constraint);
60+
61+
$this->assertNoViolation();
62+
}
63+
64+
public function testInvalidComparisonToPropertyPath()
65+
{
66+
$constraint = new Bic(array('ibanPropertyPath' => 'value'));
67+
$constraint->ibanMessage = 'Constraint Message';
68+
69+
$object = new BicComparisonTestClass('FR14 2004 1010 0505 0001 3M02 606');
70+
71+
$this->setObject($object);
72+
73+
$this->validator->validate('UNCRIT2B912', $constraint);
74+
75+
$this->buildViolation('Constraint Message')
76+
->setParameter('{{ value }}', '"UNCRIT2B912"')
77+
->setParameter('{{ iban }}', 'FR14 2004 1010 0505 0001 3M02 606')
78+
->setCode(Bic::INVALID_IBAN_COUNTRY_CODE_ERROR)
79+
->assertRaised();
80+
}
81+
82+
public function testValidComparisonToValue()
83+
{
84+
$constraint = new Bic(array('iban' => 'FR14 2004 1010 0505 0001 3M02 606'));
85+
$constraint->ibanMessage = 'Constraint Message';
86+
87+
$this->validator->validate('SOGEFRPP', $constraint);
88+
89+
$this->assertNoViolation();
90+
}
91+
92+
public function testInvalidComparisonToValue()
93+
{
94+
$constraint = new Bic(array('iban' => 'FR14 2004 1010 0505 0001 3M02 606'));
95+
$constraint->ibanMessage = 'Constraint Message';
96+
97+
$this->validator->validate('UNCRIT2B912', $constraint);
98+
99+
$this->buildViolation('Constraint Message')
100+
->setParameter('{{ value }}', '"UNCRIT2B912"')
101+
->setParameter('{{ iban }}', 'FR14 2004 1010 0505 0001 3M02 606')
102+
->setCode(Bic::INVALID_IBAN_COUNTRY_CODE_ERROR)
103+
->assertRaised();
104+
}
105+
106+
public function testNoViolationOnNullObjectWithPropertyPath()
107+
{
108+
$constraint = new Bic(array('ibanPropertyPath' => 'propertyPath'));
109+
110+
$this->setObject(null);
111+
112+
$this->validator->validate('UNCRIT2B912', $constraint);
113+
114+
$this->assertNoViolation();
115+
}
116+
117+
/**
118+
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
119+
* @expectedExceptionMessage The "iban" and "ibanPropertyPath" options of the Iban constraint cannot be used at the same time
120+
*/
121+
public function testThrowsConstraintExceptionIfBothValueAndPropertyPath()
122+
{
123+
new Bic(array(
124+
'iban' => 'value',
125+
'ibanPropertyPath' => 'propertyPath',
126+
));
127+
}
128+
129+
public function testInvalidValuePath()
130+
{
131+
$constraint = new Bic(array('ibanPropertyPath' => 'foo'));
132+
133+
if (method_exists($this, 'expectException')) {
134+
$this->expectException(ConstraintDefinitionException::class);
135+
$this->expectExceptionMessage(sprintf('Invalid property path "foo" provided to "%s" constraint', \get_class($constraint)));
136+
} else {
137+
$this->setExpectedException(ConstraintDefinitionException::class, sprintf('Invalid property path "foo" provided to "%s" constraint', \get_class($constraint)));
138+
}
139+
140+
$object = new BicComparisonTestClass(5);
141+
142+
$this->setObject($object);
143+
144+
$this->validator->validate('UNCRIT2B912', $constraint);
145+
}
146+
39147
/**
40148
* @expectedException \Symfony\Component\Validator\Exception\UnexpectedValueException
41149
*/
@@ -114,3 +222,23 @@ public function getInvalidBics()
114222
);
115223
}
116224
}
225+
226+
class BicComparisonTestClass
227+
{
228+
protected $value;
229+
230+
public function __construct($value)
231+
{
232+
$this->value = $value;
233+
}
234+
235+
public function __toString()
236+
{
237+
return (string) $this->value;
238+
}
239+
240+
public function getValue()
241+
{
242+
return $this->value;
243+
}
244+
}

0 commit comments

Comments
 (0)