Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcd820ec

Browse files
committed
[Validator] Add CidrValidator to allow validation of CIDR notations
1 parent2d0a08b commitcd820ec

File tree

8 files changed

+565
-0
lines changed

8 files changed

+565
-0
lines changed

‎src/Symfony/Component/Validator/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
5.4
55
---
66

7+
* Add a`Cidr` constraint to validate Cidr notations
78
* Add a`CssColor` constraint to validate CSS colors
89
* Add support for`ConstraintViolationList::createFromMessage()`
910
* Add error's uid to`Count` and`Length` constraints with "exactly" option enabled
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Validator\Constraints;
13+
14+
useSymfony\Component\Validator\Constraint;
15+
useSymfony\Component\Validator\Exception\ConstraintDefinitionException;
16+
17+
/**
18+
* Validates that a value is a valid CIDR notation.
19+
*
20+
* @Annotation
21+
* @Target({"PROPERTY", "METHOD", "ANNOTATION"})
22+
*
23+
* @author Sorin Pop <popsorin15@gmail.com>
24+
* @author Calin Bolea <calin.bolea@gmail.com>
25+
*/
26+
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
27+
class Cidrextends Constraint
28+
{
29+
publicconstINVALID_CIDR_ERROR ='5649e53a-5afb-47c5-a360-ffbab3be8567';
30+
31+
protectedstatic$netmaskMaxes = [
32+
Ip::ALL =>128,
33+
Ip::V4 =>32,
34+
Ip::V6 =>128,
35+
];
36+
37+
public$version = Ip::ALL;
38+
39+
public$message ='This value is not a valid CIDR notation.';
40+
41+
public$netmaskMin =0;
42+
43+
public$netmaskMax;
44+
45+
publicfunction__construct(
46+
array$options =null,
47+
string$version =null,
48+
int$netmaskMin =null,
49+
int$netmaskMax =null,
50+
string$message =null,
51+
array$groups =null,
52+
$payload =null
53+
) {
54+
$this->version =$version ??$options['version'] ??$this->version;
55+
56+
if (!\in_array($this->version,array_keys(self::$netmaskMaxes))) {
57+
thrownewConstraintDefinitionException(sprintf('The option "version" must be one of "%s".',implode('", "',array_keys(self::$netmaskMaxes))));
58+
}
59+
60+
$this->netmaskMin =$netmaskMin ??$options['netmaskMin'] ??$this->netmaskMin;
61+
$this->netmaskMax =$netmaskMax ??$options['netmaskMax'] ??self::$netmaskMaxes[$this->version];
62+
$this->message =$message ??$this->message;
63+
64+
unset($options['netmaskMin'],$options['netmaskMax'],$options['version']);
65+
66+
if ($this->netmaskMin <0 ||$this->netmaskMax >self::$netmaskMaxes[$this->version] ||$this->netmaskMin >$this->netmaskMax) {
67+
thrownewConstraintDefinitionException(sprintf('The netmask range must be between 0 and %d.',self::$netmaskMaxes[$this->version]));
68+
}
69+
70+
parent::__construct($options,$groups,$payload);
71+
}
72+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Validator\Constraints;
13+
14+
useSymfony\Component\Validator\Constraint;
15+
useSymfony\Component\Validator\ConstraintValidator;
16+
useSymfony\Component\Validator\Exception\UnexpectedTypeException;
17+
useSymfony\Component\Validator\Exception\UnexpectedValueException;
18+
19+
class CidrValidatorextends ConstraintValidator
20+
{
21+
publicfunctionvalidate($value,Constraint$constraint):void
22+
{
23+
if (!$constraintinstanceof Cidr) {
24+
thrownewUnexpectedTypeException($constraint, Cidr::class);
25+
}
26+
27+
if (null ===$value ||'' ===$value) {
28+
return;
29+
}
30+
31+
if (!\is_string($value)) {
32+
thrownewUnexpectedValueException($value,'string');
33+
}
34+
35+
$cidrParts =explode('/',$value,2);
36+
37+
if (!isset($cidrParts[1]) || !ctype_digit($cidrParts[1])) {
38+
$this->context
39+
->buildViolation($constraint->message)
40+
->setCode(Cidr::INVALID_CIDR_ERROR)
41+
->addViolation();
42+
43+
return;
44+
}
45+
46+
if ('' ===$cidrParts[0]) {
47+
$this->context
48+
->buildViolation($constraint->message)
49+
->setCode(Cidr::INVALID_CIDR_ERROR)
50+
->addViolation();
51+
52+
return;
53+
}
54+
55+
$ipAddress =$cidrParts[0];
56+
$netmask = (int)$cidrParts[1];
57+
58+
if (Ip::V6 !==$constraint->version
59+
&&filter_var($ipAddress, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV4)
60+
&&$netmask <=32
61+
&&$netmask >=$constraint->netmaskMin
62+
&&$netmask <=$constraint->netmaskMax) {
63+
return;
64+
}
65+
66+
if (Ip::V4 !==$constraint->version
67+
&&filter_var($ipAddress, \FILTER_VALIDATE_IP, \FILTER_FLAG_IPV6)
68+
&&$netmask >=$constraint->netmaskMin
69+
&&$netmask <=$constraint->netmaskMax) {
70+
return;
71+
}
72+
73+
$this->context
74+
->buildViolation($constraint->message)
75+
->setCode(Cidr::INVALID_CIDR_ERROR)
76+
->addViolation();
77+
}
78+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@
394394
<source>This value is not a valid CSS color.</source>
395395
<target>This value is not a valid CSS color.</target>
396396
</trans-unit>
397+
<trans-unitid="102">
398+
<source>This value is not a valid CIDR notation.</source>
399+
<target>This value is not a valid CIDR notation.</target>
400+
</trans-unit>
397401
</body>
398402
</file>
399403
</xliff>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,10 @@
394394
<source>This value is not a valid CSS color.</source>
395395
<target>Cette valeur n'est pas une couleur CSS valide.</target>
396396
</trans-unit>
397+
<trans-unitid="102">
398+
<source>This value is not a valid CIDR notation.</source>
399+
<target>Cette valeur n'est pas une notation CIDR valide.</target>
400+
</trans-unit>
397401
</body>
398402
</file>
399403
</xliff>

‎src/Symfony/Component/Validator/Resources/translations/validators.ro.xlf‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,14 @@
390390
<source>This value should be a valid expression.</source>
391391
<target>Această valoare ar trebui să fie o expresie validă.</target>
392392
</trans-unit>
393+
<trans-unitid="101">
394+
<source>This value is not a valid CSS color.</source>
395+
<target>Această valoare nu este o culoare CSS validă.</target>
396+
</trans-unit>
397+
<trans-unitid="102">
398+
<source>This value is not a valid CIDR notation.</source>
399+
<target>Această valoare nu este o notație CIDR validă.</target>
400+
</trans-unit>
393401
</body>
394402
</file>
395403
</xliff>
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
<?php
2+
3+
namespaceSymfony\Component\Validator\Tests\Constraints;
4+
5+
usePHPUnit\Framework\TestCase;
6+
useSymfony\Component\Validator\Constraints\Cidr;
7+
useSymfony\Component\Validator\Constraints\Ip;
8+
useSymfony\Component\Validator\Exception\ConstraintDefinitionException;
9+
useSymfony\Component\Validator\Mapping\ClassMetadata;
10+
useSymfony\Component\Validator\Mapping\Loader\AnnotationLoader;
11+
12+
class CidrTestextends TestCase
13+
{
14+
publicfunctiontestForAll()
15+
{
16+
$cidrConstraint =newCidr();
17+
18+
self::assertEquals(Ip::ALL,$cidrConstraint->version);
19+
self::assertEquals(0,$cidrConstraint->netmaskMin);
20+
self::assertEquals(128,$cidrConstraint->netmaskMax);
21+
}
22+
23+
publicfunctiontestForV4()
24+
{
25+
$cidrConstraint =newCidr(['version' => Ip::V4]);
26+
27+
self::assertEquals(Ip::V4,$cidrConstraint->version);
28+
self::assertEquals(0,$cidrConstraint->netmaskMin);
29+
self::assertEquals(32,$cidrConstraint->netmaskMax);
30+
}
31+
32+
publicfunctiontestForV6()
33+
{
34+
$cidrConstraint =newCidr(['version' => Ip::V6]);
35+
36+
self::assertEquals(Ip::V6,$cidrConstraint->version);
37+
self::assertEquals(0,$cidrConstraint->netmaskMin);
38+
self::assertEquals(128,$cidrConstraint->netmaskMax);
39+
}
40+
41+
publicfunctiontestWithInvalidVersion()
42+
{
43+
$availableVersions = [Ip::ALL, Ip::V4, Ip::V6];
44+
45+
self::expectException(ConstraintDefinitionException::class);
46+
self::expectExceptionMessage(sprintf('The option "version" must be one of "%s".',implode('", "',$availableVersions)));
47+
48+
newCidr(['version' =>'8']);
49+
}
50+
51+
/**
52+
* @dataProvider getValidMinMaxValues
53+
*/
54+
publicfunctiontestWithValidMinMaxValues(string$ipVersion,int$netmaskMin,int$netmaskMax)
55+
{
56+
$cidrConstraint =newCidr([
57+
'version' =>$ipVersion,
58+
'netmaskMin' =>$netmaskMin,
59+
'netmaskMax' =>$netmaskMax,
60+
]);
61+
62+
self::assertEquals($ipVersion,$cidrConstraint->version);
63+
self::assertEquals($netmaskMin,$cidrConstraint->netmaskMin);
64+
self::assertEquals($netmaskMax,$cidrConstraint->netmaskMax);
65+
}
66+
67+
/**
68+
* @dataProvider getInvalidMinMaxValues
69+
*/
70+
publicfunctiontestWithInvalidMinMaxValues(string$ipVersion,int$netmaskMin,int$netmaskMax)
71+
{
72+
$expectedMax = Ip::V4 ==$ipVersion ?32 :128;
73+
74+
self::expectException(ConstraintDefinitionException::class);
75+
self::expectExceptionMessage(sprintf('The netmask range must be between 0 and %d.',$expectedMax));
76+
77+
newCidr([
78+
'version' =>$ipVersion,
79+
'netmaskMin' =>$netmaskMin,
80+
'netmaskMax' =>$netmaskMax,
81+
]);
82+
}
83+
84+
publicfunctiongetInvalidMinMaxValues():array
85+
{
86+
return [
87+
[Ip::ALL, -1,23],
88+
[Ip::ALL,23,130],
89+
[Ip::ALL,2, -4],
90+
[Ip::ALL, -12, -40],
91+
[Ip::V4,0,33],
92+
[Ip::V4,2, -10],
93+
[Ip::V4, -4,128],
94+
[Ip::V4, -5, -1],
95+
[Ip::V6,5,200],
96+
[Ip::V6, -1,120],
97+
[Ip::V6,0, -10],
98+
[Ip::V6, -15, -20],
99+
];
100+
}
101+
102+
publicfunctiongetValidMinMaxValues():array
103+
{
104+
return [
105+
[Ip::ALL,0,23],
106+
[Ip::ALL,23,120],
107+
[Ip::V4,0,5],
108+
[Ip::V4,2,10],
109+
[Ip::V6,0,43],
110+
[Ip::V6,33,100],
111+
];
112+
}
113+
114+
/**
115+
* @requires PHP 8
116+
*/
117+
publicfunctiontestAttributes()
118+
{
119+
$metadata =newClassMetadata(CidrDummy::class);
120+
$loader =newAnnotationLoader();
121+
self::assertTrue($loader->loadClassMetadata($metadata));
122+
123+
[$aConstraint] =$metadata->properties['a']->getConstraints();
124+
self::assertSame(Ip::ALL,$aConstraint->version);
125+
self::assertSame(0,$aConstraint->netmaskMin);
126+
self::assertSame(128,$aConstraint->netmaskMax);
127+
128+
[$bConstraint] =$metadata->properties['b']->getConstraints();
129+
self::assertSame(Ip::V6,$bConstraint->version);
130+
self::assertSame('myMessage',$bConstraint->message);
131+
self::assertSame(10,$bConstraint->netmaskMin);
132+
self::assertSame(126,$bConstraint->netmaskMax);
133+
self::assertSame(['Default','CidrDummy'],$bConstraint->groups);
134+
135+
[$cConstraint] =$metadata->properties['c']->getConstraints();
136+
self::assertSame(['my_group'],$cConstraint->groups);
137+
self::assertSame('some attached data',$cConstraint->payload);
138+
}
139+
}
140+
141+
class CidrDummy
142+
{
143+
#[Cidr]
144+
private$a;
145+
146+
#[Cidr(version: Ip::V6, message:'myMessage', netmaskMin:10, netmaskMax:126)]
147+
private$b;
148+
149+
#[Cidr(groups: ['my_group'], payload:'some attached data')]
150+
private$c;
151+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp