Chris@0: setUpFieldStorages(4); Chris@0: Chris@0: // Attach the field to nodes only. Chris@0: $field = [ Chris@0: 'field_name' => $field_names[0], Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => 'page', Chris@0: 'label' => 'GiraffeA" label' Chris@0: ]; Chris@0: FieldConfig::create($field)->save(); Chris@0: Chris@0: // Attach the same field to a different bundle with a different label. Chris@0: $this->drupalCreateContentType(['type' => 'article']); Chris@0: FieldConfig::create([ Chris@0: 'field_name' => $field_names[0], Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => 'article', Chris@0: 'label' => 'GiraffeB" label' Chris@0: ])->save(); Chris@0: Chris@0: // Now create some example nodes/users for the view result. Chris@0: for ($i = 0; $i < 5; $i++) { Chris@0: $edit = [ Chris@0: $field_names[0] => [(['value' => $this->randomMachineName()])], Chris@0: ]; Chris@0: $nodes[] = $this->drupalCreateNode($edit); Chris@0: } Chris@0: Chris@0: $bundles = []; Chris@0: $bundles[] = $bundle = NodeType::create(['type' => 'bundle1']); Chris@0: $bundle->save(); Chris@0: $bundles[] = $bundle = NodeType::create(['type' => 'bundle2']); Chris@0: $bundle->save(); Chris@0: Chris@0: // Make the first field translatable on all bundles. Chris@0: $field = FieldConfig::create([ Chris@0: 'field_name' => $field_names[1], Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => $bundles[0]->id(), Chris@0: 'translatable' => TRUE, Chris@0: ]); Chris@0: $field->save(); Chris@0: $field = FieldConfig::create([ Chris@0: 'field_name' => $field_names[1], Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => $bundles[1]->id(), Chris@0: 'translatable' => TRUE, Chris@0: ]); Chris@0: $field->save(); Chris@0: Chris@0: // Make the second field not translatable on any bundle. Chris@0: $field = FieldConfig::create([ Chris@0: 'field_name' => $field_names[2], Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => $bundles[0]->id(), Chris@0: 'translatable' => FALSE, Chris@0: ]); Chris@0: $field->save(); Chris@0: $field = FieldConfig::create([ Chris@0: 'field_name' => $field_names[2], Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => $bundles[1]->id(), Chris@0: 'translatable' => FALSE, Chris@0: ]); Chris@0: $field->save(); Chris@0: Chris@0: // Make the last field translatable on some bundles. Chris@0: $field = FieldConfig::create([ Chris@0: 'field_name' => $field_names[3], Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => $bundles[0]->id(), Chris@0: 'translatable' => TRUE, Chris@0: ]); Chris@0: $field->save(); Chris@0: $field = FieldConfig::create([ Chris@0: 'field_name' => $field_names[3], Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => $bundles[1]->id(), Chris@0: 'translatable' => FALSE, Chris@0: ]); Chris@0: $field->save(); Chris@0: Chris@0: // Create some example content. Chris@0: ConfigurableLanguage::create([ Chris@0: 'id' => 'es', Chris@0: ])->save(); Chris@0: ConfigurableLanguage::create([ Chris@0: 'id' => 'fr', Chris@0: ])->save(); Chris@0: Chris@0: $config = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundles[0]->id()); Chris@0: $config->setDefaultLangcode('es') Chris@0: ->setLanguageAlterable(TRUE) Chris@0: ->save(); Chris@0: $config = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundles[1]->id()); Chris@0: $config->setDefaultLangcode('es') Chris@0: ->setLanguageAlterable(TRUE) Chris@0: ->save(); Chris@0: Chris@0: $node = Node::create([ Chris@0: 'title' => 'Test title ' . $bundles[0]->id(), Chris@0: 'type' => $bundles[0]->id(), Chris@0: 'langcode' => 'es', Chris@0: $field_names[1] => 'field name 1: es', Chris@0: $field_names[2] => 'field name 2: es', Chris@0: $field_names[3] => 'field name 3: es', Chris@0: ]); Chris@0: $node->save(); Chris@0: $this->translationNodes[] = $node; Chris@0: $translation = $node->addTranslation('fr'); Chris@0: $translation->{$field_names[1]}->value = 'field name 1: fr'; Chris@0: $translation->{$field_names[3]}->value = 'field name 3: fr'; Chris@0: $translation->title->value = $node->title->value; Chris@0: $translation->save(); Chris@0: Chris@0: $node = Node::create([ Chris@0: 'title' => 'Test title ' . $bundles[1]->id(), Chris@0: 'type' => $bundles[1]->id(), Chris@0: 'langcode' => 'es', Chris@0: $field_names[1] => 'field name 1: es', Chris@0: $field_names[2] => 'field name 2: es', Chris@0: $field_names[3] => 'field name 3: es', Chris@0: ]); Chris@0: $node->save(); Chris@0: $this->translationNodes[] = $node; Chris@0: $translation = $node->addTranslation('fr'); Chris@0: $translation->{$field_names[1]}->value = 'field name 1: fr'; Chris@0: $translation->title->value = $node->title->value; Chris@0: $translation->save(); Chris@0: Chris@0: } Chris@0: Chris@0: /** Chris@0: * Unit testing the views data structure. Chris@0: * Chris@0: * We check data structure for both node and node revision tables. Chris@0: */ Chris@0: public function testViewsData() { Chris@0: $table_mapping = \Drupal::entityManager()->getStorage('node')->getTableMapping(); Chris@0: $field_storage = $this->fieldStorages[0]; Chris@0: $current_table = $table_mapping->getDedicatedDataTableName($field_storage); Chris@0: $revision_table = $table_mapping->getDedicatedRevisionTableName($field_storage); Chris@0: $data = $this->getViewsData(); Chris@0: Chris@0: $this->assertTrue(isset($data[$current_table])); Chris@0: $this->assertTrue(isset($data[$revision_table])); Chris@0: // The node field should join against node_field_data. Chris@0: $this->assertTrue(isset($data[$current_table]['table']['join']['node_field_data'])); Chris@0: $this->assertTrue(isset($data[$revision_table]['table']['join']['node_field_revision'])); Chris@0: Chris@0: $expected_join = [ Chris@0: 'table' => $current_table, Chris@0: 'left_field' => 'nid', Chris@0: 'field' => 'entity_id', Chris@0: 'extra' => [ Chris@0: ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE], Chris@0: ['left_field' => 'langcode', 'field' => 'langcode'], Chris@0: ], Chris@0: ]; Chris@0: $this->assertEqual($expected_join, $data[$current_table]['table']['join']['node_field_data']); Chris@0: $expected_join = [ Chris@0: 'table' => $revision_table, Chris@0: 'left_field' => 'vid', Chris@0: 'field' => 'revision_id', Chris@0: 'extra' => [ Chris@0: ['field' => 'deleted', 'value' => 0, 'numeric' => TRUE], Chris@0: ['left_field' => 'langcode', 'field' => 'langcode'], Chris@0: ], Chris@0: ]; Chris@0: $this->assertEqual($expected_join, $data[$revision_table]['table']['join']['node_field_revision']); Chris@0: Chris@0: // Test click sortable. Chris@0: $this->assertTrue($data[$current_table][$field_storage->getName()]['field']['click sortable'], 'String field is click sortable.'); Chris@0: // Click sort should only be on the primary field. Chris@0: $this->assertTrue(empty($data[$revision_table][$field_storage->getName()]['field']['click sortable']), 'Non-primary fields are not click sortable'); Chris@0: Chris@0: $this->assertTrue($data[$current_table][$field_storage->getName()]['help'] instanceof MarkupInterface); Chris@0: $this->assertEqual($data[$current_table][$field_storage->getName()]['help'], 'Appears in: page, article. Also known as: Content: GiraffeB" label'); Chris@0: Chris@0: $this->assertTrue($data[$current_table][$field_storage->getName() . '_value']['help'] instanceof MarkupInterface); Chris@0: $this->assertEqual($data[$current_table][$field_storage->getName() . '_value']['help'], 'Appears in: page, article. Also known as: Content: GiraffeA" label (field_name_0)'); Chris@0: Chris@0: // Since each label is only used once, views_entity_field_label() will Chris@0: // return a label using alphabetical sorting. Chris@0: $this->assertEqual('GiraffeA" label (field_name_0)', $data[$current_table][$field_storage->getName() . '_value']['title']); Chris@0: Chris@0: // Attach the same field to a different bundle with a different label. Chris@0: $this->drupalCreateContentType(['type' => 'news']); Chris@0: FieldConfig::create([ Chris@0: 'field_name' => $this->fieldStorages[0]->getName(), Chris@0: 'entity_type' => 'node', Chris@0: 'bundle' => 'news', Chris@0: 'label' => 'GiraffeB" label' Chris@0: ])->save(); Chris@0: $this->container->get('views.views_data')->clear(); Chris@0: $data = $this->getViewsData(); Chris@0: Chris@0: // Now the 'GiraffeB" label' is used twice and therefore will be Chris@0: // selected by views_entity_field_label(). Chris@0: $this->assertEqual('GiraffeB" label (field_name_0)', $data[$current_table][$field_storage->getName() . '_value']['title']); Chris@0: $this->assertTrue($data[$current_table][$field_storage->getName()]['help'] instanceof MarkupInterface); Chris@0: $this->assertEqual($data[$current_table][$field_storage->getName()]['help'], 'Appears in: page, article, news. Also known as: Content: GiraffeA" label'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the views data for the field created in setUp(). Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: protected function getViewsData() { Chris@0: $views_data = $this->container->get('views.views_data'); Chris@0: $data = []; Chris@0: Chris@0: // Check the table and the joins of the first field. Chris@0: // Attached to node only. Chris@0: /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */ Chris@0: $table_mapping = \Drupal::entityManager()->getStorage('node')->getTableMapping(); Chris@0: $current_table = $table_mapping->getDedicatedDataTableName($this->fieldStorages[0]); Chris@0: $revision_table = $table_mapping->getDedicatedRevisionTableName($this->fieldStorages[0]); Chris@0: $data[$current_table] = $views_data->get($current_table); Chris@0: $data[$revision_table] = $views_data->get($revision_table); Chris@0: return $data; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests filtering entries with different translatabilty. Chris@0: */ Chris@0: public function testEntityFieldFilter() { Chris@0: $map = [ Chris@0: 'nid' => 'nid', Chris@0: 'langcode' => 'langcode', Chris@0: ]; Chris@0: Chris@0: $view = Views::getView('test_field_config_translation_filter'); Chris@0: Chris@0: // Filter by 'field name 1: es'. Chris@0: $view->setDisplay('embed_1'); Chris@0: $this->executeView($view); Chris@0: $expected = [ Chris@0: [ Chris@0: 'nid' => $this->translationNodes[0]->id(), Chris@0: 'langcode' => 'es', Chris@0: ], Chris@0: [ Chris@0: 'nid' => $this->translationNodes[1]->id(), Chris@0: 'langcode' => 'es', Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $this->assertIdenticalResultset($view, $expected, $map); Chris@0: $view->destroy(); Chris@0: Chris@0: // Filter by 'field name 1: fr'. Chris@0: $view->setDisplay('embed_2'); Chris@0: $this->executeView($view); Chris@0: $expected = [ Chris@0: [ Chris@0: 'nid' => $this->translationNodes[0]->id(), Chris@0: 'langcode' => 'fr', Chris@0: ], Chris@0: [ Chris@0: 'nid' => $this->translationNodes[1]->id(), Chris@0: 'langcode' => 'fr', Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $this->assertIdenticalResultset($view, $expected, $map); Chris@0: $view->destroy(); Chris@0: Chris@0: // Filter by 'field name 2: es'. Chris@0: $view->setDisplay('embed_3'); Chris@0: $this->executeView($view); Chris@0: $expected = [ Chris@0: [ Chris@0: 'nid' => $this->translationNodes[0]->id(), Chris@0: 'langcode' => 'es', Chris@0: ], Chris@0: [ Chris@0: 'nid' => $this->translationNodes[0]->id(), Chris@0: 'langcode' => 'fr', Chris@0: ], Chris@0: [ Chris@0: 'nid' => $this->translationNodes[1]->id(), Chris@0: 'langcode' => 'es', Chris@0: ], Chris@0: [ Chris@0: 'nid' => $this->translationNodes[1]->id(), Chris@0: 'langcode' => 'fr', Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $this->assertIdenticalResultset($view, $expected, $map); Chris@0: $view->destroy(); Chris@0: Chris@0: // Filter by 'field name 2: fr', which doesn't exist. Chris@0: $view->setDisplay('embed_4'); Chris@0: $this->executeView($view); Chris@0: $expected = []; Chris@0: Chris@0: $this->assertIdenticalResultset($view, $expected, $map); Chris@0: $view->destroy(); Chris@0: Chris@0: // Filter by 'field name 3: es'. Chris@0: $view->setDisplay('embed_5'); Chris@0: $this->executeView($view); Chris@0: $expected = [ Chris@0: [ Chris@0: 'nid' => $this->translationNodes[0]->id(), Chris@0: 'langcode' => 'es', Chris@0: ], Chris@0: [ Chris@0: 'nid' => $this->translationNodes[1]->id(), Chris@0: 'langcode' => 'es', Chris@0: ], Chris@0: // Why is this one returned? Chris@0: [ Chris@0: 'nid' => $this->translationNodes[1]->id(), Chris@0: 'langcode' => 'fr', Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $this->assertIdenticalResultset($view, $expected, $map); Chris@0: $view->destroy(); Chris@0: Chris@0: // Filter by 'field name 3: fr'. Chris@0: $view->setDisplay('embed_6'); Chris@0: $this->executeView($view); Chris@0: $expected = [ Chris@0: [ Chris@0: 'nid' => $this->translationNodes[0]->id(), Chris@0: 'langcode' => 'fr', Chris@0: ], Chris@0: ]; Chris@0: Chris@0: $this->assertIdenticalResultset($view, $expected, $map); Chris@0: $view->destroy(); Chris@0: } Chris@0: Chris@0: }