Skip to content
This repository was archived by the owner on Jan 30, 2020. It is now read-only.

Commit 95beb4d

Browse files
committed
Merge branch 'hotfix/159'
Close #159 Fixes #158
2 parents ff96c89 + 4cc04fa commit 95beb4d

File tree

12 files changed

+227
-17
lines changed

12 files changed

+227
-17
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ All notable changes to this project will be documented in this file, in reverse
2828
and thus seeding it with configured form/form element services. This means
2929
that the `form_elements` configuration will now be honored in non-zend-mvc
3030
contexts.
31+
- [#159](https://github.com/zendframework/zend-form/pull/159) fixes the behavior
32+
of the `min` and `max` attributes of the various `DateTime` elements, ensuring
33+
that the elements raise an exception during instantiation if the values
34+
provided are in a format that `DateTime` does not recognize for the element
35+
type in question.
3136

3237
## 2.10.1 - 2017-04-26
3338

src/Element/Date.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717
class Date extends DateTimeElement
1818
{
19+
20+
const DATETIME_FORMAT = 'Y-m-d';
21+
1922
/**
2023
* Seed attributes
2124
*

src/Element/DateTime.php

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
use DateInterval;
1313
use DateTime as PhpDateTime;
14+
use DateTimeInterface;
1415
use Zend\Form\Element;
16+
use Zend\Form\Exception\InvalidArgumentException;
1517
use Zend\InputFilter\InputProviderInterface;
1618
use Zend\Validator\Date as DateValidator;
1719
use Zend\Validator\DateStep as DateStepValidator;
@@ -120,17 +122,40 @@ protected function getValidators()
120122
$validators = [];
121123
$validators[] = $this->getDateValidator();
122124

123-
if (isset($this->attributes['min'])) {
125+
if (isset($this->attributes['min'])
126+
&& $this->valueIsValidDateTimeFormat($this->attributes['min'])
127+
) {
124128
$validators[] = new GreaterThanValidator([
125-
'min' => $this->attributes['min'],
129+
'min' => $this->attributes['min'],
126130
'inclusive' => true,
127131
]);
132+
} elseif (isset($this->attributes['min'])
133+
&& ! $this->valueIsValidDateTimeFormat($this->attributes['min'])
134+
) {
135+
throw new InvalidArgumentException(sprintf(
136+
'%1$s expects "min" to conform to %2$s; received "%3$s"',
137+
__METHOD__,
138+
static::DATETIME_FORMAT,
139+
$this->attributes['min']
140+
));
128141
}
129-
if (isset($this->attributes['max'])) {
142+
143+
if (isset($this->attributes['max'])
144+
&& $this->valueIsValidDateTimeFormat($this->attributes['max'])
145+
) {
130146
$validators[] = new LessThanValidator([
131-
'max' => $this->attributes['max'],
147+
'max' => $this->attributes['max'],
132148
'inclusive' => true,
133149
]);
150+
} elseif (isset($this->attributes['max'])
151+
&& ! $this->valueIsValidDateTimeFormat($this->attributes['max'])
152+
) {
153+
throw new InvalidArgumentException(sprintf(
154+
'%1$s expects "max" to conform to %2$s; received "%3$s"',
155+
__METHOD__,
156+
static::DATETIME_FORMAT,
157+
$this->attributes['max']
158+
));
134159
}
135160
if (! isset($this->attributes['step'])
136161
|| 'any' !== $this->attributes['step']
@@ -145,7 +170,7 @@ protected function getValidators()
145170
/**
146171
* Retrieves a Date Validator configured for a DateTime Input type
147172
*
148-
* @return DateTime
173+
* @return DateValidator
149174
*/
150175
protected function getDateValidator()
151176
{
@@ -155,7 +180,7 @@ protected function getDateValidator()
155180
/**
156181
* Retrieves a DateStep Validator configured for a DateTime Input type
157182
*
158-
* @return DateTime
183+
* @return DateStepValidator
159184
*/
160185
protected function getStepValidator()
161186
{
@@ -191,4 +216,18 @@ public function getInputSpecification()
191216
'validators' => $this->getValidators(),
192217
];
193218
}
219+
220+
/**
221+
* Indicate whether or not a value represents a valid DateTime format.
222+
*
223+
* @param string $value
224+
* @return bool
225+
*/
226+
private function valueIsValidDateTimeFormat($value)
227+
{
228+
return PhpDateTime::createFromFormat(
229+
static::DATETIME_FORMAT,
230+
$value
231+
) instanceof DateTimeInterface;
232+
}
194233
}

src/Element/DateTimeLocal.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@
1313

1414
class DateTimeLocal extends DateTime
1515
{
16+
1617
const DATETIME_LOCAL_FORMAT = 'Y-m-d\TH:i';
1718

19+
const DATETIME_FORMAT = self::DATETIME_LOCAL_FORMAT;
20+
1821
/**
1922
* Seed attributes
2023
*

src/Element/Month.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515

1616
class Month extends DateTime
1717
{
18+
19+
const DATETIME_FORMAT = 'Y-m';
20+
1821
/**
1922
* Seed attributes
2023
*

src/Element/Time.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
class Time extends DateTime
1616
{
17+
18+
const DATETIME_FORMAT = 'H:i:s';
19+
1720
/**
1821
* Seed attributes
1922
*

src/Element/Week.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
use Zend\Validator\DateStep as DateStepValidator;
1313
use Zend\Validator\Regex as RegexValidator;
14+
use Zend\Validator\GreaterThan as GreaterThanValidator;
15+
use Zend\Validator\LessThan as LessThanValidator;
1416

1517
class Week extends DateTime
1618
{
@@ -52,4 +54,36 @@ protected function getStepValidator()
5254
'step' => new \DateInterval("P{$stepValue}W"),
5355
]);
5456
}
57+
58+
/**
59+
* @see https://bugs.php.net/bug.php?id=74511
60+
* @return array
61+
*/
62+
protected function getValidators()
63+
{
64+
if ($this->validators) {
65+
return $this->validators;
66+
}
67+
$validators = [];
68+
$validators[] = $this->getDateValidator();
69+
if (isset($this->attributes['min'])) {
70+
$validators[] = new GreaterThanValidator([
71+
'min' => $this->attributes['min'],
72+
'inclusive' => true,
73+
]);
74+
}
75+
if (isset($this->attributes['max'])) {
76+
$validators[] = new LessThanValidator([
77+
'max' => $this->attributes['max'],
78+
'inclusive' => true,
79+
]);
80+
}
81+
if (! isset($this->attributes['step'])
82+
|| 'any' !== $this->attributes['step']
83+
) {
84+
$validators[] = $this->getStepValidator();
85+
}
86+
$this->validators = $validators;
87+
return $this->validators;
88+
}
5589
}

test/Element/DateTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use DateTime;
1313
use PHPUnit\Framework\TestCase;
1414
use Zend\Form\Element\Date as DateElement;
15+
use Zend\Form\Exception\InvalidArgumentException;
1516

1617
/**
1718
* @covers \Zend\Form\Element\Date
@@ -158,4 +159,33 @@ public function testStepValidatorIgnoresDaylightSavings()
158159
}
159160
}
160161
}
162+
163+
public function testFailsWithInvalidMinSpecification()
164+
{
165+
$element = new DateElement('foo');
166+
$element->setAttributes(
167+
[
168+
'inclusive' => true,
169+
'min' => '2000-01-01T00',
170+
'step' => '1',
171+
]
172+
);
173+
174+
$this->expectException(InvalidArgumentException::class);
175+
$element->getInputSpecification();
176+
}
177+
178+
public function testFailsWithInvalidMaxSpecification()
179+
{
180+
$element = new DateElement('foo');
181+
$element->setAttributes(
182+
[
183+
'inclusive' => true,
184+
'max' => '2001-01-01T00',
185+
'step' => '1',
186+
]
187+
);
188+
$this->expectException(InvalidArgumentException::class);
189+
$element->getInputSpecification();
190+
}
161191
}

test/Element/DateTimeLocalTest.php

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use PHPUnit\Framework\TestCase;
1313
use Zend\Form\Element\DateTimeLocal as DateTimeLocalElement;
14+
use Zend\Form\Exception\InvalidArgumentException;
1415

1516
class DateTimeLocalTest extends TestCase
1617
{
@@ -19,8 +20,8 @@ public function testProvidesInputSpecificationThatIncludesValidatorsBasedOnAttri
1920
$element = new DateTimeLocalElement('foo');
2021
$element->setAttributes([
2122
'inclusive' => true,
22-
'min' => '2000-01-01T00:00Z',
23-
'max' => '2001-01-01T00:00Z',
23+
'min' => '2000-01-01T00:00',
24+
'max' => '2001-01-01T00:00',
2425
'step' => '1',
2526
]);
2627

@@ -40,11 +41,11 @@ public function testProvidesInputSpecificationThatIncludesValidatorsBasedOnAttri
4041
switch ($class) {
4142
case 'Zend\Validator\GreaterThan':
4243
$this->assertTrue($validator->getInclusive());
43-
$this->assertEquals('2000-01-01T00:00Z', $validator->getMin());
44+
$this->assertEquals('2000-01-01T00:00', $validator->getMin());
4445
break;
4546
case 'Zend\Validator\LessThan':
4647
$this->assertTrue($validator->getInclusive());
47-
$this->assertEquals('2001-01-01T00:00Z', $validator->getMax());
48+
$this->assertEquals('2001-01-01T00:00', $validator->getMax());
4849
break;
4950
case 'Zend\Validator\DateStep':
5051
$dateInterval = new \DateInterval('PT1M');
@@ -55,4 +56,33 @@ public function testProvidesInputSpecificationThatIncludesValidatorsBasedOnAttri
5556
}
5657
}
5758
}
59+
60+
public function testFailsWithInvalidMinSpecification()
61+
{
62+
$element = new DateTimeLocalElement('foo');
63+
$element->setAttributes(
64+
[
65+
'inclusive' => true,
66+
'min' => '2001-01-01T00:00Z',
67+
'step' => '1',
68+
]
69+
);
70+
71+
$this->expectException(InvalidArgumentException::class);
72+
$element->getInputSpecification();
73+
}
74+
75+
public function testFailsWithInvalidMaxSpecification()
76+
{
77+
$element = new DateTimeLocalElement('foo');
78+
$element->setAttributes(
79+
[
80+
'inclusive' => true,
81+
'max' => '2001-01-01T00:00Z',
82+
'step' => '1',
83+
]
84+
);
85+
$this->expectException(InvalidArgumentException::class);
86+
$element->getInputSpecification();
87+
}
5888
}

test/Element/DateTimeTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use DateTime;
1313
use PHPUnit\Framework\TestCase;
1414
use Zend\Form\Element\DateTime as DateTimeElement;
15+
use Zend\Form\Exception\InvalidArgumentException;
1516

1617
class DateTimeTest extends TestCase
1718
{
@@ -119,4 +120,33 @@ public function testSetFormatWithOptions()
119120

120121
$this->assertSame($format, $element->getFormat());
121122
}
123+
124+
public function testFailsWithInvalidMinSpecification()
125+
{
126+
$element = new DateTimeElement('foo');
127+
$element->setAttributes(
128+
[
129+
'inclusive' => true,
130+
'min' => '2000-01-01T00',
131+
'step' => '1',
132+
]
133+
);
134+
135+
$this->expectException(InvalidArgumentException::class);
136+
$element->getInputSpecification();
137+
}
138+
139+
public function testFailsWithInvalidMaxSpecification()
140+
{
141+
$element = new DateTimeElement('foo');
142+
$element->setAttributes(
143+
[
144+
'inclusive' => true,
145+
'max' => '2001-01-01T00',
146+
'step' => '1',
147+
]
148+
);
149+
$this->expectException(InvalidArgumentException::class);
150+
$element->getInputSpecification();
151+
}
122152
}

0 commit comments

Comments
 (0)