diff --git a/core/modules/datetime/config/schema/datetime.schema.yml b/core/modules/datetime/config/schema/datetime.schema.yml index 4074ff2..05e9fc8 100644 --- a/core/modules/datetime/config/schema/datetime.schema.yml +++ b/core/modules/datetime/config/schema/datetime.schema.yml @@ -9,15 +9,10 @@ field.datetime.settings: label: 'Date type' field.datetime.instance_settings: - type: mapping - label: 'Datetime settings' - mapping: - default_value: - type: string - label: 'Default date' - user_register_form: - type: boolean - label: 'Display on user registration form.' + type: sequence + label: 'Settings' + sequence: + - type: string field.datetime.value: type: sequence diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module index 78f1874..ccf1a0c 100644 --- a/core/modules/datetime/datetime.module +++ b/core/modules/datetime/datetime.module @@ -168,48 +168,6 @@ function datetime_datelist_widget_validate(&$element, &$form_state) { } /** - * Sets a default value for an empty date field. - * - * Callback for $instance['default_value_function'], as implemented by - * Drupal\datetime\Plugin\Field\FieldWidget\DateTimeDatepicker. - * - * @param $entity_type - * - * @param $entity - * - * @param array $field - * - * @param array $instance - * - * @param $langcode - * - * - * @return array - * - */ -function datetime_default_value($entity, $field, $instance, $langcode) { - - $value = ''; - $date = ''; - if ($instance->getFieldSetting('default_value') == 'now') { - // A default value should be in the format and timezone used for date - // storage. - $date = new DrupalDateTime('now', DATETIME_STORAGE_TIMEZONE); - $storage_format = $field->getFieldSetting('datetime_type') == 'date' ? DATETIME_DATE_STORAGE_FORMAT: DATETIME_DATETIME_STORAGE_FORMAT; - $value = $date->format($storage_format); - } - - // We only provide a default value for the first item, as do all fields. - // Otherwise, there is no way to clear out unwanted values on multiple value - // fields. - $item = array(); - $item[0]['value'] = $value; - $item[0]['date'] = $date; - - return $item; -} - -/** * Sets a consistent time on a date without time. * * The default time for a date without time can be anything, so long as it is diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeFieldItemList.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeFieldItemList.php new file mode 100644 index 0000000..9602621 --- /dev/null +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeFieldItemList.php @@ -0,0 +1,86 @@ +getFieldDefinition()->default_value_function)) { + $default_value = $this->getFieldDefinition()->default_value; + + $element = array( + '#parents' => array('default_value_input'), + 'default_date' => array( + '#type' => 'select', + '#title' => t('Default date'), + '#description' => t('Set a default value for this date.'), + '#default_value' => isset($default_value[0]['default_date']) ? $default_value[0]['default_date'] : '', + '#options' => array(static::DEFAULT_VALUE_NOW => t('The current date')), + '#empty_value' => '', + ) + ); + + return $element; + } + } + + /** + * {@inheritdoc} + */ + public function defaultValuesFormValidate(array $element, array &$form, array &$form_state) { } + + /** + * {@inheritdoc} + */ + public function defaultValuesFormSubmit(array $element, array &$form, array &$form_state) { + if ($form_state['values']['default_value_input']['default_date']) { + return array($form_state['values']['default_value_input']); + } + return array(); + } + + /** + * {@inheritdoc} + */ + public function getDefaultValue() { + $default_value = parent::getDefaultValue(); + + if (isset($default_value[0]['default_date']) && $default_value[0]['default_date'] == static::DEFAULT_VALUE_NOW) { + // A default value should be in the format and timezone used for date + // storage. + $date = new DrupalDateTime('now', DATETIME_STORAGE_TIMEZONE); + $storage_format = $this->getFieldDefinition()->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE ? DATETIME_DATE_STORAGE_FORMAT: DATETIME_DATETIME_STORAGE_FORMAT; + $value = $date->format($storage_format); + // We only provide a default value for the first item, as do all fields. + // Otherwise, there is no way to clear out unwanted values on multiple value + // fields. + $default_value = array( + array( + 'value' => $value, + 'date' => $date, + ) + ); + } + return $default_value; + } + +} diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php index 3fbcca1..dc2c201 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php @@ -23,16 +23,24 @@ * settings = { * "datetime_type" = "datetime" * }, - * instance_settings = { - * "default_value" = "now" - * }, * default_widget = "datetime_default", - * default_formatter = "datetime_default" + * default_formatter = "datetime_default", + * list_class = "\Drupal\datetime\Plugin\Field\FieldType\DateTimeFieldItemList" * ) */ class DateTimeItem extends ConfigFieldItemBase implements PrepareCacheInterface { /** + * Value for the 'datetime_type' setting: store only a date. + */ + const DATETIME_TYPE_DATE = 'date'; + + /** + * Value for the 'datetime_type' setting: store a date and time. + */ + const DATETIME_TYPE_DATETIME = 'datetime'; + + /** * Field definitions of the contained properties. * * @var array @@ -89,8 +97,8 @@ public function settingsForm(array $form, array &$form_state, $has_data) { '#description' => t('Choose the type of date to create.'), '#default_value' => $this->getFieldSetting('datetime_type'), '#options' => array( - 'datetime' => t('Date and time'), - 'date' => t('Date only'), + static::DATETIME_TYPE_DATETIME => t('Date and time'), + static::DATETIME_TYPE_DATE => t('Date only'), ), ); @@ -100,24 +108,6 @@ public function settingsForm(array $form, array &$form_state, $has_data) { /** * {@inheritdoc} */ - public function instanceSettingsForm(array $form, array &$form_state) { - $element = array(); - - $element['default_value'] = array( - '#type' => 'select', - '#title' => t('Default date'), - '#description' => t('Set a default value for this date.'), - '#default_value' => $this->getFieldSetting('default_value'), - '#options' => array('blank' => t('No default value'), 'now' => t('The current date')), - '#weight' => 1, - ); - - return $element; - } - - /** - * {@inheritdoc} - */ public function getCacheData() { $data = $this->getValue(); // The function generates a Date object for each field early so that it is diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldWidget/DatetimeDatelistWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldWidget/DatetimeDatelistWidget.php index 667fbff..98c3f05 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldWidget/DatetimeDatelistWidget.php +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldWidget/DatetimeDatelistWidget.php @@ -8,9 +8,7 @@ use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\WidgetBase; -use Drupal\Core\Field\FieldDefinitionInterface; -use Drupal\field\FieldInstanceInterface; -use Drupal\datetime\DateHelper; +use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; /** * Plugin implementation of the 'datetime_datelist' widget. @@ -33,29 +31,6 @@ class DateTimeDatelistWidget extends WidgetBase { /** * {@inheritdoc} */ - public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) { - // Identify the function used to set the default value. - // @todo Make this work for both configurable and nonconfigurable fields: - // https://drupal.org/node/1989468. - if ($field_definition instanceof FieldInstanceInterface) { - $field_definition->default_value_function = $this->defaultValueFunction(); - } - parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings); - } - - /** - * Returns the callback used to set a date default value. - * - * @return string - * The name of the callback to use when setting a default date value. - */ - public function defaultValueFunction() { - return 'datetime_default_value'; - } - - /** - * {@inheritdoc} - */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) { $date_order = $this->getSetting('date_order'); $time_type = $this->getSetting('time_type'); @@ -74,7 +49,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen // Identify the type of date and time elements to use. switch ($this->getFieldSetting('datetime_type')) { - case 'date': + case DateTimeItem::DATETIME_TYPE_DATE: $storage_format = DATETIME_DATE_STORAGE_FORMAT; $type_type = 'none'; break; diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldWidget/DatetimeDefaultWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldWidget/DatetimeDefaultWidget.php index 7f9708a..9389a71 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldWidget/DatetimeDefaultWidget.php +++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldWidget/DatetimeDefaultWidget.php @@ -9,7 +9,7 @@ use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\WidgetBase; use Drupal\Core\Field\FieldDefinitionInterface; -use Drupal\field\FieldInstanceInterface; +use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem; /** * Plugin implementation of the 'datetime_default' widget. @@ -35,12 +35,6 @@ class DateTimeDefaultWidget extends WidgetBase { * {@inheritdoc} */ public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) { - // Identify the function used to set the default value. - // @todo Make this work for both configurable and nonconfigurable fields: - // https://drupal.org/node/1989468. - if ($field_definition instanceof FieldInstanceInterface) { - $field_definition->default_value_function = $this->defaultValueFunction(); - } parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings); // @todo Inject this once https://drupal.org/node/2035317 is in. @@ -48,16 +42,6 @@ public function __construct($plugin_id, array $plugin_definition, FieldDefinitio } /** - * Return the callback used to set a date default value. - * - * @return string - * The name of the callback to use when setting a default date value. - */ - public function defaultValueFunction() { - return 'datetime_default_value'; - } - - /** * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) { @@ -75,7 +59,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen // Identify the type of date and time elements to use. switch ($this->getFieldSetting('datetime_type')) { - case 'date': + case DateTimeItem::DATETIME_TYPE_DATE: $date_type = 'date'; $time_type = 'none'; $date_format = $this->dateStorage->load('html_date')->getPattern($format_type); @@ -117,7 +101,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen // The date was created and verified during field_load(), so it is safe to // use without further inspection. $date->setTimezone(new \DateTimeZone($element['value']['#date_timezone'])); - if ($this->getFieldSetting('datetime_type') == 'date') { + if ($this->getFieldSetting('datetime_type') == DateTimeItem::DATETIME_TYPE_DATE) { // A date without time will pick up the current time, use the default // time. datetime_date_default_time($date); diff --git a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php similarity index 82% rename from core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php rename to core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php index 5bee2e3..c2ec068 100644 --- a/core/modules/datetime/lib/Drupal/datetime/Tests/DatetimeFieldTest.php +++ b/core/modules/datetime/lib/Drupal/datetime/Tests/DateTimeFieldTest.php @@ -13,7 +13,7 @@ /** * Tests Datetime field functionality. */ -class DatetimeFieldTest extends WebTestBase { +class DateTimeFieldTest extends WebTestBase { /** * Modules to enable. @@ -48,9 +48,11 @@ function setUp() { parent::setUp(); $web_user = $this->drupalCreateUser(array( + 'access content', 'view test entity', 'administer entity_test content', 'administer content types', + 'administer node fields', )); $this->drupalLogin($web_user); @@ -66,9 +68,6 @@ function setUp() { 'field_name' => $this->field->name, 'entity_type' => 'entity_test', 'bundle' => 'entity_test', - 'settings' => array( - 'default_value' => 'blank', - ), )); $this->instance->save(); @@ -292,40 +291,67 @@ function testDatelistWidget() { * Test default value functionality. */ function testDefaultValue() { + // Create a test content type. + $this->drupalCreateContentType(array('type' => 'date_content')); - // Change the field to a datetime field. - $this->field->settings['datetime_type'] = 'datetime'; - $this->field->save(); - $field_name = $this->field->name; + // Create a field with settings to validate. + $field = entity_create('field_entity', array( + 'name' => drupal_strtolower($this->randomName()), + 'entity_type' => 'node', + 'type' => 'datetime', + 'settings' => array('datetime_type' => 'date'), + )); + $field->save(); - // Set the default value to 'now'. - $this->instance->settings['default_value'] = 'now'; - $this->instance->default_value_function = 'datetime_default_value'; - $this->instance->save(); + $instance = entity_create('field_instance', array( + 'field_name' => $field->name, + 'entity_type' => 'node', + 'bundle' => 'date_content', + )); + $instance->save(); - // Display creation form. - $date = new DrupalDateTime(); - $date_format = 'Y-m-d'; - $this->drupalGet('entity_test/add'); + // Set now as default_value. + $instance_edit = array( + 'default_value_input[default_date]' => 'now', + ); + $this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field->name, $instance_edit, t('Save settings')); - // See if current date is set. We cannot test for the precise time because - // it may be a few seconds between the time the comparison date is created - // and the form date, so we just test the date and that the time is not - // empty. - $this->assertFieldByName("{$field_name}[0][value][date]", $date->format($date_format), 'Date element found.'); - $this->assertNoFieldByName("{$field_name}[0][value][time]", '', 'Time element found.'); + // Check that default value is selected in default value form. + $this->drupalGet('admin/structure/types/manage/date_content/fields/node.date_content.' . $field->name); + $this->assertRaw('', 'The default value is selected in instance settings page'); - // Set the default value to 'blank'. - $this->instance->settings['default_value'] = 'blank'; - $this->instance->default_value_function = 'datetime_default_value'; - $this->instance->save(); + // Check if default_date has been stored successfully. + $config_entity = $this->container->get('config.factory')->get('field.instance.node.date_content.' . $field->name)->get(); + $this->assertEqual($config_entity['default_value'][0]['default_date'], 'now', 'Default value has been stored succesfully'); - // Display creation form. - $this->drupalGet('entity_test/add'); + // Clean field_info cache in order to avoid stale cache values. + field_info_cache_clear(); - // See that no date is set. - $this->assertFieldByName("{$field_name}[0][value][date]", '', 'Date element found.'); - $this->assertFieldByName("{$field_name}[0][value][time]", '', 'Time element found.'); + // Create a new node to check that datetime field default value is today. + $new_node = entity_create('node', array('type' => 'date_content')); + $expected_date = new DrupalDateTime('now', DATETIME_STORAGE_TIMEZONE); + $this->assertEqual($new_node->get($field->name)->offsetGet(0)->value, $expected_date->format(DATETIME_DATE_STORAGE_FORMAT)); + + // Remove default value. + $instance_edit = array( + 'default_value_input[default_date]' => '', + ); + $this->drupalPostForm('admin/structure/types/manage/date_content/fields/node.date_content.' . $field->name, $instance_edit, t('Save settings')); + + // Check that default value is selected in default value form. + $this->drupalGet('admin/structure/types/manage/date_content/fields/node.date_content.' . $field->name); + $this->assertRaw('', 'The default value is selected in instance settings page'); + + // Check if default_date has been stored successfully. + $config_entity = $this->container->get('config.factory')->get('field.instance.node.date_content.' . $field->name)->get(); + $this->assertTrue(empty($config_entity['default_value']), 'Empty default value has been stored succesfully'); + + // Clean field_info cache in order to avoid stale cache values. + field_info_cache_clear(); + + // Create a new node to check that datetime field default value is today. + $new_node = entity_create('node', array('type' => 'date_content')); + $this->assertNull($new_node->get($field->name)->offsetGet(0)->value, 'Default value is not set'); } /**