diff --git a/core/modules/datetime/datetime.views.inc b/core/modules/datetime/datetime.views.inc new file mode 100644 index 0000000..84ade9b --- /dev/null +++ b/core/modules/datetime/datetime.views.inc @@ -0,0 +1,38 @@ + $table_data) { + // Set the 'datetime' filter type. + $data[$table_name][$field_storage->getName() . '_value']['filter']['id'] = 'datetime'; + + // Set the 'datetime' argument type. + $data[$table_name][$field_storage->getName() . '_value']['argument']['id'] = 'datetime'; + + // Create year, month, and day arguments. + $group = $data[$table_name][$field_storage->getName() . '_value']['group']; + foreach (array('year', 'month', 'day') as $argument_type) { + $data[$table_name][$field_storage->getName() . '_value_' . $argument_type] = array( + 'title' => $field_storage->getLabel() . ' (' . $argument_type . ')', + 'help' => t('Date in the form of YYYY.'), + 'argument' => array( + 'field' => $field_storage->getName() . '_value', + 'id' => 'datetime_' . $argument_type, + ), + 'group' => $group, + ); + } + } + + return $data; +} diff --git a/core/modules/datetime/src/Plugin/views/argument/Date.php b/core/modules/datetime/src/Plugin/views/argument/Date.php new file mode 100644 index 0000000..c59930a --- /dev/null +++ b/core/modules/datetime/src/Plugin/views/argument/Date.php @@ -0,0 +1,36 @@ +tableAlias.$this->realField"; + } +} diff --git a/core/modules/datetime/src/Plugin/views/argument/DayDate.php b/core/modules/datetime/src/Plugin/views/argument/DayDate.php new file mode 100644 index 0000000..17d5cbd --- /dev/null +++ b/core/modules/datetime/src/Plugin/views/argument/DayDate.php @@ -0,0 +1,22 @@ +value['min'], 0)); + $b = intval(strtotime($this->value['max'], 0)); + + if ($this->value['type'] == 'offset') { + $a = REQUEST_TIME + $a; + $b = REQUEST_TIME + $b; + } + // Convert to ISO format. + $a = format_date($a, 'custom', 'c'); + $b = format_date($b, 'custom', 'c'); + + // This is safe because we are manually scrubbing the values. + // It is necessary to do it this way because $a and $b are formulas when using an offset. + $operator = strtoupper($this->operator); + $this->query->addWhereExpression($this->options['group'], "$field $operator '$a' AND '$b'"); + } + + /** + * Override parent method, which deals with dates as integers. + */ + protected function opSimple($field) { + $value = intval(strtotime($this->value['value'], 0)); + if (!empty($this->value['type']) && $this->value['type'] == 'offset') { + $value = REQUEST_TIME + $value; + } + // Convert to ISO. + $value = format_date($value, 'custom', 'c'); + // This is safe because we are manually scrubbing the value. + // It is necessary to do it this way because $value is a formula when using an offset. + $this->query->addWhereExpression($this->options['group'], "$field $this->operator '$value'"); + + } +} diff --git a/core/modules/datetime/src/Tests/Views/ArgumentDateTimeTest.php b/core/modules/datetime/src/Tests/Views/ArgumentDateTimeTest.php new file mode 100644 index 0000000..10202ec --- /dev/null +++ b/core/modules/datetime/src/Tests/Views/ArgumentDateTimeTest.php @@ -0,0 +1,142 @@ +nodes[] = $this->drupalCreateNode(array( + 'field_date' => array( + 'value' => $date, + ) + )); + } + } + + /** + * Test year argument. + * + * @see \Drupal\datetime\Plugin\views\argument\YearDate + */ + public function testDatetimeArgumentYear() { + $view = Views::getView('test_argument_datetime'); + + // The 'default' display has the 'year' argument. + $view->setDisplay('default'); + $this->executeView($view, array('2000')); + $expected = array(); + $expected[] = array('nid' => $this->nodes[0]->id()); + $this->assertIdenticalResultset($view, $expected, $this->map); + $view->destroy(); + + $view->setDisplay('default'); + $this->executeView($view, array('2002')); + $expected = array(); + $expected[] = array('nid' => $this->nodes[2]->id()); + $this->assertIdenticalResultset($view, $expected, $this->map); + $view->destroy(); + } + + /** + * Test month argument. + * + * @see \Drupal\datetime\Plugin\views\argument\MonthDate + */ + public function testDatetimeArgumentMonth() { + $view = Views::getView('test_argument_datetime'); + // The 'embed_1' display has the 'month' argument. + $view->setDisplay('embed_1'); + + $this->executeView($view, array('10')); + $expected = array(); + $expected[] = array('nid' => $this->nodes[0]->id()); + $expected[] = array('nid' => $this->nodes[1]->id()); + $this->assertIdenticalResultset($view, $expected, $this->map); + $view->destroy(); + + $view->setDisplay('embed_1'); + $this->executeView($view, array('01')); + $expected = array(); + $expected[] = array('nid' => $this->nodes[2]->id()); + $this->assertIdenticalResultset($view, $expected, $this->map); + $view->destroy(); + } + + /** + * Test day argument. + * + * @see \Drupal\datetime\Plugin\views\argument\DayDate + */ + public function testDatetimeArgumentDay() { + $view = Views::getView('test_argument_datetime'); + // The 'embed_2' display has the 'day' argument. + $view->setDisplay('embed_2'); + + $this->executeView($view, array('10')); + $expected = array(); + $expected[] = array('nid' => $this->nodes[0]->id()); + $expected[] = array('nid' => $this->nodes[1]->id()); + $this->assertIdenticalResultset($view, $expected, $this->map); + $view->destroy(); + + $view->setDisplay('embed_2'); + $this->executeView($view, array('01')); + $expected = array(); + $expected[] = array('nid' => $this->nodes[2]->id()); + $this->assertIdenticalResultset($view, $expected, $this->map); + $view->destroy(); + } + + /** + * Test year, month, and day arguments combined. + */ + public function testDatetimeArgumentAll() { + $view = Views::getView('test_argument_datetime'); + // The 'embed_3' display has year, month, and day arguments. + $view->setDisplay('embed_3'); + + $this->executeView($view, array('2000', '10', '10')); + $expected = array(); + $expected[] = array('nid' => $this->nodes[0]->id()); + $this->assertIdenticalResultset($view, $expected, $this->map); + $view->destroy(); + + $view->setDisplay('embed_3'); + $this->executeView($view, array('2002', '01', '01')); + $expected = array(); + $expected[] = array('nid' => $this->nodes[2]->id()); + $this->assertIdenticalResultset($view, $expected, $this->map); + $view->destroy(); + } + +} diff --git a/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php b/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php new file mode 100644 index 0000000..4f4791d --- /dev/null +++ b/core/modules/datetime/src/Tests/Views/DateTimeHandlerTestBase.php @@ -0,0 +1,79 @@ + 'page', + 'name' => 'page' + )); + $node_type->save(); + $fieldStorage = entity_create('field_storage_config', array( + 'field_name' => static::$field_name, + 'entity_type' => 'node', + 'type' => 'datetime', + 'settings' => array('datetime_type' => 'date'), + )); + $fieldStorage->save(); + $field = entity_create('field_config', array( + 'field_storage' => $fieldStorage, + 'bundle' => 'page', + 'required' => TRUE, + )); + $field->save(); + + // Views needs to be aware of the new field. + $this->container->get('views.views_data')->clear(); + + // Set column map. + $this->map = array( + 'nid' => 'nid', + ); + } + +} diff --git a/core/modules/datetime/src/Tests/Views/FilterDateTimeTest.php b/core/modules/datetime/src/Tests/Views/FilterDateTimeTest.php new file mode 100644 index 0000000..1394b24 --- /dev/null +++ b/core/modules/datetime/src/Tests/Views/FilterDateTimeTest.php @@ -0,0 +1,145 @@ +nodes[] = $this->drupalCreateNode(array( + 'field_date' => array( + 'value' => $date, + ) + )); + } + } + + /** + * Test filter operations. + */ + public function testDatetimeFilter() { + $this->_testOffset(); + $this->_testBetween(); + } + + /** + * Test offset operations. + */ + protected function _testOffset() { + $view = Views::getView('test_filter_datetime'); + $field = static::$field_name . '_value'; + + // Test simple operations. + $view->initHandlers(); + + $view->filter[$field]->operator = '>'; + $view->filter[$field]->value['type'] = 'offset'; + $view->filter[$field]->value['value'] = '+1 hour'; + $view->executeDisplay('default'); + $expected_result = array( + array('nid' => $this->nodes[3]->id()), + ); + $this->assertIdenticalResultset($view, $expected_result, $this->map); + $view->destroy(); + + // Test offset for between operator. + $view->initHandlers(); + $view->filter[$field]->operator = 'between'; + $view->filter[$field]->value['type'] = 'offset'; + $view->filter[$field]->value['max'] = '+2 days'; + $view->filter[$field]->value['min'] = '+1 hour'; + $view->executeDisplay('default'); + $expected_result = array( + array('nid' => $this->nodes[3]->id()), + ); + $this->assertIdenticalResultset($view, $expected_result, $this->map); + } + + /** + * Test between operations. + */ + protected function _testBetween() { + $view = Views::getView('test_filter_datetime'); + $field = static::$field_name . '_value'; + + // Test between with min and max. + $view->initHandlers(); + $view->filter[$field]->operator = 'between'; + $view->filter[$field]->value['min'] = '2001-01-01'; + $view->filter[$field]->value['max'] = '2002-01-01'; + $view->executeDisplay('default'); + $expected_result = array( + array('nid' => $this->nodes[1]->id()), + ); + $this->assertIdenticalResultset($view, $expected_result, $this->map); + $view->destroy(); + + // Test between with just max. + $view->initHandlers(); + $view->filter[$field]->operator = 'between'; + $view->filter[$field]->value['max'] = '2002-01-01'; + $view->executeDisplay('default'); + $expected_result = array( + array('nid' => $this->nodes[0]->id()), + array('nid' => $this->nodes[1]->id()), + ); + $this->assertIdenticalResultset($view, $expected_result, $this->map); + $view->destroy(); + + // Test not between with min and max. + $view->initHandlers(); + $view->filter[$field]->operator = 'not between'; + $view->filter[$field]->value['min'] = '2001-01-01'; + $view->filter[$field]->value['max'] = '2002-01-01'; + $view->executeDisplay('default'); + $expected_result = array( + array('nid' => $this->nodes[0]->id()), + array('nid' => $this->nodes[2]->id()), + array('nid' => $this->nodes[3]->id()), + ); + $this->assertIdenticalResultset($view, $expected_result, $this->map); + $view->destroy(); + + // Test not between with just max. + $view->initHandlers(); + $view->filter[$field]->operator = 'not between'; + $view->filter[$field]->value['max'] = '2001-01-01'; + $view->executeDisplay('default'); + $expected_result = array( + array('nid' => $this->nodes[1]->id()), + array('nid' => $this->nodes[2]->id()), + array('nid' => $this->nodes[3]->id()), + ); + $this->assertIdenticalResultset($view, $expected_result, $this->map); + } + +} diff --git a/core/modules/datetime/tests/modules/datetime_test/datetime_test.info.yml b/core/modules/datetime/tests/modules/datetime_test/datetime_test.info.yml new file mode 100644 index 0000000..84ba9e4 --- /dev/null +++ b/core/modules/datetime/tests/modules/datetime_test/datetime_test.info.yml @@ -0,0 +1,8 @@ +name: 'Datetime test' +type: module +description: 'Provides default views for tests.' +package: Testing +version: VERSION +core: 8.x +dependencies: + - views diff --git a/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_argument_datetime.yml b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_argument_datetime.yml new file mode 100644 index 0000000..d2c4316 --- /dev/null +++ b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_argument_datetime.yml @@ -0,0 +1,105 @@ +langcode: und +status: true +dependencies: { } +id: test_argument_datetime +label: '' +module: views +description: '' +tag: '' +base_table: node +base_field: nid +core: '8' +display: + default: + display_options: + defaults: + fields: false + pager: false + sorts: false + arguments: + field_date_value_year: + field: field_date_value_year + id: field_date_value + table: node__field_date + plugin_id: datetime_year + fields: + id: + field: nid + id: nid + relationship: none + table: node + plugin_id: numeric + pager: + options: + offset: 0 + type: none + sorts: + id: + field: nid + id: nid + order: ASC + relationship: none + table: node + plugin_id: numeric + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_plugin: default + display_title: Master + id: default + position: 0 + embed_1: + display_options: + defaults: + arguments: false + arguments: + field_date_value_month: + field: field_date_value_month + id: field_date_value + table: node__field_date + plugin_id: datetime_month + display_plugin: embed + id: embed_1 + display_title: '' + position: null + embed_2: + display_options: + defaults: + arguments: false + arguments: + field_date_value_day: + field: field_date_value_day + id: field_date_value + table: node__field_date + plugin_id: datetime_day + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_plugin: embed + id: embed_2 + display_title: '' + position: null + embed_3: + display_options: + defaults: + arguments: false + arguments: + field_date_value_year: + field: field_date_value_year + id: field_date_value + table: node__field_date + plugin_id: datetime_year + field_date_value_month: + field: field_date_value_month + id: field_date_value + table: node__field_date + plugin_id: datetime_month + field_date_value_day: + field: field_date_value_day + id: field_date_value + table: node__field_date + plugin_id: datetime_day + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_plugin: embed + id: embed_2 + display_title: '' + position: null diff --git a/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_filter_datetime.yml b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_filter_datetime.yml new file mode 100644 index 0000000..f1210d0 --- /dev/null +++ b/core/modules/datetime/tests/modules/datetime_test/test_views/views.view.test_filter_datetime.yml @@ -0,0 +1,50 @@ +langcode: und +status: true +dependencies: + module: + - node +id: test_filter_datetime +label: '' +module: views +description: '' +tag: '' +base_table: node +base_field: nid +core: '8' +display: + default: + display_options: + access: + type: none + cache: + type: none + exposed_form: + type: basic + fields: + nid: + field: nid + id: nid + table: node + plugin_id: node + filters: + field_date_value: + id: field_date_value + table: node__field_date + field: field_date_value + plugin_id: datetime + pager: + type: full + query: + options: + query_comment: false + type: views_query + style: + type: default + row: + type: fields + field_langcode: '***LANGUAGE_language_content***' + field_langcode_add_to_query: null + display_plugin: default + display_title: Master + id: default + position: 0