diff --git a/core/lib/Drupal/Core/Datetime/Element/Datelist.php b/core/lib/Drupal/Core/Datetime/Element/Datelist.php index c68a787..2caa4ca 100644 --- a/core/lib/Drupal/Core/Datetime/Element/Datelist.php +++ b/core/lib/Drupal/Core/Datetime/Element/Datelist.php @@ -252,7 +252,7 @@ public static function processDatelist(&$element, FormStateInterface $form_state $title = ''; } - $default = !empty($element['#value'][$part]) ? $element['#value'][$part] : ''; + $default = isset($element['#value'][$part]) && trim($element['#value'][$part]) != '' ? $element['#value'][$part] : ''; $value = $date instanceOf DrupalDateTime && !$date->hasErrors() ? $date->format($format) : $default; if (!empty($value) && $part != 'ampm') { $value = intval($value); @@ -313,9 +313,8 @@ public static function validateDatelist(&$element, FormStateInterface $form_stat $form_state->setError($element, t('The %field date is required.')); } elseif (!empty($all_empty)) { - foreach ( $all_empty as $value ){ - $message = t('A value must be selected for %part.', array('%part' => $value)); - $form_state->setError($element[$value], $message); + foreach ($all_empty as $value){ + $form_state->setError($element[$value], t('A value must be selected for %part.', array('%part' => $value))); } } else { @@ -341,20 +340,17 @@ public static function validateDatelist(&$element, FormStateInterface $form_stat * returned array is empty. * * @param array $input - * Array of individual inputs to check for value + * Array of individual inputs to check for value. * @param array $parts - * Array to check input against, ignoring elements not in this array + * Array to check input against, ignoring elements not in this array. + * * @return array - * Array of keys from the input array that have no value, may be empty + * Array of keys from the input array that have no value, may be empty. */ protected static function checkEmptyInputs($input, $parts) { - $empty_parts = []; - foreach ($parts as $part) { - if (empty($input[$part])) { - $empty_parts[] = $part; - } - } - return $empty_parts; + // Filters out empty array values, any valid value would have a string length. + $filtered_input = array_filter($input, 'strlen'); + return array_diff($parts, array_keys($filtered_input)); } /** diff --git a/core/modules/datetime/src/Tests/DateTimeFieldTest.php b/core/modules/datetime/src/Tests/DateTimeFieldTest.php index 70ec207..44e542a 100644 --- a/core/modules/datetime/src/Tests/DateTimeFieldTest.php +++ b/core/modules/datetime/src/Tests/DateTimeFieldTest.php @@ -492,11 +492,43 @@ function testDatelistWidget() { ->save(); \Drupal::entityManager()->clearCachedFieldDefinitions(); - // Display creation form. + // Test the widget for validation notifications. + foreach ($this->datelistDataProvider() as $data) { + list($date_value, $expected) = $data; + + // Display creation form. + $this->drupalGet('entity_test/add'); + + // Submit a partial date and ensure and error message is provided. + $edit = array(); + foreach ($date_value as $part => $value) { + $edit["{$field_name}[0][value][$part]"] = $value; + } + + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertResponse(200); + $this->assertText(t($expected)); + } + + // Test the widget for complete input with zeros as part of selections. + $this->drupalGet('entity_test/add'); + + $date_value = array('year' => 2012, 'month' => '12', 'day' => '31', 'hour' => '0', 'minute' => '0'); + $edit = array(); + foreach ($date_value as $part => $value) { + $edit["{$field_name}[0][value][$part]"] = $value; + } + + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertResponse(200); + preg_match('|entity_test/manage/(\d+)|', $this->url, $match); + $id = $match[1]; + $this->assertText(t('entity_test @id has been created.', array('@id' => $id))); + + // Test the widget to ensure zeros are not deselected on validation. $this->drupalGet('entity_test/add'); - // Submit a partial date and ensure and error message is provided - $date_value = array('year' => 2012, 'month' => '', 'day' => '', 'hour' => '', 'minute' => ''); + $date_value = array('year' => 2012, 'month' => '12', 'day' => '31', 'hour' => '', 'minute' => '0'); $edit = array(); foreach ($date_value as $part => $value) { $edit["{$field_name}[0][value][$part]"] = $value; @@ -504,7 +536,26 @@ function testDatelistWidget() { $this->drupalPostForm(NULL, $edit, t('Save')); $this->assertResponse(200); - $this->assertTextPattern('/(error has)|(errors have) been found/', 'Date validation error found'); + $this->assertOptionSelected("edit-$field_name-0-value-minute", '0', 'Correct minute selected.'); + } + + /** + * The data provider for testing the validation of the datelist widget. + * + * @return array + * An array of datelist input permutations to test. + */ + protected function datelistDataProvider() { + return [ + // Year only selected, validation error on Month, Day, Hour, Minute. + [['year' => 2012, 'month' => '', 'day' => '', 'hour' => '', 'minute' => ''], '4 errors have been found: Month, Day, Hour, Minute'], + // Year and Month selected, validation error on Day, Hour, Minute. + [['year' => 2012, 'month' => '12', 'day' => '', 'hour' => '', 'minute' => ''], '3 errors have been found: Day, Hour, Minute'], + // Year, Month and Day selected, validation error on Hour, Minute. + [['year' => 2012, 'month' => '12', 'day' => '31', 'hour' => '', 'minute' => ''], '2 errors have been found: Hour, Minute'], + // Year, Month, Day and Hour selected, validation error on Minute only. + [['year' => 2012, 'month' => '12', 'day' => '31', 'hour' => '0', 'minute' => ''], '1 error has been found: Minute'], + ]; } /**