diff --git a/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php b/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php index 5dc096f651c01d73d8590a5cb78d8b86a0afe164..d18d9f30bce3a35a33da5f8e48cfdea41d0329b7 100644 --- a/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php +++ b/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\field\Kernel\EntityReference\Views; use Drupal\entity_test\Entity\EntityTestMulChanged; +use Drupal\field\Entity\FieldStorageConfig; use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait; use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTestMul; @@ -32,6 +33,7 @@ class EntityReferenceRelationshipTest extends ViewsKernelTestBase { 'test_entity_reference_reverse_entity_test_view', 'test_entity_reference_entity_test_mul_view', 'test_entity_reference_reverse_entity_test_mul_view', + 'test_entity_reference_group_by_empty_relationships', ); /** @@ -71,6 +73,9 @@ protected function setUp($import_test_views = TRUE) { // @see \Drupal\Core\Entity\Sql\DefaultTableMapping::generateFieldTableName() $this->createEntityReferenceField('entity_test_mul_changed', 'entity_test_mul_changed', 'field_test_data_with_a_long_name', 'field_test_data_with_a_long_name', 'entity_test'); + // Create reference from entity_test_mul to entity_test cardinality: infinite. + $this->createEntityReferenceField('entity_test_mul', 'entity_test_mul', 'field_data_test_unlimited', 'field_data_test_unlimited', 'entity_test', 'default', array(), FieldStorageConfig::CARDINALITY_UNLIMITED); + ViewTestData::createTestViews(get_class($this), array('entity_reference_test_views')); } @@ -276,4 +281,56 @@ public function testDataTableRelationshipWithLongFieldName() { } } + /** + * Tests group by with optional and empty relationship. + */ + public function testGroupByWithEmptyRelationships() { + $entities = []; + // Create 4 entities with name1 and 3 entities with name2. + for ($i = 1; $i <= 4; $i++) { + $entity = [ + 'name' => 'name' . $i, + ]; + $entity = EntityTest::create($entity); + $entities[] = $entity; + $entity->save(); + } + + $entity = EntityTestMul::create([ + 'name' => 'name1', + ]); + $entity->field_data_test_unlimited = [ + ['target_id' => $entities[0]->id()], + ['target_id' => $entities[1]->id()], + ['target_id' => $entities[2]->id()], + ]; + $entity->save(); + + $entity = EntityTestMul::create([ + 'name' => 'name2', + ]); + $entity->field_data_test_unlimited = [ + ['target_id' => $entities[0]->id()], + ['target_id' => $entities[1]->id()], + ]; + $entity->save(); + + $entity = EntityTestMul::create([ + 'name' => 'name3', + ]); + $entity->field_data_test_unlimited->target_id = $entities[0]->id(); + $entity->save(); + + $view = Views::getView('test_entity_reference_group_by_empty_relationships'); + $this->executeView($view); + $this->assertCount(4, $view->result); + // First three results should contain a reference from EntityTestMul. + $this->assertNotEmpty($view->getStyle()->getField(0, 'name_2')); + $this->assertNotEmpty($view->getStyle()->getField(1, 'name_2')); + $this->assertNotEmpty($view->getStyle()->getField(2, 'name_2')); + // Fourth result has no reference from EntityTestMul hence the output for + // should be empty. + $this->assertEqual('', $view->getStyle()->getField(3, 'name_2')); + } + } diff --git a/core/modules/system/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_group_by_empty_relationships.yml b/core/modules/system/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_group_by_empty_relationships.yml new file mode 100644 index 0000000000000000000000000000000000000000..5c9352412a86e9a29401932e67fb4ef7c25c018c --- /dev/null +++ b/core/modules/system/tests/modules/entity_reference_test_views/test_views/views.view.test_entity_reference_group_by_empty_relationships.yml @@ -0,0 +1,128 @@ +langcode: en +status: true +dependencies: { } +id: test_entity_reference_group_by_empty_relationships +label: '' +module: views +description: '' +tag: '' +base_table: entity_test +base_field: id +core: '8' +display: + default: + display_options: + access: + type: none + cache: + type: tag + exposed_form: + type: basic + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + fields: + name_1: + id: name_1 + table: entity_test + field: name + entity_type: entity_test + entity_field: name + plugin_id: field + relationship: none + group_type: group + group_column: value + group_columns: { } + group_rows: true + exclude: false + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + name_2: + id: name_2 + table: entity_test_mul_property_data + field: name + entity_type: entity_test_mul + entity_field: name + plugin_id: field + relationship: reverse__entity_test_mul__field_data_test_unlimited + group_type: group + group_column: entity_id + group_columns: { } + group_rows: false + exclude: false + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + sorts: + name: + table: entity_test + field: name + id: name + entity_type: entity_test + entity_field: field_test + order: ASC + plugin_id: standard + pager: + type: some + style: + type: table + options: + grouping: { } + row_class: '' + default_row_class: true + override: true + sticky: false + caption: '' + summary: '' + description: '' + columns: + name_1: name_1 + name_2: name_2 + info: + name_1: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + name_2: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + default: '-1' + empty_table: false + row: + type: fields + options: + inline: { } + separator: '' + hide_empty: false + default_field_elements: true + relationships: + reverse__entity_test_mul__field_data_test_unlimited: + id: reverse__entity_test_mul__field_data_test_unlimited + table: entity_test + field: reverse__entity_test_mul__field_data_test_unlimited + entity_type: entity_test + plugin_id: entity_reverse + group_type: group + required: false + group_by: true + display_plugin: block + display_title: Master + id: default + position: 0 diff --git a/core/modules/views/src/Plugin/views/field/EntityField.php b/core/modules/views/src/Plugin/views/field/EntityField.php index 4c8032d3eb5f2415a3c4b0f0529089e9d48be118..dfabda3a3f93be764602285fcf730a7bedd3186f 100644 --- a/core/modules/views/src/Plugin/views/field/EntityField.php +++ b/core/modules/views/src/Plugin/views/field/EntityField.php @@ -818,10 +818,17 @@ public function getItems(ResultRow $values) { 'settings' => $this->options['settings'], 'label' => 'hidden', ]; - // Some bundles might not have a specific field, in which case the faked - // entity doesn't have it either. - $entity = $this->createEntityForGroupBy($this->getEntity($values), $values); - $build_list = isset($entity->{$this->definition['field_name']}) ? $entity->{$this->definition['field_name']}->view($display) : NULL; + // Optional relationships may not provide an entity at all. So we can't + // use createEntityForGroupBy() for those rows. + if ($entity = $this->getEntity($values)) { + $entity = $this->createEntityForGroupBy($entity, $values); + // Some bundles might not have a specific field, in which case the faked + // entity doesn't have it either. + $build_list = isset($entity->{$this->definition['field_name']}) ? $entity->{$this->definition['field_name']}->view($display) : NULL; + } + else { + $build_list = NULL; + } } if (!$build_list) {