From c9d63410bc03b06fbcad342da5aa4940d8149de2 Mon Sep 17 00:00:00 2001 From: Alex Pott <alex.a.pott@googlemail.com> Date: Thu, 6 Oct 2022 11:17:07 +0100 Subject: [PATCH] Issue #2993165 by kkasson, tatianag, Spokje, mpdonadio, xurizaemon, raman.b, wombatbuddy, pooja saraah, tannguyenhn, VladimirAus, ranjith_kumar_k_u, jannakha, pameeela: Date Only field shows incorrect default value when UTC date is different than user's date --- .../Field/FieldWidget/DateTimeWidgetBase.php | 8 +- .../tests/src/Functional/DateTestBase.php | 2 + .../src/Functional/DateTimeWidgetTest.php | 102 ++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 core/modules/datetime/tests/src/Functional/DateTimeWidgetTest.php diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php index aa7c959689b0..a5cbcece15f3 100644 --- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php +++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php @@ -86,10 +86,16 @@ public function massageFormValues(array $values, array $form, FormStateInterface protected function createDefaultValue($date, $timezone) { // The date was created and verified during field_load(), so it is safe to // use without further inspection. + $year = $date->format('Y'); + $month = $date->format('m'); + $day = $date->format('d'); + $date->setTimezone(new \DateTimeZone($timezone)); if ($this->getFieldSetting('datetime_type') === DateTimeItem::DATETIME_TYPE_DATE) { $date->setDefaultDateTime(); + // Reset the date to handle cases where the UTC offset is greater than + // 12 hours. + $date->setDate($year, $month, $day); } - $date->setTimezone(new \DateTimeZone($timezone)); return $date; } diff --git a/core/modules/datetime/tests/src/Functional/DateTestBase.php b/core/modules/datetime/tests/src/Functional/DateTestBase.php index 60ca92bce6cb..57cc4cb641e1 100644 --- a/core/modules/datetime/tests/src/Functional/DateTestBase.php +++ b/core/modules/datetime/tests/src/Functional/DateTestBase.php @@ -99,6 +99,8 @@ protected function setUp(): void { 'administer content types', 'bypass node access', 'administer node fields', + 'administer node form display', + 'administer node display', ]); $this->drupalLogin($web_user); diff --git a/core/modules/datetime/tests/src/Functional/DateTimeWidgetTest.php b/core/modules/datetime/tests/src/Functional/DateTimeWidgetTest.php new file mode 100644 index 000000000000..529d06c96b4d --- /dev/null +++ b/core/modules/datetime/tests/src/Functional/DateTimeWidgetTest.php @@ -0,0 +1,102 @@ +<?php + +namespace Drupal\Tests\datetime\Functional; + +use Drupal\field\Entity\FieldConfig; +use Drupal\field\Entity\FieldStorageConfig; + +/** + * Tests Datetime widgets functionality. + * + * @group datetime + */ +class DateTimeWidgetTest extends DateTestBase { + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * The default display settings to use for the formatters. + * + * @var array + */ + protected $defaultSettings = ['timezone_override' => '']; + + /** + * {@inheritdoc} + */ + protected function getTestFieldType() { + return 'datetime'; + } + + /** + * Test default value functionality. + */ + public function testDateonlyDefaultValue() { + // Create a test content type. + $this->drupalCreateContentType(['type' => 'dateonly_content']); + + // Create a field storage with settings to validate. + $field_storage = FieldStorageConfig::create([ + 'field_name' => 'field_dateonly', + 'entity_type' => 'node', + 'type' => 'datetime', + 'settings' => ['datetime_type' => 'date'], + ]); + $field_storage->save(); + + $field = FieldConfig::create([ + 'field_storage' => $field_storage, + 'bundle' => 'dateonly_content', + ]); + $field->save(); + + $edit = [ + 'fields[field_dateonly][region]' => 'content', + 'fields[field_dateonly][type]' => 'datetime_default', + ]; + $this->drupalGet('admin/structure/types/manage/dateonly_content/form-display'); + $this->submitForm($edit, 'Save'); + $this->drupalGet('admin/structure/types/manage/dateonly_content/display'); + $this->submitForm($edit, 'Save'); + + // Set now as default_value. + $edit = [ + 'default_value_input[default_date_type]' => 'now', + ]; + $this->drupalGet('admin/structure/types/manage/dateonly_content/fields/node.dateonly_content.field_dateonly'); + $this->submitForm($edit, 'Save settings'); + + // Check that default value is selected in default value form. + $this->drupalGet('admin/structure/types/manage/dateonly_content/fields/node.dateonly_content.field_dateonly'); + $option_field = $this->assertSession()->optionExists('edit-default-value-input-default-date-type', 'now'); + $this->assertTrue($option_field->hasAttribute('selected')); + $this->assertSession()->fieldValueEquals('default_value_input[default_date]', ''); + + // Loop through defined timezones to test that date-only defaults work at + // the extremes. + foreach (static::$timezones as $timezone) { + $this->setSiteTimezone($timezone); + $this->assertEquals($timezone, $this->config('system.date')->get('timezone.default'), 'Time zone set to ' . $timezone); + + $this->drupalGet('node/add/dateonly_content'); + + $request_time = $this->container->get('datetime.time')->getRequestTime(); + $today = $this->dateFormatter->format($request_time, 'html_date', NULL, $timezone); + $this->assertSession()->fieldValueEquals('field_dateonly[0][value][date]', $today); + + $edit = [ + 'title[0][value]' => $timezone, + ]; + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('dateonly_content ' . $timezone . ' has been created'); + + $node = $this->drupalGetNodeByTitle($timezone); + $today_storage = $this->dateFormatter->format($request_time, 'html_date', NULL, $timezone); + $this->assertEquals($today_storage, $node->field_dateonly->value); + } + } + +} -- GitLab