diff --git a/core/modules/datetime/config/schema/datetime.schema.yml b/core/modules/datetime/config/schema/datetime.schema.yml index 406a2fd..4fe710d 100644 --- a/core/modules/datetime/config/schema/datetime.schema.yml +++ b/core/modules/datetime/config/schema/datetime.schema.yml @@ -7,6 +7,9 @@ field.storage_settings.datetime: datetime_type: type: string label: 'Date type' + enddate_get: + type: string + label: 'Collect end date' field.field_settings.datetime: type: mapping diff --git a/core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php b/core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php index a7dd1c3..d6e54d0 100644 --- a/core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php +++ b/core/modules/datetime/src/Plugin/Field/FieldType/DateTimeItem.php @@ -33,6 +33,7 @@ class DateTimeItem extends FieldItemBase { public static function defaultStorageSettings() { return array( 'datetime_type' => 'datetime', + 'enddate_get' => FALSE, ) + parent::defaultStorageSettings(); } @@ -47,20 +48,38 @@ public static function defaultStorageSettings() { const DATETIME_TYPE_DATETIME = 'datetime'; /** + * Value for the 'datetime_type' setting: store a date and time. + */ + const DATETIME_TYPE_DATETIMERANGE = 'datetimerange'; + + /** * {@inheritdoc} */ public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) { $properties['value'] = DataDefinition::create('datetime_iso8601') - ->setLabel(t('Date value')) + ->setLabel(t('Date value (start)')) ->setRequired(TRUE); $properties['date'] = DataDefinition::create('any') - ->setLabel(t('Computed date')) - ->setDescription(t('The computed DateTime object.')) + ->setLabel(t('Computed date (start)')) + ->setDescription(t('The computed start DateTime object.')) ->setComputed(TRUE) ->setClass('\Drupal\datetime\DateTimeComputed') ->setSetting('date source', 'value'); + // TODO a check here fatals. + //if ($field_definition->getSetting('enddate_get')) { + $properties['value2'] = DataDefinition::create('datetime_iso8601') + ->setLabel(t('Date value (end)')); + + $properties['date2'] = DataDefinition::create('any') + ->setLabel(t('Computed date (end)')) + ->setDescription(t('The computed end DateTime object.')) + ->setComputed(TRUE) + ->setClass('\Drupal\datetime\DateTimeComputed') + ->setSetting('date source', 'value2'); + //} + return $properties; } @@ -68,10 +87,10 @@ public static function propertyDefinitions(FieldStorageDefinitionInterface $fiel * {@inheritdoc} */ public static function schema(FieldStorageDefinitionInterface $field_definition) { - return array( + $schema = array( 'columns' => array( 'value' => array( - 'description' => 'The date value.', + 'description' => 'The start date value.', 'type' => 'varchar', 'length' => 20, ), @@ -80,6 +99,19 @@ public static function schema(FieldStorageDefinitionInterface $field_definition) 'value' => array('value'), ), ); + + if ($field_definition->getSetting('enddate_get')) { + $schema['columns']['value2'] = array( + 'description' => 'The end date value.', + 'type' => 'varchar', + 'length' => 20, + ); + $schema['indexes']['value2'] = array( + 'value2' + ); + } + + return $schema; } /** @@ -94,11 +126,19 @@ public function storageSettingsForm(array &$form, FormStateInterface $form_state '#description' => t('Choose the type of date to create.'), '#default_value' => $this->getSetting('datetime_type'), '#options' => array( + static::DATETIME_TYPE_DATE => t('Date (all day)'), static::DATETIME_TYPE_DATETIME => t('Date and time'), - static::DATETIME_TYPE_DATE => t('Date only'), + static::DATETIME_TYPE_DATETIMERANGE => t('Date and time with range'), ), ); + $element['enddate_get'] = array( + '#type' => 'checkbox', + '#title' => t('Collect an end date'), + '#default_value' => $this->getSetting('enddate_get'), + '#disabled' => $has_data, + ); + return $element; } @@ -107,15 +147,22 @@ public function storageSettingsForm(array &$form, FormStateInterface $form_state */ public static function generateSampleValue(FieldDefinitionInterface $field_definition) { $type = $field_definition->getSetting('datetime_type'); + $collect_end_date = $field_definition->getSetting('enddate_get'); // Just pick a date in the past year. No guidance is provided by this Field // type. $timestamp = REQUEST_TIME - mt_rand(0, 86400*365); if ($type == DateTimeItem::DATETIME_TYPE_DATE) { $values['value'] = gmdate(DATETIME_DATE_STORAGE_FORMAT, $timestamp); + if ($collect_end_date) { + $values['value2'] = gmdate(DATETIME_DATE_STORAGE_FORMAT, $timestamp); + } } else { $values['value'] = gmdate(DATETIME_DATETIME_STORAGE_FORMAT, $timestamp); + if ($collect_end_date) { + $values['value2'] = gmdate(DATETIME_DATETIME_STORAGE_FORMAT, $timestamp); + } } return $values; } @@ -136,6 +183,9 @@ public function onChange($property_name, $notify = TRUE) { if ($property_name == 'value') { $this->date = NULL; } + if ($property_name == 'value2') { + $this->date2 = NULL; + } parent::onChange($property_name, $notify); } diff --git a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php index dfe750e..192e52f 100644 --- a/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php +++ b/core/modules/datetime/src/Plugin/Field/FieldWidget/DateTimeWidgetBase.php @@ -52,6 +52,33 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $element['value']['#default_value'] = $date; } + if ($this->getFieldSetting('enddate_get')) { + + $element['value']['#title'] = t('Start date'); + + $element['value2'] = array( + '#title' => t('End date'), + '#type' => 'datetime', + '#default_value' => NULL, + '#date_increment' => 1, + '#date_timezone' => drupal_get_user_timezone(), + '#required' => $element['#required'], + ); + + if ($items[$delta]->date2) { + $date = $items[$delta]->date2; + // The date was created and verified during field_load(), so it is safe to + // use without further inspection. + 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); + } + $date->setTimezone(new \DateTimeZone($element['value2']['#date_timezone'])); + $element['value2']['#default_value'] = $date; + } + } + return $element; } @@ -62,9 +89,22 @@ public function massageFormValues(array $values, array $form, FormStateInterface // The widget form element type has transformed the value to a // DrupalDateTime object at this point. We need to convert it back to the // storage timezone and format. + $properties = array('value'); + if ($this->getFieldSetting('enddate_get')) { + $properties[] = 'value2'; + } foreach ($values as &$item) { - if (!empty($item['value']) && $item['value'] instanceof DrupalDateTime) { - $date = $item['value']; + foreach ($properties as $property) { + if (!empty($item[$property]) && $item[$property] instanceof DrupalDateTime) { + $this->massageDateProperty($item, $property); + } + } + } + return $values; + } + + public function massageDateProperty(&$item, $property) { + $date = $item[$property]; switch ($this->getFieldSetting('datetime_type')) { case DateTimeItem::DATETIME_TYPE_DATE: // If this is a date-only field, set it to the default time so the @@ -79,10 +119,7 @@ public function massageFormValues(array $values, array $form, FormStateInterface } // Adjust the date for storage. $date->setTimezone(new \DateTimezone(DATETIME_STORAGE_TIMEZONE)); - $item['value'] = $date->format($format); - } - } - return $values; - } + $item[$property] = $date->format($format); + } } diff --git a/core/modules/datetime/src/Tests/DateTimeItemTest.php b/core/modules/datetime/src/Tests/DateTimeItemTest.php index d83d2a2..6394cae 100644 --- a/core/modules/datetime/src/Tests/DateTimeItemTest.php +++ b/core/modules/datetime/src/Tests/DateTimeItemTest.php @@ -9,6 +9,8 @@ use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldItemInterface; +use Drupal\entity_test\Entity\EntityTest; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Tests\FieldUnitTestBase; /** @@ -122,4 +124,25 @@ public function testSetValueProperty() { $this->assertEqual($entity->field_datetime[0]->value, $value, '"Value" property can be set directly.'); } + /** + * Tests collecting an end date. + */ + public function testEnddate() { + /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ + $field_storage = FieldStorageConfig::load('entity_test.field_datetime'); + $field_storage->setSetting('enddate_get', TRUE); + $field_storage->save(); + + $entity = EntityTest::create(); + $value = '2014-01-01T20:00:00Z'; + $value2 = '2014-02-01T20:00:00Z'; + + $entity->set('field_datetime', ['value' => $value, 'value2' => $value2]); + $entity->save(); + + // Load the entity. + $id = $entity->id(); + $entity = EntityTest::load($id); + $this->assertEqual($value2, $entity->field_datetime[0]->value2, '"end date" property can be set.'); + } }