Loading core/lib/Drupal/Core/Datetime/Element/Datetime.php +15 −1 Original line number Diff line number Diff line Loading @@ -389,8 +389,22 @@ public static function validateDatetime(&$element, FormStateInterface $form_stat // If the date is valid, set it. $date = $input['object']; if ($date instanceof DrupalDateTime && !$date->hasErrors()) { $range = static::datetimeRangeYears($element['#date_year_range']); $min = DrupalDateTime::createFromArray(['year' => $range[0]], $date->getTimezone()); $max = DrupalDateTime::createFromArray(['year' => $range[1] + 1], $date->getTimezone()); // Validate the date. It's valid if it's within the valid year range. if ($date->getTimestamp() < $min->getTimestamp() || $date->getTimestamp() >= $max->getTimestamp()) { $form_state->setError( $element, t('The %field date is invalid. Date should be in the %min-%max year range.', ['%field' => $title, '%min' => $range[0], '%max' => $range[1]]) ); } else { $form_state->setValueForElement($element, $date); } } // If the date is invalid, set an error. A reminder of the required // format in the message provides a good UX. else { Loading core/tests/Drupal/KernelTests/Core/Datetime/DatetimeElementFormTest.php +56 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,17 @@ public function buildForm(array $form, FormStateInterface $form_state, string $d '#date_time_element' => 'HTML Time', ]; // Element with a year range. $form['range_datetime_element'] = [ '#title' => 'range_datetime_element', '#type' => 'datetime', '#date_date_format' => 'Y-m-d', '#date_time_format' => 'H:i:s', '#date_date_element' => 'HTML Date', '#date_time_element' => 'HTML Time', '#date_year_range' => '1850:3000', ]; // Element with #required_error. $form['datetime_required_error'] = [ '#type' => 'datetime', Loading Loading @@ -223,6 +234,51 @@ public function testTimezoneHandling(): void { $this->assertEquals('UTC', $form['datetime_element']['#date_timezone']); } /** * Tests that year range is validated. */ public function testRangeValidate(): void { // Tests with a date after maximum. $formState = new FormState(); $formState->setValue(['range_datetime_element', 'date'], '4000-01-01'); $formState->setValue(['range_datetime_element', 'time'], '10:10'); $form = \Drupal::formBuilder()->getForm($this); \Drupal::formBuilder()->submitForm($this, $formState); $this->assertEquals( 'The range_datetime_element date is invalid. Date should be in the 1850-3000 year range.', $formState->getError($form['range_datetime_element']) ); // Tests with a date before minimum. $formState = new FormState(); $formState->setValue(['range_datetime_element', 'date'], '1000-01-01'); $formState->setValue(['range_datetime_element', 'time'], '10:10'); $form = \Drupal::formBuilder()->getForm($this); \Drupal::formBuilder()->submitForm($this, $formState); $this->assertEquals( 'The range_datetime_element date is invalid. Date should be in the 1850-3000 year range.', $formState->getError($form['range_datetime_element']) ); // Tests with a date barely outside range. $formState = new FormState(); $formState->setValue(['range_datetime_element', 'date'], '3001-01-01'); $formState->setValue(['range_datetime_element', 'time'], '00:00'); $form = \Drupal::formBuilder()->getForm($this); \Drupal::formBuilder()->submitForm($this, $formState); $this->assertEquals( 'The range_datetime_element date is invalid. Date should be in the 1850-3000 year range.', $formState->getError($form['range_datetime_element']) ); // Tests with a date inside range. $formState = new FormState(); $formState->setValue(['range_datetime_element', 'date'], '2000-01-01'); $formState->setValue(['range_datetime_element', 'time'], '10:10'); \Drupal::formBuilder()->submitForm($this, $formState); $this->assertEmpty($formState->getError($form['range_datetime_element'])); } /** * {@inheritdoc} */ Loading Loading
core/lib/Drupal/Core/Datetime/Element/Datetime.php +15 −1 Original line number Diff line number Diff line Loading @@ -389,8 +389,22 @@ public static function validateDatetime(&$element, FormStateInterface $form_stat // If the date is valid, set it. $date = $input['object']; if ($date instanceof DrupalDateTime && !$date->hasErrors()) { $range = static::datetimeRangeYears($element['#date_year_range']); $min = DrupalDateTime::createFromArray(['year' => $range[0]], $date->getTimezone()); $max = DrupalDateTime::createFromArray(['year' => $range[1] + 1], $date->getTimezone()); // Validate the date. It's valid if it's within the valid year range. if ($date->getTimestamp() < $min->getTimestamp() || $date->getTimestamp() >= $max->getTimestamp()) { $form_state->setError( $element, t('The %field date is invalid. Date should be in the %min-%max year range.', ['%field' => $title, '%min' => $range[0], '%max' => $range[1]]) ); } else { $form_state->setValueForElement($element, $date); } } // If the date is invalid, set an error. A reminder of the required // format in the message provides a good UX. else { Loading
core/tests/Drupal/KernelTests/Core/Datetime/DatetimeElementFormTest.php +56 −0 Original line number Diff line number Diff line Loading @@ -99,6 +99,17 @@ public function buildForm(array $form, FormStateInterface $form_state, string $d '#date_time_element' => 'HTML Time', ]; // Element with a year range. $form['range_datetime_element'] = [ '#title' => 'range_datetime_element', '#type' => 'datetime', '#date_date_format' => 'Y-m-d', '#date_time_format' => 'H:i:s', '#date_date_element' => 'HTML Date', '#date_time_element' => 'HTML Time', '#date_year_range' => '1850:3000', ]; // Element with #required_error. $form['datetime_required_error'] = [ '#type' => 'datetime', Loading Loading @@ -223,6 +234,51 @@ public function testTimezoneHandling(): void { $this->assertEquals('UTC', $form['datetime_element']['#date_timezone']); } /** * Tests that year range is validated. */ public function testRangeValidate(): void { // Tests with a date after maximum. $formState = new FormState(); $formState->setValue(['range_datetime_element', 'date'], '4000-01-01'); $formState->setValue(['range_datetime_element', 'time'], '10:10'); $form = \Drupal::formBuilder()->getForm($this); \Drupal::formBuilder()->submitForm($this, $formState); $this->assertEquals( 'The range_datetime_element date is invalid. Date should be in the 1850-3000 year range.', $formState->getError($form['range_datetime_element']) ); // Tests with a date before minimum. $formState = new FormState(); $formState->setValue(['range_datetime_element', 'date'], '1000-01-01'); $formState->setValue(['range_datetime_element', 'time'], '10:10'); $form = \Drupal::formBuilder()->getForm($this); \Drupal::formBuilder()->submitForm($this, $formState); $this->assertEquals( 'The range_datetime_element date is invalid. Date should be in the 1850-3000 year range.', $formState->getError($form['range_datetime_element']) ); // Tests with a date barely outside range. $formState = new FormState(); $formState->setValue(['range_datetime_element', 'date'], '3001-01-01'); $formState->setValue(['range_datetime_element', 'time'], '00:00'); $form = \Drupal::formBuilder()->getForm($this); \Drupal::formBuilder()->submitForm($this, $formState); $this->assertEquals( 'The range_datetime_element date is invalid. Date should be in the 1850-3000 year range.', $formState->getError($form['range_datetime_element']) ); // Tests with a date inside range. $formState = new FormState(); $formState->setValue(['range_datetime_element', 'date'], '2000-01-01'); $formState->setValue(['range_datetime_element', 'time'], '10:10'); \Drupal::formBuilder()->submitForm($this, $formState); $this->assertEmpty($formState->getError($form['range_datetime_element'])); } /** * {@inheritdoc} */ Loading