Skip to content

Commit 3c1cfc2

Browse files
committed
New extractor for constraints
1 parent 2960262 commit 3c1cfc2

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
<?php
2+
3+
namespace Translation\Extractor\Visitor\Php\Symfony;
4+
5+
use PhpParser\Node;
6+
use PhpParser\NodeVisitor;
7+
use Translation\Extractor\Visitor\Php\BasePHPVisitor;
8+
9+
final class Constraint extends BasePHPVisitor implements NodeVisitor
10+
{
11+
const CONSTRAINT_CLASS_NAMES = [
12+
'AbstractComparison',
13+
'All',
14+
'Bic',
15+
'Blank',
16+
'Callback',
17+
'CardScheme',
18+
'Choice',
19+
'Collection',
20+
'Composite',
21+
'Count',
22+
'Country',
23+
'Currency',
24+
'Date',
25+
'DateTime',
26+
'DisableAutoMapping',
27+
'DivisibleBy',
28+
'Email',
29+
'EnableAutoMapping',
30+
'EqualTo',
31+
'Existence',
32+
'Expression',
33+
'File',
34+
'GreaterThan',
35+
'GreaterThanOrEqual',
36+
'GroupSequence',
37+
'GroupSequenceProvider',
38+
'Iban',
39+
'IdenticalTo',
40+
'Image',
41+
'Ip',
42+
'Isbn',
43+
'IsFalse',
44+
'IsNull',
45+
'Issn',
46+
'IsTrue',
47+
'Json',
48+
'Language',
49+
'Length',
50+
'LessThan',
51+
'LessThanOrEqual',
52+
'Locale',
53+
'Luhn',
54+
'Negative',
55+
'NegativeOrZero',
56+
'NotBlank',
57+
'NotCompromisedPassword',
58+
'NotEqualTo',
59+
'NotIdenticalTo',
60+
'NotNull',
61+
'NumberConstraintTrait',
62+
'Optional',
63+
'Positive',
64+
'PositiveOrZero',
65+
'Range',
66+
'Regex',
67+
'Required',
68+
'Time',
69+
'Timezone',
70+
'Traverse',
71+
'Type',
72+
'Unique',
73+
'Url',
74+
'Uuid',
75+
'Valid',
76+
];
77+
78+
/**
79+
* {@inheritdoc}
80+
*/
81+
public function beforeTraverse(array $nodes): ?Node
82+
{
83+
return null;
84+
}
85+
86+
/**
87+
* {@inheritdoc}
88+
*/
89+
public function enterNode(Node $node): ?Node
90+
{
91+
if (!$node instanceof Node\Expr\New_) {
92+
return null;
93+
}
94+
95+
$className = $node->class;
96+
if (!$className instanceof Node\Name) {
97+
return null;
98+
}
99+
100+
$parts = $className->parts;
101+
$isConstraintClass = false;
102+
foreach ($parts as $part) {
103+
if (\in_array($part, self::CONSTRAINT_CLASS_NAMES)) {
104+
$isConstraintClass = true;
105+
}
106+
}
107+
108+
if (!$isConstraintClass) {
109+
return null;
110+
}
111+
112+
$args = $node->args;
113+
if (0 === \count($args)) {
114+
return null;
115+
}
116+
117+
$arg = $args[0];
118+
if (!$arg instanceof Node\Arg) {
119+
return null;
120+
}
121+
122+
$options = $arg->value;
123+
if (!$options instanceof Node\Expr\Array_) {
124+
return null;
125+
}
126+
127+
$message = null;
128+
$messageNode = null;
129+
130+
foreach ($options->items as $item) {
131+
if (!$item->key instanceof Node\Scalar\String_) {
132+
continue;
133+
}
134+
135+
if ('message' !== $item->key->value) {
136+
continue;
137+
}
138+
139+
if (!$item->value instanceof Node\Scalar\String_) {
140+
$this->addError($item, 'Constraint message is not a scalar string');
141+
142+
continue;
143+
}
144+
145+
$message = $item->value->value;
146+
$messageNode = $item;
147+
148+
break;
149+
}
150+
151+
if (!empty($message) && null !== $messageNode) {
152+
$this->addLocation($message, $messageNode->getAttribute('startLine'), $messageNode, ['domain' => 'validators']);
153+
}
154+
155+
return null;
156+
}
157+
158+
/**
159+
* {@inheritdoc}
160+
*/
161+
public function leaveNode(Node $node): ?Node
162+
{
163+
return null;
164+
}
165+
166+
/**
167+
* {@inheritdoc}
168+
*/
169+
public function afterTraverse(array $nodes): ?Node
170+
{
171+
return null;
172+
}
173+
}

0 commit comments

Comments
 (0)