[BUGFIX] DateValidator fails to validate incorrect dates
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Classes / Validation / DateValidator.php
1 <?php
2 namespace TYPO3\CMS\Form\Validation;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Date rule
19 *
20 * @author Patrick Broens <patrick@patrickbroens.nl>
21 */
22 class DateValidator extends \TYPO3\CMS\Form\Validation\AbstractValidator {
23
24 /**
25 * Constant for localisation
26 *
27 * @var string
28 */
29 const LOCALISATION_OBJECT_NAME = 'tx_form_system_validate_date';
30
31 /**
32 * strftime format for date
33 *
34 * @var string
35 */
36 protected $format;
37
38 /**
39 * Constructor
40 *
41 * @param array $arguments Typoscript configuration
42 */
43 public function __construct($arguments) {
44 $this->setFormat($arguments['format']);
45 parent::__construct($arguments);
46 }
47
48 /**
49 * Returns TRUE if submitted value validates according to rule
50 *
51 * @return boolean
52 * @see \TYPO3\CMS\Form\Validation\ValidatorInterface::isValid()
53 */
54 public function isValid() {
55 if ($this->requestHandler->has($this->fieldName)) {
56 $value = $this->requestHandler->getByMethod($this->fieldName);
57 if (function_exists('strptime')) {
58 $parsedDate = strptime($value, $this->format);
59 $parsedDateYear = $parsedDate['tm_year'] + 1900;
60 $parsedDateMonth = $parsedDate['tm_mon'] + 1;
61 $parsedDateDay = $parsedDate['tm_mday'];
62 return checkdate($parsedDateMonth, $parsedDateDay, $parsedDateYear);
63 } else {
64 // %a => D : An abbreviated textual representation of the day (conversion works only for english)
65 // %A => l : A full textual representation of the day (conversion works only for english)
66 // %d => d : Day of the month, 2 digits with leading zeros
67 // %e => j : Day of the month, 2 digits without leading zeros
68 // %j => z : Day of the year, 3 digits with leading zeros
69 // %b => M : Abbreviated month name, based on the locale (conversion works only for english)
70 // %B => F : Full month name, based on the locale (conversion works only for english)
71 // %h => M : Abbreviated month name, based on the locale (an alias of %b) (conversion works only for english)
72 // %m => m : Two digit representation of the month
73 // %y => y : Two digit representation of the year
74 // %Y => Y : Four digit representation for the year
75 $dateTimeFormat = str_replace(
76 array('%a', '%A', '%d', '%e', '%j', '%b', '%B', '%h', '%m', '%y', '%Y'),
77 array('D', 'l', 'd', 'j', 'z', 'M', 'F', 'M', 'm', 'y', 'Y'),
78 $this->format
79 );
80 $dateTimeObject = date_create_from_format($dateTimeFormat, $value);
81 if ($dateTimeObject === FALSE) {
82 return FALSE;
83 }
84
85 return $value === $dateTimeObject->format($dateTimeFormat);
86 }
87 }
88 return TRUE;
89 }
90
91 /**
92 * Set the format of the date
93 *
94 * @param string $format strftime format
95 * @return Rule object
96 */
97 public function setFormat($format) {
98 if ($format === NULL) {
99 $this->format = '%e-%m-%Y';
100 } else {
101 $this->format = (string) $format;
102 }
103 return $this;
104 }
105
106 /**
107 * Substitute makers in the message text
108 * Overrides the abstract
109 *
110 * @param string $message Message text with markers
111 * @return string Message text with substituted markers
112 */
113 protected function substituteValues($message) {
114 $humanReadableDateFormat = $this->humanReadableDateFormat($this->format);
115 $message = str_replace('%format', $humanReadableDateFormat, $message);
116 return $message;
117 }
118
119 /**
120 * Converts strftime date format to human readable format
121 * according to local language.
122 *
123 * Example for default language: %e-%m-%Y becomes d-mm-yyyy
124 *
125 * @param string $format strftime format
126 * @return string Human readable format
127 */
128 protected function humanReadableDateFormat($format) {
129 $label = get_class($this) . '.strftime.';
130 $pairs = array(
131 '%A' => $this->localizationHandler->getLocalLanguageLabel($label . 'A'),
132 '%a' => $this->localizationHandler->getLocalLanguageLabel($label . 'a'),
133 '%d' => $this->localizationHandler->getLocalLanguageLabel($label . 'd'),
134 '%e' => $this->localizationHandler->getLocalLanguageLabel($label . 'e'),
135 '%B' => $this->localizationHandler->getLocalLanguageLabel($label . 'B'),
136 '%b' => $this->localizationHandler->getLocalLanguageLabel($label . 'b'),
137 '%m' => $this->localizationHandler->getLocalLanguageLabel($label . 'm'),
138 '%Y' => $this->localizationHandler->getLocalLanguageLabel($label . 'Y'),
139 '%y' => $this->localizationHandler->getLocalLanguageLabel($label . 'y'),
140 '%H' => $this->localizationHandler->getLocalLanguageLabel($label . 'H'),
141 '%I' => $this->localizationHandler->getLocalLanguageLabel($label . 'I'),
142 '%M' => $this->localizationHandler->getLocalLanguageLabel($label . 'M'),
143 '%S' => $this->localizationHandler->getLocalLanguageLabel($label . 'S')
144 );
145 $humanReadableFormat = str_replace(array_keys($pairs), array_values($pairs), $format);
146 return $humanReadableFormat;
147 }
148
149 }