diff --git a/core/lib/Drupal/Core/Datetime/Element/Datelist.php b/core/lib/Drupal/Core/Datetime/Element/Datelist.php index b0a990f..b560065 100644 --- a/core/lib/Drupal/Core/Datetime/Element/Datelist.php +++ b/core/lib/Drupal/Core/Datetime/Element/Datelist.php @@ -55,14 +55,7 @@ public static function valueCallback(&$element, $input, FormStateInterface $form $date = NULL; if ($input !== FALSE) { $return = $input; - $filled_keys = TRUE; - foreach ($input as $key => $value) { - if (empty($value)) { - $filled_keys = FALSE; - break; - } - } - if ($filled_keys) { + if (is_null(static::checkEmptyInputs($input, $parts))) { if (isset($input['ampm'])) { if ($input['ampm'] == 'pm' && $input['hour'] < 12) { $input['hour'] += 12; @@ -309,6 +302,7 @@ public static function validateDatelist(&$element, FormStateInterface $form_stat $input_exists = FALSE; $input = NestedArray::getValue($form_state->getValues(), $element['#parents'], $input_exists); if ($input_exists) { + $first_empty = static::checkEmptyInputs($input, $element['#date_part_order']); // If there's empty input and the field is not required, set it to empty. if (empty($input['year']) && empty($input['month']) && empty($input['day']) && !$element['#required']) { @@ -318,6 +312,10 @@ public static function validateDatelist(&$element, FormStateInterface $form_stat elseif (empty($input['year']) && empty($input['month']) && empty($input['day']) && $element['#required']) { $form_state->setError($element, t('The %field date is required.')); } + elseif (!is_null($first_empty)) { + $message = t('The %field date is invalid. A value must be selected for %part.', array('%field' => !empty($element['#title']) ? $element['#title'] : '', '%part' => $first_empty)); + $form_state->setError($element, $message); + } else { // If the input is valid, set it. $date = $input['object']; @@ -333,6 +331,30 @@ public static function validateDatelist(&$element, FormStateInterface $form_stat } /** + * Checks the input array for empty values. + * + * Input array keys are checked against values in the parts array. Elements + * not in the parts array are ignored. If no empty values are found, null is + * returned. Otherwise, returns the first key in the input array that has an + * empty value. + * + * @param array $input + * + * @param array $parts + * + * @return string + * + */ + protected static function checkEmptyInputs($input, $parts) { + foreach ($parts as $part) { + if (empty($input[$part])) { + return $part; + } + } + return null; + } + + /** * Rounds minutes and seconds to nearest requested value. * * @param $date diff --git a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php index 7bccf89..5291fc6 100644 --- a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php @@ -255,8 +255,6 @@ public function testDateTimezoneWithDateTimeObject() { * Expected result of checkArray method * @param array $date_value * Input argument for DateTimePlus::checkArray(). - * @param string $message - * Message to print on test failure. * * @dataProvider providerTestCheckArray *