Skip to content

Commit 0ab2258

Browse files
committed
Better (although ugly) HTML5 detection
1 parent 45228ca commit 0ab2258

4 files changed

Lines changed: 185 additions & 8 deletions

File tree

src/Factory/ConstraintFactory.php

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ class ConstraintFactory
3232
* @throws \InvalidArgumentException
3333
* @throws \RuntimeException
3434
*/
35-
public static function createFromValidationConstraint(Constraint $validationConstraint, FormInterface $form): ConstraintInterface
36-
{
35+
public static function createFromValidationConstraint(
36+
Constraint $validationConstraint,
37+
FormInterface $form
38+
): ConstraintInterface {
3739
if ($validationConstraint instanceof \Symfony\Component\Validator\Constraints\Length) {
3840
if ($validationConstraint->min !== null && $validationConstraint->max !== null) {
3941
// TODO Pick a better message!
@@ -64,7 +66,7 @@ public static function createFromValidationConstraint(Constraint $validationCons
6466

6567
$innerType = $form->getConfig()->getType()->getInnerType();
6668

67-
if (is_string($validationConstraint->value) && !($innerType instanceof DateType || $innerType instanceof BirthdayType || $innerType instanceof DateTimeType)) {
69+
if (is_string($validationConstraint->value) && !static::isFormHtml5DateType($form)) {
6870
throw new \RuntimeException('Date evaluation called on a non-DateType field: '.$form->getName());
6971
}
7072

@@ -94,10 +96,31 @@ public static function createFromValidationConstraint(Constraint $validationCons
9496

9597
}
9698

97-
9899
throw new \RuntimeException('Unsupported Symfony Constraint: '.get_class($validationConstraint));
99100
}
100101

102+
/**
103+
* @param FormInterface $form
104+
* @return bool
105+
*/
106+
private static function isFormHtml5DateType(FormInterface $form): bool
107+
{
108+
$innerType = $form->getConfig()->getType()->getInnerType();
109+
$options = $form->getConfig()->getOptions();
110+
111+
// NOTE: Code below shamelessly lifted from the DateType and DateTimeType view methods as this seems to be
112+
// the only way to tell if a field is going to be rendered as type="date|datetime"
113+
114+
$isHtml5 = false;
115+
if ($innerType instanceof DateType || $innerType instanceof BirthdayType) {
116+
$isHtml5 = $options['html5'] && 'single_text' === $options['widget'] && DateType::HTML5_FORMAT === $options['format'];
117+
} elseif ($innerType instanceof DateTimeType) {
118+
$isHtml5 = $options['html5'] && 'single_text' === $options['widget'] && DateTimeType::HTML5_FORMAT === $options['format'];
119+
}
120+
121+
return $isHtml5;
122+
}
123+
101124
/**
102125
* @param int|float|string $value
103126
* @param bool $isAdjusted

tests/Factory/ConstraintFactoryTest.php

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,16 @@ class ConstraintFactoryTest extends \PHPUnit_Framework_TestCase
3333
public function testCreateFromValidationConstraint(
3434
Constraint $constraint,
3535
FormInterface $form,
36-
?ConstraintInterface $expected
36+
?ConstraintInterface $expected,
37+
string $testName
3738
) {
3839
$return = null;
3940
try {
4041
$return = ConstraintFactory::createFromValidationConstraint($constraint, $form);
4142
} catch (\RuntimeException $exception) {
4243

4344
}
44-
self::assertEquals($expected, $return);
45+
self::assertEquals($expected, $return, $testName);
4546
}
4647

4748
/**
@@ -71,6 +72,7 @@ public function getFactoryTestData()
7172
),
7273
$form->get('id'),
7374
new Pattern('/pattern/', 'This doesn\'t look right'),
75+
'Regex to Pattern',
7476
],
7577
[
7678
new Length(
@@ -82,6 +84,7 @@ public function getFactoryTestData()
8284
),
8385
$form->get('id'),
8486
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Length(1, 20, 'This doesn\'t look right'),
87+
'Length to Length',
8588
],
8689
[
8790
new Length(
@@ -92,6 +95,7 @@ public function getFactoryTestData()
9295
),
9396
$form->get('id'),
9497
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\MinLength(1, 'This doesn\'t look right'),
98+
'Length to MinLength',
9599
],
96100
[
97101
new Length(
@@ -102,6 +106,7 @@ public function getFactoryTestData()
102106
),
103107
$form->get('id'),
104108
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\MaxLength(20, 'This doesn\'t look right'),
109+
'Length to MaxLength',
105110
],
106111
[
107112
new Email(
@@ -111,6 +116,7 @@ public function getFactoryTestData()
111116
),
112117
$form->get('id'),
113118
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Email('This doesn\'t look right'),
119+
'Email to Email',
114120
],
115121

116122
// Max 'n' Min (integer)
@@ -119,21 +125,25 @@ public function getFactoryTestData()
119125
new GreaterThanOrEqual(['value' => 10, 'message' => 'Ouch']),
120126
$form->get('id'),
121127
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Min(10, 'Ouch'),
128+
'GreaterThanOrEqual to Min (integer)',
122129
],
123130
[
124131
new GreaterThan(['value' => 10, 'message' => 'Ouch']),
125132
$form->get('id'),
126133
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Min(11, 'Ouch'),
134+
'GreaterThan to Min (integer)',
127135
],
128136
[
129137
new LessThanOrEqual(['value' => 10, 'message' => 'Ouch']),
130138
$form->get('id'),
131139
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Max(10, 'Ouch'),
140+
'LessThanOrEqual to Max (integer)',
132141
],
133142
[
134143
new LessThan(['value' => 10, 'message' => 'Ouch']),
135144
$form->get('id'),
136145
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Max(9, 'Ouch'),
146+
'LessThan to Max (integer)',
137147
],
138148

139149
// Max 'n' Min (float)
@@ -142,21 +152,25 @@ public function getFactoryTestData()
142152
new GreaterThanOrEqual(['value' => 10.0, 'message' => 'Ouch']),
143153
$form->get('id'),
144154
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Min(10, 'Ouch'),
155+
'GreaterThanOrEqual to Min (float)',
145156
],
146157
[
147158
new GreaterThan(['value' => 10.0, 'message' => 'Ouch']),
148159
$form->get('id'),
149160
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Min(10.0000001, 'Ouch'),
161+
'GreaterThan to Min (float)',
150162
],
151163
[
152164
new LessThanOrEqual(['value' => 10.0, 'message' => 'Ouch']),
153165
$form->get('id'),
154166
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Max(10, 'Ouch'),
167+
'LessThanOrEqual to Max (float)',
155168
],
156169
[
157170
new LessThan(['value' => 10.0, 'message' => 'Ouch']),
158171
$form->get('id'),
159172
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Max(9.9999999, 'Ouch'),
173+
'LessThanOrEqual to Max (float)',
160174
],
161175

162176
// Max 'n' Min (DateTime) (The id field isn't a DateType so we shouldn't get a result back!)
@@ -165,21 +179,25 @@ public function getFactoryTestData()
165179
new GreaterThanOrEqual(['value' => '2018-01-19', 'message' => 'Ouch']),
166180
$form->get('id'),
167181
null,
182+
'GreaterThanOrEqual to Null (date (non-date field))',
168183
],
169184
[
170185
new GreaterThan(['value' => '2018-01-19', 'message' => 'Ouch']),
171186
$form->get('id'),
172187
null,
188+
'GreaterThan to Null (date (non-date field))',
173189
],
174190
[
175191
new LessThanOrEqual(['value' => '2018-01-19', 'message' => 'Ouch']),
176192
$form->get('id'),
177193
null,
194+
'LessThanOrEqual to Null (date (non-date field))',
178195
],
179196
[
180197
new LessThan(['value' => '2018-01-19', 'message' => 'Ouch']),
181198
$form->get('id'),
182199
null,
200+
'LessThan to Null (date (non-date field))',
183201
],
184202

185203
// Max 'n' Min (DateTime) (The date field is a DateType so we should get a result back!)
@@ -188,21 +206,25 @@ public function getFactoryTestData()
188206
new GreaterThanOrEqual(['value' => '2018-01-19', 'message' => 'Ouch']),
189207
$form->get('date'),
190208
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Min('2018-01-19 00:00:00', 'Ouch'),
209+
'GreaterThanOrEqual to Min (date (date field))',
191210
],
192211
[
193212
new GreaterThan(['value' => '2018-01-19', 'message' => 'Ouch']),
194213
$form->get('date'),
195214
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Min('2018-01-19 00:00:01', 'Ouch'),
215+
'GreaterThan to Min (date (date field))',
196216
],
197217
[
198218
new LessThanOrEqual(['value' => '2018-01-19', 'message' => 'Ouch']),
199219
$form->get('date'),
200220
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Max('2018-01-19 00:00:00', 'Ouch'),
221+
'LessThanOrEqual to Max (date (date field))',
201222
],
202223
[
203224
new LessThan(['value' => '2018-01-19', 'message' => 'Ouch']),
204225
$form->get('date'),
205226
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Max('2018-01-18 23:59:59', 'Ouch'),
227+
'LessThan to Max (date (date field))',
206228
],
207229

208230
// Max 'n' Min (DateTime) (The dob field is a BirthdayType so we shoul get a result back!)
@@ -211,21 +233,52 @@ public function getFactoryTestData()
211233
new GreaterThanOrEqual(['value' => '2018-01-19', 'message' => 'Ouch']),
212234
$form->get('dob'),
213235
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Min('2018-01-19 00:00:00', 'Ouch'),
236+
'GreaterThanOrEqual to Min (date (birthday field))',
214237
],
215238
[
216239
new GreaterThan(['value' => '2018-01-19', 'message' => 'Ouch']),
217240
$form->get('dob'),
218241
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Min('2018-01-19 00:00:01', 'Ouch'),
242+
'GreaterThan to Min (date (birthday field))',
219243
],
220244
[
221245
new LessThanOrEqual(['value' => '2018-01-19', 'message' => 'Ouch']),
222246
$form->get('dob'),
223247
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Max('2018-01-19 00:00:00', 'Ouch'),
248+
'LessThanOrEqual to Min (date (birthday field))',
224249
],
225250
[
226251
new LessThan(['value' => '2018-01-19', 'message' => 'Ouch']),
227252
$form->get('dob'),
228253
new \C0ntax\ParsleyBundle\Directive\Field\Constraint\Max('2018-01-18 23:59:59', 'Ouch'),
254+
'LessThan to Min (date (birthday field))',
255+
],
256+
257+
// Max 'n' Min (DateTime) (The dateNotHtml field is a DateType but not HTML5 so we should get null back)
258+
259+
[
260+
new GreaterThanOrEqual(['value' => '2018-01-19', 'message' => 'Ouch']),
261+
$form->get('dateNotHtml5'),
262+
null,
263+
'GreaterThanOrEqual to Null (date (non-html5-date field))',
264+
],
265+
[
266+
new GreaterThan(['value' => '2018-01-19', 'message' => 'Ouch']),
267+
$form->get('dateNotHtml5'),
268+
null,
269+
'GreaterThan to Null (date (non-html5-date field))',
270+
],
271+
[
272+
new LessThanOrEqual(['value' => '2018-01-19', 'message' => 'Ouch']),
273+
$form->get('dateNotHtml5'),
274+
null,
275+
'LessThanOrEqual to Null (date (non-html5-date field))',
276+
],
277+
[
278+
new LessThan(['value' => '2018-01-19', 'message' => 'Ouch']),
279+
$form->get('dateNotHtml5'),
280+
null,
281+
'LessThan to Null (date (non-html5-date field))',
229282
],
230283
];
231284
}

tests/Fixtures/Entity/TestEntity.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,16 @@ class TestEntity
1919
*/
2020
private $email;
2121

22+
/**
23+
* @var int|null
24+
*/
25+
private $int;
26+
27+
/**
28+
* @var float|null
29+
*/
30+
private $float;
31+
2232
/**
2333
* @var string
2434
* @Assert\Length(max=50)
@@ -35,6 +45,11 @@ class TestEntity
3545
*/
3646
private $dob;
3747

48+
/**
49+
* @var \DateTime|null
50+
*/
51+
private $dateNotHtml5;
52+
3853
/**
3954
* @return string
4055
*/
@@ -129,4 +144,61 @@ public function setDob(?\DateTime $dob)
129144

130145
return $this;
131146
}
147+
148+
/**
149+
* @return int|null
150+
*/
151+
public function getInt(): ?int
152+
{
153+
return $this->int;
154+
}
155+
156+
/**
157+
* @param int|null $int
158+
* @return TestEntity
159+
*/
160+
public function setInt(?int $int)
161+
{
162+
$this->int = $int;
163+
164+
return $this;
165+
}
166+
167+
/**
168+
* @return float|null
169+
*/
170+
public function getFloat(): ?float
171+
{
172+
return $this->float;
173+
}
174+
175+
/**
176+
* @param float|null $float
177+
* @return TestEntity
178+
*/
179+
public function setFloat(?float $float)
180+
{
181+
$this->float = $float;
182+
183+
return $this;
184+
}
185+
186+
/**
187+
* @return \DateTime|null
188+
*/
189+
public function getDateNotHtml5(): ?\DateTime
190+
{
191+
return $this->dateNotHtml5;
192+
}
193+
194+
/**
195+
* @param \DateTime|null $dateNotHtml5
196+
* @return TestEntity
197+
*/
198+
public function setDateNotHtml5(?\DateTime $dateNotHtml5)
199+
{
200+
$this->dateNotHtml5 = $dateNotHtml5;
201+
202+
return $this;
203+
}
132204
}

0 commit comments

Comments
 (0)