diff --git a/core/modules/datetime/datetime.views.inc b/core/modules/datetime/datetime.views.inc index d3b0d18..539f4bf 100644 --- a/core/modules/datetime/datetime.views.inc +++ b/core/modules/datetime/datetime.views.inc @@ -11,18 +11,38 @@ * Implements hook_field_views_data(). */ function datetime_field_views_data(FieldStorageConfigInterface $field_storage) { + return datetime_type_field_views_data($field_storage, [], 'value'); +} + +/** + * Helper for datetime based fields. + * + * Override the default Views data for a datetime based fields, + * adding datetime views plugins. + * + * @param FieldStorageConfigInterface $field_storage + * The field storage config entity. + * @param array $data + * Field view data or views_field_default_views_data($field_storage) if empty. + * @param string $column_name + * The schema column name with the datetime value. + * + * @return array + * The array of field views data with the datetime plugin. + */ +function datetime_type_field_views_data(FieldStorageConfigInterface $field_storage, $data, $column_name) { // @todo This code only covers configurable fields, handle base table fields // in https://www.drupal.org/node/2489476. - $data = views_field_default_views_data($field_storage); + $data = (empty($data)) ? views_field_default_views_data($field_storage) : $data; foreach ($data as $table_name => $table_data) { // Set the 'datetime' filter type. - $data[$table_name][$field_storage->getName() . '_value']['filter']['id'] = 'datetime'; + $data[$table_name][$field_storage->getName() . '_' . $column_name]['filter']['id'] = 'datetime'; // Set the 'datetime' argument type. - $data[$table_name][$field_storage->getName() . '_value']['argument']['id'] = 'datetime'; + $data[$table_name][$field_storage->getName() . '_' . $column_name]['argument']['id'] = 'datetime'; // Create year, month, and day arguments. - $group = $data[$table_name][$field_storage->getName() . '_value']['group']; + $group = $data[$table_name][$field_storage->getName() . '_' . $column_name]['group']; $arguments = [ // Argument type => help text. 'year' => t('Date in the form of YYYY.'), @@ -33,11 +53,12 @@ function datetime_field_views_data(FieldStorageConfigInterface $field_storage) { 'full_date' => t('Date in the form of CCYYMMDD.'), ]; foreach ($arguments as $argument_type => $help_text) { - $data[$table_name][$field_storage->getName() . '_value_' . $argument_type] = [ - 'title' => $field_storage->getLabel() . ' (' . $argument_type . ')', + $column_name_text = $column_name !== 'value' ? ':' . $column_name : ''; + $data[$table_name][$field_storage->getName() . '_' . $column_name . '_' . $argument_type] = [ + 'title' => $field_storage->getLabel() . $column_name_text . ' (' . $argument_type . ')', 'help' => $help_text, 'argument' => [ - 'field' => $field_storage->getName() . '_value', + 'field' => $field_storage->getName() . '_' . $column_name, 'id' => 'datetime_' . $argument_type, ], 'group' => $group, @@ -45,7 +66,7 @@ function datetime_field_views_data(FieldStorageConfigInterface $field_storage) { } // Set the 'datetime' sort handler. - $data[$table_name][$field_storage->getName() . '_value']['sort']['id'] = 'datetime'; + $data[$table_name][$field_storage->getName() . '_' . $column_name]['sort']['id'] = 'datetime'; } return $data; diff --git a/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php b/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php index 0f068ab..73b453f 100644 --- a/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php +++ b/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php @@ -34,6 +34,13 @@ protected static $field_name = 'field_date'; /** + * Type of the field. + * + * @var string + */ + protected static $field_type = 'datetime'; + + /** * Nodes to test. * * @var \Drupal\node\NodeInterface[] @@ -55,7 +62,7 @@ protected function setUp() { $fieldStorage = FieldStorageConfig::create([ 'field_name' => static::$field_name, 'entity_type' => 'node', - 'type' => 'datetime', + 'type' => static::$field_type, 'settings' => ['datetime_type' => DateTimeItem::DATETIME_TYPE_DATETIME], ]); $fieldStorage->save(); diff --git a/core/modules/datetime_range/datetime_range.install b/core/modules/datetime_range/datetime_range.install new file mode 100644 index 0000000..dc16c24 --- /dev/null +++ b/core/modules/datetime_range/datetime_range.install @@ -0,0 +1,130 @@ +listAll('views.view.') as $view_config_name) { + $view = $config_factory->getEditable($view_config_name); + $displays = $view->get('display'); + + foreach ($displays as $display_name => $display) { + + // Update datetime_range filters. + if (isset($display['display_options']['filters'])) { + foreach ($display['display_options']['filters'] as $field_name => $filter) { + if ($filter['plugin_id'] == 'string') { + + // Get field config. + $filter_views_data = \Drupal\views\Views::viewsData()->get($filter['table'])[$filter['field']]['filter']; + if (!isset($filter_views_data['entity_type']) || !isset($filter_views_data['field_name'])) { + continue; + } + $field_storage_name = 'field.storage.' . $filter_views_data['entity_type'] . '.' . $filter_views_data['field_name']; + $field_configuration = $config_factory->get($field_storage_name); + + if ($field_configuration->get('type') == 'daterange') { + $ids[] = $view->get('id'); + + // Save off the base part of the config path we are updating. + $base = "display.$display_name.display_options.filters.$field_name"; + + // Set entity_type and field_name if missing. + if (!isset($filter['entity_type'])) { + $view->set($base . '.entity_type', $filter_views_data['entity_type']); + } + + // Set datetime plugin_id. + $view->set($base . '.plugin_id', 'datetime'); + + // Create datetime value array. + $datetime_value = [ + 'min' => '', + 'max' => '', + 'value' => $filter['value'], + 'type' => 'date', + ]; + + // Map string operator/value to numeric equivalent. + switch ($view->get($base . '.operator')) { + case '=': + $operator = '='; + break; + case '!=': + case 'not': + $operator = '!='; + break; + case 'starts': + $operator = 'regular_expression'; + $datetime_value['value'] = '^' . $datetime_value['value']; + break; + case 'ends': + $operator = 'regular_expression'; + $datetime_value['value'] = $datetime_value['value'] . '$'; + break; + default: + $operator = 'regular_expression'; + } + + // Set value and operator. + $view->set($base . '.value', $datetime_value); + $view->set($base . '.operator', $operator); + + // Store the changes. + $view->save(TRUE); + } + } + } + } + + // Update datetime_range sort handlers. + if (isset($display['display_options']['sorts'])) { + foreach ($display['display_options']['sorts'] as $field_name => $sort) { + if ($sort['plugin_id'] == 'standard') { + + // Get field config. + $sort_views_data = \Drupal\views\Views::viewsData()->get($sort['table'])[$sort['field']]['sort']; + if (!isset($sort_views_data['entity_type']) || !isset($sort_views_data['field_name'])) { + continue; + } + $field_storage_name = 'field.storage.' . $sort_views_data['entity_type'] . '.' . $sort_views_data['field_name']; + $field_configuration = $config_factory->get($field_storage_name); + + if ($field_configuration->get('type') == 'daterange') { + $ids[] = $view->get('id'); + + // Save off the base part of the config path we are updating. + $base = "display.$display_name.display_options.sorts.$field_name"; + + // Set entity_type and field_name if missing. + if (!isset($sort['entity_type'])) { + $view->set($base . '.entity_type', $sort_views_data['entity_type']); + } + + // Set datetime plugin_id. + $view->set($base . '.plugin_id', 'datetime'); + + // Store the changes. + $view->save(TRUE); + } + } + } + } + } + } + + if (!empty($ids)) { + $message = \Drupal::translation()->translate('Updated datetime_range filter/sort plugins for views: @ids', ['@ids' => implode(', ', array_unique($ids))]); + } + + return $message; +} diff --git a/core/modules/datetime_range/datetime_range.views.inc b/core/modules/datetime_range/datetime_range.views.inc new file mode 100644 index 0000000..6d4407b --- /dev/null +++ b/core/modules/datetime_range/datetime_range.views.inc @@ -0,0 +1,21 @@ +loadInclude('datetime', 'inc', 'datetime.views'); + + // Get datetime field data for value and end_value + $data = datetime_type_field_views_data($field_storage, [], 'value'); + $data = datetime_type_field_views_data($field_storage, $data, 'end_value'); + + return $data; +} diff --git a/core/modules/datetime_range/src/Tests/Update/DatetimeRangeViewUpdateTest.php b/core/modules/datetime_range/src/Tests/Update/DatetimeRangeViewUpdateTest.php new file mode 100644 index 0000000..fd21383 --- /dev/null +++ b/core/modules/datetime_range/src/Tests/Update/DatetimeRangeViewUpdateTest.php @@ -0,0 +1,52 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', + __DIR__ . '/../../../tests/fixtures/update/datetime_range-filter-values.php', + ]; + } + + /** + * Tests that datetime_range filter values are updated properly. + */ + public function testViewsPostUpdateDateRangeFilterValues() { + + $this->runUpdates(); + + // Load and initialize our test view. + $field_name = 'field_range_value'; + $view = View::load('test_datetime_range_filter_values'); + $data = $view->toArray(); + + // Check filter values + $filter = $data['display']['default']['display_options']['filters'][$field_name]; + + $this->assertIdentical('datetime', $filter['plugin_id']); + $this->assertIdentical('2017', $filter['value']['value']); + + // Check sort values + $sort = $data['display']['default']['display_options']['sorts'][$field_name]; + $this->assertIdentical('datetime', $sort['plugin_id']); + } + +} diff --git a/core/modules/datetime_range/src/Tests/Views/DateRangeHandlerTestBase.php b/core/modules/datetime_range/src/Tests/Views/DateRangeHandlerTestBase.php new file mode 100644 index 0000000..2dcf829 --- /dev/null +++ b/core/modules/datetime_range/src/Tests/Views/DateRangeHandlerTestBase.php @@ -0,0 +1,24 @@ +setSetting('datetime_type', DateRangeItem::DATETIME_TYPE_DATE); + $storage->save(); + + $dates = [ + // Tomorrow. + \Drupal::service('date.formatter')->format(static::$date + 86400, 'custom', DATETIME_DATE_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE), + // Today. + \Drupal::service('date.formatter')->format(static::$date, 'custom', DATETIME_DATE_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE), + // Yesterday. + \Drupal::service('date.formatter')->format(static::$date - 86400, 'custom', DATETIME_DATE_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE), + ]; + + // Node 0: Yesterday - Today. + $this->nodes[] = $this->drupalCreateNode([ + 'field_date' => [ + 'value' => $dates[2], + 'end_value' => $dates[1], + ], + ]); + // Node 1: Today - Today. + $this->nodes[] = $this->drupalCreateNode([ + 'field_date' => [ + 'value' => $dates[1], + 'end_value' => $dates[1], + ], + ]); + // Node 2: Today - Tomorrow. + $this->nodes[] = $this->drupalCreateNode([ + 'field_date' => [ + 'value' => $dates[1], + 'end_value' => $dates[0], + ], + ]); + + // Add end date filter to the test_filter_datetime view. + /** @var \Drupal\views\Entity\View $view */ + $view = \Drupal::entityTypeManager()->getStorage('view')->load('test_filter_datetime'); + $field_end = static::$field_name . '_end_value'; + $display = $view->getDisplay('default'); + $filter_end_date = $display['display_options']['filters'][static::$field_name . '_value']; + $filter_end_date['id'] = $field_end; + $filter_end_date['field'] = $field_end; + + $view->getDisplay('default')['display_options']['filters'][$field_end] = $filter_end_date; + $view->save(); + } + + /** + * Test offsets with date-only fields. + */ + public function testDateOffsets() { + $view = Views::getView('test_filter_datetime'); + $field_start = static::$field_name . '_value'; + $field_end = static::$field_name . '_end_value'; + + // Test simple operations. + $view->initHandlers(); + + // Search nodes with: + // - start date greater than or equal to 'yesterday'. + // - end date lower than or equal to 'today'. + // Expected results: nodes 0 and 1. + $view->filter[$field_start]->operator = '>='; + $view->filter[$field_start]->value['type'] = 'offset'; + $view->filter[$field_start]->value['value'] = '-1 day'; + $view->filter[$field_end]->operator = '<='; + $view->filter[$field_end]->value['type'] = 'offset'; + $view->filter[$field_end]->value['value'] = 'now'; + $view->setDisplay('default'); + $this->executeView($view); + $expected_result = [ + ['nid' => $this->nodes[0]->id()], + ['nid' => $this->nodes[1]->id()], + ]; + $this->assertIdenticalResultset($view, $expected_result, $this->map); + $view->destroy(); + + // Search nodes with: + // - start date greater than or equal to 'yesterday'. + // - end date greater than 'today'. + // Expected results: node 2. + $view->initHandlers(); + $view->filter[$field_start]->operator = '>='; + $view->filter[$field_start]->value['type'] = 'offset'; + $view->filter[$field_start]->value['value'] = '-1 day'; + $view->filter[$field_end]->operator = '>'; + $view->filter[$field_end]->value['type'] = 'offset'; + $view->filter[$field_end]->value['value'] = 'now'; + $view->setDisplay('default'); + $this->executeView($view); + $expected_result = [ + ['nid' => $this->nodes[2]->id()], + ]; + $this->assertIdenticalResultset($view, $expected_result, $this->map); + } + +} diff --git a/core/modules/datetime_range/tests/fixtures/update/datetime_range-filter-values.php b/core/modules/datetime_range/tests/fixtures/update/datetime_range-filter-values.php new file mode 100644 index 0000000..869e60a --- /dev/null +++ b/core/modules/datetime_range/tests/fixtures/update/datetime_range-filter-values.php @@ -0,0 +1,322 @@ +select('config') + ->fields('config', ['data']) + ->condition('collection', '') + ->condition('name', 'core.entity_form_display.node.page.default') + ->execute() + ->fetchField(); + +$data = unserialize($data); +$data['dependencies']['config'][] = 'field.field.node.page.field_range'; +$data['dependencies']['module'][] = 'datetime_range'; +$data['content']['field_range'] = array( + "weight"=> 27, + "settings" => array(), + "third_party_settings" => array(), + "type" => "daterange_default", + "region" => "content" +); +$connection->update('config') + ->fields([ + 'data' => serialize($data), + ]) + ->condition('collection', '') + ->condition('name', 'core.entity_form_display.node.page.default') + ->execute(); + +// Update core.entity_view_display.node.page.default +$data = $connection->select('config') + ->fields('config', ['data']) + ->condition('collection', '') + ->condition('name', 'core.entity_view_display.node.page.default') + ->execute() + ->fetchField(); + +$data = unserialize($data); +$data['dependencies']['config'][] = 'field.field.node.page.field_range'; +$data['dependencies']['module'][] = 'datetime_range'; +$data['content']['field_range'] = array( + "weight"=> 102, + "label"=> "above", + "settings" => array("separator"=> "-", "format_type" => "medium", "timezone_override" => ""), + "third_party_settings" => array(), + "type" => "daterange_default", + "region" => "content" +); +$connection->update('config') + ->fields([ + 'data' => serialize($data), + ]) + ->condition('collection', '') + ->condition('name', 'core.entity_view_display.node.page.default') + ->execute(); + +$connection->insert('config') +->fields(array( + 'collection', + 'name', + 'data', +)) +->values(array( + 'collection' => '', + 'name' => 'field.field.node.page.field_range', + 'data' => 'a:16:{s:4:"uuid";s:36:"87dc4221-8d56-4112-8a7f-7a855ac35d08";s:8:"langcode";s:2:"en";s:6:"status";b:1;s:12:"dependencies";a:2:{s:6:"config";a:2:{i:0;s:30:"field.storage.node.field_range";i:1;s:14:"node.type.page";}s:6:"module";a:1:{i:0;s:14:"datetime_range";}}s:2:"id";s:21:"node.page.field_range";s:10:"field_name";s:11:"field_range";s:11:"entity_type";s:4:"node";s:6:"bundle";s:4:"page";s:5:"label";s:5:"range";s:11:"description";s:0:"";s:8:"required";b:0;s:12:"translatable";b:0;s:13:"default_value";a:0:{}s:22:"default_value_callback";s:0:"";s:8:"settings";a:0:{}s:10:"field_type";s:9:"daterange";}', +)) +->values(array( + 'collection' => '', + 'name' => 'field.storage.node.field_range', + 'data' => 'a:16:{s:4:"uuid";s:36:"2190ad8c-39dd-4eb1-b189-1bfc0c244a40";s:8:"langcode";s:2:"en";s:6:"status";b:1;s:12:"dependencies";a:1:{s:6:"module";a:2:{i:0;s:14:"datetime_range";i:1;s:4:"node";}}s:2:"id";s:16:"node.field_range";s:10:"field_name";s:11:"field_range";s:11:"entity_type";s:4:"node";s:4:"type";s:9:"daterange";s:8:"settings";a:1:{s:13:"datetime_type";s:8:"datetime";}s:6:"module";s:14:"datetime_range";s:6:"locked";b:0;s:11:"cardinality";i:1;s:12:"translatable";b:1;s:7:"indexes";a:0:{}s:22:"persist_with_no_fields";b:0;s:14:"custom_storage";b:0;}', +)) +->values(array( + 'collection' => '', + 'name' => 'views.view.test_datetime_range_filter_values', + 'data' => 'a:13:{s:4:"uuid";s:36:"d20760b6-7cc4-4844-ae04-96da7225a46f";s:8:"langcode";s:2:"en";s:6:"status";b:1;s:12:"dependencies";a:1:{s:6:"module";a:2:{i:0;s:4:"node";i:1;s:4:"user";}}s:2:"id";s:33:"test_datetime_range_filter_values";s:5:"label";s:33:"test_datetime_range_filter_values";s:6:"module";s:5:"views";s:11:"description";s:0:"";s:3:"tag";s:0:"";s:10:"base_table";s:15:"node_field_data";s:10:"base_field";s:3:"nid";s:4:"core";s:3:"8.x";s:7:"display";a:1:{s:7:"default";a:6:{s:14:"display_plugin";s:7:"default";s:2:"id";s:7:"default";s:13:"display_title";s:6:"Master";s:8:"position";i:0;s:15:"display_options";a:17:{s:6:"access";a:2:{s:4:"type";s:4:"perm";s:7:"options";a:1:{s:4:"perm";s:14:"access content";}}s:5:"cache";a:2:{s:4:"type";s:3:"tag";s:7:"options";a:0:{}}s:5:"query";a:2:{s:4:"type";s:11:"views_query";s:7:"options";a:5:{s:19:"disable_sql_rewrite";b:0;s:8:"distinct";b:0;s:7:"replica";b:0;s:13:"query_comment";s:0:"";s:10:"query_tags";a:0:{}}}s:12:"exposed_form";a:2:{s:4:"type";s:5:"basic";s:7:"options";a:7:{s:13:"submit_button";s:5:"Apply";s:12:"reset_button";b:0;s:18:"reset_button_label";s:5:"Reset";s:19:"exposed_sorts_label";s:7:"Sort by";s:17:"expose_sort_order";b:1;s:14:"sort_asc_label";s:3:"Asc";s:15:"sort_desc_label";s:4:"Desc";}}s:5:"pager";a:2:{s:4:"type";s:4:"mini";s:7:"options";a:6:{s:14:"items_per_page";i:10;s:6:"offset";i:0;s:2:"id";i:0;s:11:"total_pages";N;s:6:"expose";a:7:{s:14:"items_per_page";b:0;s:20:"items_per_page_label";s:14:"Items per page";s:22:"items_per_page_options";s:13:"5, 10, 25, 50";s:26:"items_per_page_options_all";b:0;s:32:"items_per_page_options_all_label";s:7:"- All -";s:6:"offset";b:0;s:12:"offset_label";s:6:"Offset";}s:4:"tags";a:2:{s:8:"previous";s:6:"‹‹";s:4:"next";s:6:"››";}}}s:5:"style";a:2:{s:4:"type";s:7:"default";s:7:"options";a:4:{s:8:"grouping";a:0:{}s:9:"row_class";s:0:"";s:17:"default_row_class";b:1;s:11:"uses_fields";b:0;}}s:3:"row";a:2:{s:4:"type";s:6:"fields";s:7:"options";a:4:{s:6:"inline";a:0:{}s:9:"separator";s:0:"";s:10:"hide_empty";b:0;s:22:"default_field_elements";b:1;}}s:6:"fields";a:1:{s:5:"title";a:37:{s:2:"id";s:5:"title";s:5:"table";s:15:"node_field_data";s:5:"field";s:5:"title";s:11:"entity_type";s:4:"node";s:12:"entity_field";s:5:"title";s:5:"label";s:0:"";s:5:"alter";a:8:{s:10:"alter_text";b:0;s:9:"make_link";b:0;s:8:"absolute";b:0;s:4:"trim";b:0;s:13:"word_boundary";b:0;s:8:"ellipsis";b:0;s:10:"strip_tags";b:0;s:4:"html";b:0;}s:10:"hide_empty";b:0;s:10:"empty_zero";b:0;s:8:"settings";a:1:{s:14:"link_to_entity";b:1;}s:9:"plugin_id";s:5:"field";s:12:"relationship";s:4:"none";s:10:"group_type";s:5:"group";s:11:"admin_label";s:0:"";s:7:"exclude";b:0;s:12:"element_type";s:0:"";s:13:"element_class";s:0:"";s:18:"element_label_type";s:0:"";s:19:"element_label_class";s:0:"";s:19:"element_label_colon";b:1;s:20:"element_wrapper_type";s:0:"";s:21:"element_wrapper_class";s:0:"";s:23:"element_default_classes";b:1;s:5:"empty";s:0:"";s:16:"hide_alter_empty";b:1;s:17:"click_sort_column";s:5:"value";s:4:"type";s:6:"string";s:12:"group_column";s:5:"value";s:13:"group_columns";a:0:{}s:10:"group_rows";b:1;s:11:"delta_limit";i:0;s:12:"delta_offset";i:0;s:14:"delta_reversed";b:0;s:16:"delta_first_last";b:0;s:10:"multi_type";s:9:"separator";s:9:"separator";s:2:", ";s:17:"field_api_classes";b:0;}}s:7:"filters";a:1:{s:17:"field_range_value";a:14:{s:2:"id";s:17:"field_range_value";s:5:"table";s:17:"node__field_range";s:5:"field";s:17:"field_range_value";s:12:"relationship";s:4:"none";s:10:"group_type";s:5:"group";s:11:"admin_label";s:0:"";s:8:"operator";s:8:"contains";s:5:"value";s:4:"2017";s:5:"group";i:1;s:7:"exposed";b:0;s:6:"expose";a:10:{s:11:"operator_id";s:0:"";s:5:"label";s:0:"";s:11:"description";s:0:"";s:12:"use_operator";b:0;s:8:"operator";s:0:"";s:10:"identifier";s:0:"";s:8:"required";b:0;s:8:"remember";b:0;s:8:"multiple";b:0;s:14:"remember_roles";a:1:{s:13:"authenticated";s:13:"authenticated";}}s:10:"is_grouped";b:0;s:10:"group_info";a:10:{s:5:"label";s:0:"";s:11:"description";s:0:"";s:10:"identifier";s:0:"";s:8:"optional";b:1;s:6:"widget";s:6:"select";s:8:"multiple";b:0;s:8:"remember";b:0;s:13:"default_group";s:3:"All";s:22:"default_group_multiple";a:0:{}s:11:"group_items";a:0:{}}s:9:"plugin_id";s:6:"string";}}s:5:"sorts";a:1:{s:17:"field_range_value";a:10:{s:2:"id";s:17:"field_range_value";s:5:"table";s:17:"node__field_range";s:5:"field";s:17:"field_range_value";s:12:"relationship";s:4:"none";s:10:"group_type";s:5:"group";s:11:"admin_label";s:0:"";s:5:"order";s:3:"ASC";s:7:"exposed";b:0;s:6:"expose";a:1:{s:5:"label";s:0:"";}s:9:"plugin_id";s:8:"standard";}}s:6:"header";a:0:{}s:6:"footer";a:0:{}s:5:"empty";a:0:{}s:13:"relationships";a:0:{}s:9:"arguments";a:0:{}s:17:"display_extenders";a:0:{}s:13:"filter_groups";a:2:{s:8:"operator";s:3:"AND";s:6:"groups";a:0:{}}}s:14:"cache_metadata";a:3:{s:7:"max-age";i:-1;s:8:"contexts";a:5:{i:0;s:26:"languages:language_content";i:1;s:28:"languages:language_interface";i:2;s:14:"url.query_args";i:3;s:21:"user.node_grants:view";i:4;s:16:"user.permissions";}s:4:"tags";a:0:{}}}}}', +)) +->execute(); + +// Update core.extension. +$extensions = $connection->select('config') + ->fields('config', ['data']) + ->condition('collection', '') + ->condition('name', 'core.extension') + ->execute() + ->fetchField(); +$extensions = unserialize($extensions); +$extensions['module']['datetime_range'] = 0; +$connection->update('config') + ->fields([ + 'data' => serialize($extensions), + ]) + ->condition('collection', '') + ->condition('name', 'core.extension') + ->execute(); + +$connection->insert('key_value') +->fields(array( + 'collection', + 'name', + 'value', +)) +->values(array( + 'collection' => 'config.entity.key_store.field_config', + 'name' => 'uuid:87dc4221-8d56-4112-8a7f-7a855ac35d08', + 'value' => 'a:1:{i:0;s:33:"field.field.node.page.field_range";}', +)) +->values(array( + 'collection' => 'config.entity.key_store.field_storage_config', + 'name' => 'uuid:2190ad8c-39dd-4eb1-b189-1bfc0c244a40', + 'value' => 'a:1:{i:0;s:30:"field.storage.node.field_range";}', +)) +->values(array( + 'collection' => 'config.entity.key_store.view', + 'name' => 'uuid:d20760b6-7cc4-4844-ae04-96da7225a46f', + 'value' => 'a:1:{i:0;s:44:"views.view.test_datetime_range_filter_values";}', +)) +->values(array( + 'collection' => 'entity.storage_schema.sql', + 'name' => 'node.field_schema_data.field_range', + 'value' => 'a:2:{s:17:"node__field_range";a:4:{s:11:"description";s:40:"Data storage for node field field_range.";s:6:"fields";a:8:{s:6:"bundle";a:5:{s:4:"type";s:13:"varchar_ascii";s:6:"length";i:128;s:8:"not null";b:1;s:7:"default";s:0:"";s:11:"description";s:88:"The field instance bundle to which this row belongs, used when deleting a field instance";}s:7:"deleted";a:5:{s:4:"type";s:3:"int";s:4:"size";s:4:"tiny";s:8:"not null";b:1;s:7:"default";i:0;s:11:"description";s:60:"A boolean indicating whether this data item has been deleted";}s:9:"entity_id";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:38:"The entity id this data is attached to";}s:11:"revision_id";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:47:"The entity revision id this data is attached to";}s:8:"langcode";a:5:{s:4:"type";s:13:"varchar_ascii";s:6:"length";i:32;s:8:"not null";b:1;s:7:"default";s:0:"";s:11:"description";s:37:"The language code for this data item.";}s:5:"delta";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:67:"The sequence number for this data item, used for multi-value fields";}s:17:"field_range_value";a:4:{s:11:"description";s:21:"The start date value.";s:4:"type";s:7:"varchar";s:6:"length";i:20;s:8:"not null";b:1;}s:21:"field_range_end_value";a:4:{s:11:"description";s:19:"The end date value.";s:4:"type";s:7:"varchar";s:6:"length";i:20;s:8:"not null";b:1;}}s:11:"primary key";a:4:{i:0;s:9:"entity_id";i:1;s:7:"deleted";i:2;s:5:"delta";i:3;s:8:"langcode";}s:7:"indexes";a:4:{s:6:"bundle";a:1:{i:0;s:6:"bundle";}s:11:"revision_id";a:1:{i:0;s:11:"revision_id";}s:17:"field_range_value";a:1:{i:0;s:17:"field_range_value";}s:21:"field_range_end_value";a:1:{i:0;s:21:"field_range_end_value";}}}s:26:"node_revision__field_range";a:4:{s:11:"description";s:52:"Revision archive storage for node field field_range.";s:6:"fields";a:8:{s:6:"bundle";a:5:{s:4:"type";s:13:"varchar_ascii";s:6:"length";i:128;s:8:"not null";b:1;s:7:"default";s:0:"";s:11:"description";s:88:"The field instance bundle to which this row belongs, used when deleting a field instance";}s:7:"deleted";a:5:{s:4:"type";s:3:"int";s:4:"size";s:4:"tiny";s:8:"not null";b:1;s:7:"default";i:0;s:11:"description";s:60:"A boolean indicating whether this data item has been deleted";}s:9:"entity_id";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:38:"The entity id this data is attached to";}s:11:"revision_id";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:47:"The entity revision id this data is attached to";}s:8:"langcode";a:5:{s:4:"type";s:13:"varchar_ascii";s:6:"length";i:32;s:8:"not null";b:1;s:7:"default";s:0:"";s:11:"description";s:37:"The language code for this data item.";}s:5:"delta";a:4:{s:4:"type";s:3:"int";s:8:"unsigned";b:1;s:8:"not null";b:1;s:11:"description";s:67:"The sequence number for this data item, used for multi-value fields";}s:17:"field_range_value";a:4:{s:11:"description";s:21:"The start date value.";s:4:"type";s:7:"varchar";s:6:"length";i:20;s:8:"not null";b:1;}s:21:"field_range_end_value";a:4:{s:11:"description";s:19:"The end date value.";s:4:"type";s:7:"varchar";s:6:"length";i:20;s:8:"not null";b:1;}}s:11:"primary key";a:5:{i:0;s:9:"entity_id";i:1;s:11:"revision_id";i:2;s:7:"deleted";i:3;s:5:"delta";i:4;s:8:"langcode";}s:7:"indexes";a:4:{s:6:"bundle";a:1:{i:0;s:6:"bundle";}s:11:"revision_id";a:1:{i:0;s:11:"revision_id";}s:17:"field_range_value";a:1:{i:0;s:17:"field_range_value";}s:21:"field_range_end_value";a:1:{i:0;s:21:"field_range_end_value";}}}}', +)) +->values(array( + 'collection' => 'system.schema', + 'name' => 'datetime_range', + 'value' => 'i:8000;', +)) +->execute(); + +// Update entity.definitions.bundle_field_map +$value = $connection->select('key_value') + ->fields('key_value', ['value']) + ->condition('collection', 'entity.definitions.bundle_field_map') + ->condition('name', 'node') + ->execute() + ->fetchField(); + +$value = unserialize($value); +$value["field_range"] = array("type" => "daterange", "bundles" => array("page" => "page")); + +$connection->update('key_value') + ->fields([ + 'value' => serialize($value), + ]) + ->condition('collection', 'entity.definitions.bundle_field_map') + ->condition('name', 'node') + ->execute(); + +// Update system.module.files +$files = $connection->select('key_value') + ->fields('key_value', ['value']) + ->condition('collection', 'state') + ->condition('name', 'system.module.files') + ->execute() + ->fetchField(); + +$files = unserialize($files); +$files["datetime_range"] = "core/modules/datetime_range/datetime_range.info.yml"; + +$connection->update('key_value') + ->fields([ + 'value' => serialize($files), + ]) + ->condition('collection', 'state') + ->condition('name', 'system.module.files') + ->execute(); + +$connection->schema()->createTable('node__field_range', array( + 'fields' => array( + 'bundle' => array( + 'type' => 'varchar_ascii', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'langcode' => array( + 'type' => 'varchar_ascii', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_range_value' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '20', + ), + 'field_range_end_value' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '20', + ), + ), + 'primary key' => array( + 'entity_id', + 'deleted', + 'delta', + 'langcode', + ), + 'indexes' => array( + 'bundle' => array( + 'bundle', + ), + 'revision_id' => array( + 'revision_id', + ), + 'field_range_value' => array( + 'field_range_value', + ), + 'field_range_end_value' => array( + 'field_range_end_value', + ), + ), + 'mysql_character_set' => 'utf8mb4', +)); + +$connection->schema()->createTable('node_revision__field_range', array( + 'fields' => array( + 'bundle' => array( + 'type' => 'varchar_ascii', + 'not null' => TRUE, + 'length' => '128', + 'default' => '', + ), + 'deleted' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'tiny', + 'default' => '0', + ), + 'entity_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'revision_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'langcode' => array( + 'type' => 'varchar_ascii', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ), + 'delta' => array( + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'unsigned' => TRUE, + ), + 'field_range_value' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '20', + ), + 'field_range_end_value' => array( + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '20', + ), + ), + 'primary key' => array( + 'entity_id', + 'revision_id', + 'deleted', + 'delta', + 'langcode', + ), + 'indexes' => array( + 'bundle' => array( + 'bundle', + ), + 'revision_id' => array( + 'revision_id', + ), + 'field_range_value' => array( + 'field_range_value', + ), + 'field_range_end_value' => array( + 'field_range_end_value', + ), + ), + 'mysql_character_set' => 'utf8mb4', +)); +