diff --git a/core/modules/views/src/Plugin/views/field/Field.php b/core/modules/views/src/Plugin/views/field/Field.php index 251d025..59f18af 100644 --- a/core/modules/views/src/Plugin/views/field/Field.php +++ b/core/modules/views/src/Plugin/views/field/Field.php @@ -976,8 +976,12 @@ protected function getTableMapping() { * {@inheritdoc} */ public function getValue(ResultRow $values, $field = NULL) { + // Retrieve the correct translation object. + $entity = $this->getEntity($values); + $processed_entity = clone $this->getEntityFieldRenderer()->getEntityTranslation($entity, $values); + /** @var \Drupal\Core\Field\FieldItemListInterface $field_item_list */ - $field_item_list = $this->getEntity($values)->{$this->definition['field_name']}; + $field_item_list = $processed_entity->{$this->definition['field_name']}; $field_item_definition = $field_item_list->getFieldDefinition(); if ($field_item_definition->getFieldStorageDefinition()->getCardinality() == 1) { diff --git a/core/modules/views/src/Plugin/views/join/FieldOrLanguageJoin.php b/core/modules/views/src/Plugin/views/join/FieldOrLanguageJoin.php new file mode 100644 index 0000000..f679b52 --- /dev/null +++ b/core/modules/views/src/Plugin/views/join/FieldOrLanguageJoin.php @@ -0,0 +1,59 @@ +extra)) { + $extras = array(); + foreach ($this->extra as $extra) { + $extras[] = $this->buildExtra($extra, $arguments, $table, $select_query, $left_table); + } + + if ($extras) { + + // Remove and store the langcode OR bundle join condition extra. + $language_bundle_conditions = []; + foreach ($extras as $key => &$extra) { + if (strpos($extra, '.langcode') !== FALSE || strpos($extra, '.bundle') !== FALSE ) { + $language_bundle_conditions[] = $extra; + unset($extras[$key]); + } + } + + if (count($extras) == 1) { + $condition .= ' AND ' . array_shift($extras); + } + else { + $condition .= ' AND (' . implode(' ' . $this->extraOperator . ' ', $extras) . ')'; + } + + // Tack on the langcode OR bundle join condition extra. + if (!empty($language_bundle_conditions)) { + $condition .= ' AND (' . implode(' OR ', $language_bundle_conditions) . ')'; + } + } + } + elseif ($this->extra && is_string($this->extra)) { + $condition .= " AND ($this->extra)"; + } + } +} diff --git a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php index 45418c9..fdcc37f 100644 --- a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php +++ b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php @@ -7,6 +7,7 @@ namespace Drupal\views\Plugin\views\join; +use Drupal\Core\Database\Query\SelectInterface; use Drupal\Core\Plugin\PluginBase; /** @@ -254,12 +255,13 @@ public function buildJoin($select_query, $table, $view_query) { } if ($this->leftTable) { - $left = $view_query->getTableInfo($this->leftTable); - $left_field = "$left[alias].$this->leftField"; + $left_table = $view_query->getTableInfo($this->leftTable); + $left_field = "$left_table[alias].$this->leftField"; } else { // This can be used if left_field is a formula or something. It should be used only *very* rarely. $left_field = $this->leftField; + $left_table = NULL; } $condition = "$left_field = $table[alias].$this->field"; @@ -267,90 +269,149 @@ public function buildJoin($select_query, $table, $view_query) { // Tack on the extra. if (isset($this->extra)) { - if (is_array($this->extra)) { - $extras = array(); - foreach ($this->extra as $info) { - // Do not require 'value' to be set; allow for field syntax instead. - $info += array( - 'value' => NULL, - ); - // Figure out the table name. Remember, only use aliases provided - // if at all possible. - $join_table = ''; - if (!array_key_exists('table', $info)) { - $join_table = $table['alias'] . '.'; - } - elseif (isset($info['table'])) { - // If we're aware of a table alias for this table, use the table - // alias instead of the table name. - if (isset($left) && $left['table'] == $info['table']) { - $join_table = $left['alias'] . '.'; - } - else { - $join_table = $info['table'] . '.'; - } - } - - // Convert a single-valued array of values to the single-value case, - // and transform from IN() notation to = notation - if (is_array($info['value']) && count($info['value']) == 1) { - $info['value'] = array_shift($info['value']); - } - - if (is_array($info['value'])) { - // With an array of values, we need multiple placeholders and the - // 'IN' operator is implicit. - $local_arguments = array(); - foreach ($info['value'] as $value) { - $placeholder_i = ':views_join_condition_' . $select_query->nextPlaceholder(); - $local_arguments[$placeholder_i] = $value; - } - - $operator = !empty($info['operator']) ? $info['operator'] : 'IN'; - $placeholder = '( ' . implode(', ', array_keys($local_arguments)) . ' )'; - $arguments += $local_arguments; - } - else { - // With a single value, the '=' operator is implicit. - $operator = !empty($info['operator']) ? $info['operator'] : '='; - $placeholder = ':views_join_condition_' . $select_query->nextPlaceholder(); - } - // Set 'field' as join table field if available or set 'left field' as - // join table field is not set. - if (isset($info['field'])) { - $join_table_field = "$join_table$info[field]"; - // Allow the value to be set either with the 'value' element or - // with 'left_field'. - if (isset($info['left_field'])) { - $placeholder = "$left[alias].$info[left_field]"; - } - else { - $arguments[$placeholder] = $info['value']; - } - } - // Set 'left field' as join table field is not set. - else { - $join_table_field = "$left[alias].$info[left_field]"; - $arguments[$placeholder] = $info['value']; - } - $extras[] = "$join_table_field $operator $placeholder"; - } + $this->joinAddExtra($arguments, $condition, $table, $select_query, $left_table); + } + + $select_query->addJoin($this->type, $right_table, $table['alias'], $condition, $arguments); + } + + /** + * Adds the extras to the join condition. + * + * @param $arguments + * Array of query arguments. + * + * @param $condition + * The condition to be built. + * + * @param $table + * The right table. + * + * @param $select_query + * The current select query being built. + * + * @param $left_table + * The left table. + */ + protected function joinAddExtra(&$arguments, &$condition, $table, SelectInterface $select_query, $left_table = NULL) { + if (is_array($this->extra)) { + $extras = array(); + foreach ($this->extra as $extra) { + $extras[] = $this->buildExtra($extra, $arguments, $table, $select_query, $left_table); + } - if ($extras) { - if (count($extras) == 1) { - $condition .= ' AND ' . array_shift($extras); - } - else { - $condition .= ' AND (' . implode(' ' . $this->extraOperator . ' ', $extras) . ')'; - } + if ($extras) { + if (count($extras) == 1) { + $condition .= ' AND ' . array_shift($extras); + } + else { + $condition .= ' AND (' . implode(' ' . $this->extraOperator . ' ', $extras) . ')'; } } - elseif ($this->extra && is_string($this->extra)) { - $condition .= " AND ($this->extra)"; + } + elseif ($this->extra && is_string($this->extra)) { + $condition .= " AND ($this->extra)"; + } + } + + /** + * Builds a single extra condition. + * + * @param $extra + * The extra information + * + * @param $arguments + * Array of query arguments. + * + * @param $table + * The right table. + * + * @param $select_query + * The current select query being built. + * + * @param $left_table + * The left table. + * + * @return string + * The extra condition + */ + protected function buildExtra($extra, &$arguments, $table, SelectInterface $select_query, $left_table) { + // Do not require 'value' to be set; allow for field syntax instead. + $extra += array( + 'value' => NULL, + ); + // Figure out the table name. Remember, only use aliases provided + // if at all possible. + $join_table = ''; + if (!array_key_exists('table', $extra)) { + $join_table = $table['alias'] . '.'; + } + elseif (isset($extra['table'])) { + // If we're aware of a table alias for this table, use the table + // alias instead of the table name. + if (isset($left_table) && $left_table['table'] == $extra['table']) { + $join_table = $left_table['alias'] . '.'; + } + else { + $join_table = $extra['table'] . '.'; } } - $select_query->addJoin($this->type, $right_table, $table['alias'], $condition, $arguments); + // Convert a single-valued array of values to the single-value case, + // and transform from IN() notation to = notation + if (is_array($extra['value']) && count($extra['value']) == 1) { + if (empty($extra['operator'])) { + $operator = '='; + } + else { + $operator = $extra['operator'] == 'NOT IN' ? '!=' : '='; + } + $extra['value'] = array_shift($extra['value']); + } + + if (is_array($extra['value'])) { + // With an array of values, we need multiple placeholders and the + // 'IN' operator is implicit. + $local_arguments = array(); + foreach ($extra['value'] as $value) { + $placeholder_i = ':views_join_condition_' . $select_query->nextPlaceholder(); + $local_arguments[$placeholder_i] = $value; + } + + $operator = !empty($extra['operator']) ? $extra['operator'] : 'IN'; + $placeholder = '( ' . implode(', ', array_keys($local_arguments)) . ' )'; + $arguments += $local_arguments; + } + else { + // With a single value, the '=' operator is implicit. + $operator = !empty($extra['operator']) ? $extra['operator'] : '='; + $placeholder = ':views_join_condition_' . $select_query->nextPlaceholder(); + } + // Set 'field' as join table field if available or set 'left field' as + // join table field is not set. + if (isset($extra['field'])) { + $join_table_field = "$join_table$extra[field]"; + // Allow the value to be set either with the 'value' element or + // with 'left_field'. + if (isset($extra['left_field'])) { + $placeholder = "$left_table[alias].$extra[left_field]"; + } + else { + // We are adding this placeholder only if the value is not an array + // because the individual placeholders got added earlier through the + // local arguments already. + if (!is_array($extra['value'])) { + $arguments[$placeholder] = $extra['value']; + } + } + } + // Set 'left field' as join table field is not set. + else { + $join_table_field = "$left_table[alias].$extra[left_field]"; + $arguments[$placeholder] = $extra['value']; + } + + return "$join_table_field $operator $placeholder"; } } diff --git a/core/modules/views/src/Tests/FieldApiDataTest.php b/core/modules/views/src/Tests/FieldApiDataTest.php index 96ff642..9778fbb 100644 --- a/core/modules/views/src/Tests/FieldApiDataTest.php +++ b/core/modules/views/src/Tests/FieldApiDataTest.php @@ -7,7 +7,12 @@ namespace Drupal\views\Tests; +use Drupal\field\Entity\FieldConfig; use Drupal\field\Tests\Views\FieldTestBase; +use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\node\Entity\Node; +use Drupal\node\Entity\NodeType; +use Drupal\views\Views; /** * Tests the Field Views data. @@ -16,10 +21,27 @@ */ class FieldApiDataTest extends FieldTestBase { + /** + * {@inheritdoc} + */ + public static $modules = ['language']; + + /** + * {@inheritdoc} + */ + public static $testViews = ['test_field_config_translation_filter']; + + /** + * The nodes used by the translation filter tests. + * + * @var \Drupal\node\NodeInterface[] + */ + protected $translationNodes; + protected function setUp() { - parent::setUp(); + parent::setUp(FALSE); - $field_names = $this->setUpFieldStorages(1); + $field_names = $this->setUpFieldStorages(4); // Attach the field to nodes only. $field = array( @@ -36,6 +58,96 @@ protected function setUp() { ); $nodes[] = $this->drupalCreateNode($edit); } + + $bundles = []; + $bundles[] = $bundle = NodeType::create(['type' => 'bundle1']); + $bundle->save(); + $bundles[] = $bundle = NodeType::create(['type' => 'bundle2']); + $bundle->save(); + + // Make the first field translatable on all bundles. + $field = FieldConfig::create([ + 'field_name' => $field_names[1], + 'entity_type' => 'node', + 'bundle' => $bundles[0]->id(), + 'translatable' => TRUE, + ]); + $field->save(); + $field = FieldConfig::create([ + 'field_name' => $field_names[1], + 'entity_type' => 'node', + 'bundle' => $bundles[1]->id(), + 'translatable' => TRUE, + ]); + $field->save(); + + // Make the second field not translatable on any bundle. + $field = FieldConfig::create([ + 'field_name' => $field_names[2], + 'entity_type' => 'node', + 'bundle' => $bundles[0]->id(), + 'translatable' => FALSE, + ]); + $field->save(); + $field = FieldConfig::create([ + 'field_name' => $field_names[2], + 'entity_type' => 'node', + 'bundle' => $bundles[1]->id(), + 'translatable' => FALSE, + ]); + $field->save(); + + // Make the last field translatable on some bundles. + $field = FieldConfig::create([ + 'field_name' => $field_names[3], + 'entity_type' => 'node', + 'bundle' => $bundles[0]->id(), + 'translatable' => TRUE, + ]); + $field->save(); + $field = FieldConfig::create([ + 'field_name' => $field_names[3], + 'entity_type' => 'node', + 'bundle' => $bundles[1]->id(), + 'translatable' => FALSE, + ]); + $field->save(); + + // Create some example content + ConfigurableLanguage::create([ + 'id' => 'es', + ])->save(); + ConfigurableLanguage::create([ + 'id' => 'fr', + ])->save(); + + $node = Node::create([ + 'type' => $bundles[0]->id(), + 'langcode' => 'es', + $field_names[1] => 'field name 1: es', + $field_names[2] => 'field name 2: es', + $field_names[3] => 'field name 3: es', + ]); + $node->save(); + $this->translationNodes[] = $node; + $translation = $node->getTranslation('fr'); + $translation->{$field_names[1]}->value = 'field name 1: fr'; + $translation->{$field_names[3]}->value = 'field name 3: fr'; + $translation->save(); + + $node = Node::create([ + 'type' => $bundles[1]->id(), + 'langcode' => 'es', + $field_names[1] => 'field name 1: es', + $field_names[2] => 'field name 2: es', + $field_names[3] => 'field name 3: es', + ]); + $node->save(); + $this->translationNodes[] = $node; + $translation = $node->getTranslation('fr'); + $translation->{$field_names[1]}->value = 'field name 1: fr'; + $translation->save(); + } /** @@ -88,4 +200,119 @@ function testViewsData() { $this->assertTrue(empty($data[$revision_table][$field_storage->getName()]['field']['click sortable']), 'Non-primary fields are not click sortable'); } + /** + * Tests filtering entries with different translatabilty. + */ + public function testEntityFieldFilter() { + $map = [ + 'nid' => 'nid', + 'langcode' => 'langcode', + ]; + + $view = Views::getView('test_field_config_translation_filter'); + + // Filter by 'field name 1: es'. + $view->setDisplay('embed_1'); + $this->executeView($view); + $expected = [ + [ + 'nid' => $this->translationNodes[0]->id(), + 'langcode' => 'es', + ], + [ + 'nid' => $this->translationNodes[1]->id(), + 'langcode' => 'es', + ], + ]; + + $this->assertIdenticalResultset($view, $expected, $map); + $view->destroy(); + + // Filter by 'field name 1: fr'. + $view->setDisplay('embed_2'); + $this->executeView($view); + $expected = [ + [ + 'nid' => $this->translationNodes[0]->id(), + 'langcode' => 'fr', + ], + [ + 'nid' => $this->translationNodes[1]->id(), + 'langcode' => 'fr', + ], + ]; + + $this->assertIdenticalResultset($view, $expected, $map); + $view->destroy(); + + // Filter by 'field name 2: es'. + $view->setDisplay('embed_3'); + $this->executeView($view); + $expected = [ + [ + 'nid' => $this->translationNodes[0]->id(), + 'langcode' => 'es', + ], + [ + 'nid' => $this->translationNodes[0]->id(), + 'langcode' => 'fr', + ], + [ + 'nid' => $this->translationNodes[1]->id(), + 'langcode' => 'es', + ], + [ + 'nid' => $this->translationNodes[1]->id(), + 'langcode' => 'fr', + ], + ]; + + $this->assertIdenticalResultset($view, $expected, $map); + $view->destroy(); + + // Filter by 'field name 2: fr', which doesn't exist. + $view->setDisplay('embed_4'); + $this->executeView($view); + $expected = [ + ]; + + $this->assertIdenticalResultset($view, $expected, $map); + $view->destroy(); + + // Filter by 'field name 3: es'. + $view->setDisplay('embed_5'); + $this->executeView($view); + $expected = [ + [ + 'nid' => $this->translationNodes[0]->id(), + 'langcode' => 'es', + ], + [ + 'nid' => $this->translationNodes[1]->id(), + 'langcode' => 'es', + ], + // Why is this one returned? + [ + 'nid' => $this->translationNodes[1]->id(), + 'langcode' => 'fr', + ], + ]; + + $this->assertIdenticalResultset($view, $expected, $map); + $view->destroy(); + + // Filter by 'field name 3: fr'. + $view->setDisplay('embed_6'); + $this->executeView($view); + $expected = [ + [ + 'nid' => $this->translationNodes[0]->id(), + 'langcode' => 'fr', + ], + ]; + + $this->assertIdenticalResultset($view, $expected, $map); + $view->destroy(); + } + } diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_config_translation_filter.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_config_translation_filter.yml new file mode 100644 index 0000000..146f280 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_config_translation_filter.yml @@ -0,0 +1,173 @@ +langcode: en +status: true +dependencies: { } +id: test_field_config_translation_filter +module: views +description: '' +tag: '' +base_table: node_field_data +base_field: id +core: '8' +display: + default: + display_options: + access: + type: none + cache: + type: none + fields: + nid: + id: nid + field: nid + table: node_field_data + plugin_id: field + entity_type: node + entity_type: nid + langcode: + id: langcode + field: langcode + table: node_field_data + plugin_id: field + entity_type: node + entity_field: langcode + field_name_1: + id: field_name_1 + table: node__field_name_1 + field: field_name_1 + plugin_id: field + entity_type: node + entity_field: field_name_1 + field_name_2: + id: field_name_2 + table: node__field_name_2 + field: field_name_2 + plugin_id: field + entity_type: node + entity_field: field_name_2 + field_name_3: + id: field_name_3 + table: node__field_name_3 + field: field_name_3 + plugin_id: field + entity_type: node + entity_field: field_name_3 + sorts: + nid: + id: nid + table: node_field_data + field: nid + order: ASC + plugin_id: standard + entity_type: node + entity_field: nid + style: + type: html_list + row: + type: fields + display_plugin: default + display_title: Master + id: default + position: 0 + embed_1: + display_options: + defaults: + fields: true + filters: false + filters: + field_name_1_value: + id: field_name_1_value + table: node__field_name_1 + field: field_name_1_value + value: 'field name 1: es' + plugin_id: string + entity_type: node + entity_field: field_name_1 + display_plugin: embed + display_title: Embed 1 + id: embed_1 + position: 1 + embed_2: + display_options: + defaults: + filters: false + filters: + field_name_1_value: + id: field_name_1_value + table: node__field_name_1 + field: field_name_1_value + value: 'field name 1: fr' + plugin_id: string + entity_type: node + entity_field: field_name_1 + display_plugin: embed + display_title: Embed 2 + id: embed_2 + position: 2 + embed_3: + display_options: + defaults: + filters: false + filters: + field_name_2_value: + id: field_name_2_value + table: node__field_name_2 + field: field_name_2_value + value: 'field name 2: es' + plugin_id: string + entity_type: node + entity_field: field_name_2 + display_plugin: embed + display_title: Embed 3 + id: embed_3 + position: 3 + embed_4: + display_options: + defaults: + filters: false + filters: + field_name_2_value: + id: field_name_2_value + table: node__field_name_2 + field: field_name_2_value + value: 'field name 2: fr' + plugin_id: string + entity_type: node + entity_field: field_name_2 + display_plugin: embed + display_title: Embed 4 + id: embed_4 + position: 4 + embed_5: + display_options: + defaults: + filters: false + filters: + field_name_3_value: + id: field_name_3_value + table: node__field_name_3 + field: field_name_3_value + value: 'field name 3: es' + plugin_id: string + entity_type: node + entity_field: field_name_3 + display_plugin: embed + display_title: Embed 5 + id: embed_5 + position: 5 + embed_6: + display_options: + defaults: + filters: false + filters: + field_name_3_value: + id: field_name_3_value + table: node__field_name_3 + field: field_name_3_value + value: 'field name 3: fr' + plugin_id: string + entity_type: node + entity_field: field_name_3 + display_plugin: embed + display_title: Embed 6 + id: embed_6 + position: 6 diff --git a/core/modules/views/views.module b/core/modules/views/views.module index b321940..0e7682c 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -24,7 +24,7 @@ use Drupal\Component\Plugin\Exception\PluginException; use Drupal\views\Entity\View; use Drupal\views\Views; -use Drupal\field\FieldConfigInterface; +use Drupal\Core\Entity\EntityInterface; /** * Implements hook_help(). @@ -479,23 +479,44 @@ function views_add_contextual_links(&$render_element, $location, $display_id, ar } /** - * Implements hook_ENTITY_TYPE_insert() for 'field_config'. + * Implements hook_ENTITY_TYPE_insert(). */ -function views_field_config_insert(FieldConfigInterface $field) { +function views_field_config_insert(EntityInterface $field) { Views::viewsData()->clear(); } /** - * Implements hook_ENTITY_TYPE_update() for 'field_config'. + * Implements hook_ENTITY_TYPE_update(). */ -function views_field_config_update(FieldConfigInterface $field) { +function views_field_config_update(EntityInterface $entity) { Views::viewsData()->clear(); } /** - * Implements hook_ENTITY_TYPE_delete() for 'field_config'. + * Implements hook_ENTITY_TYPE_delete(). */ -function views_field_config_delete(FieldConfigInterface $field) { +function views_field_config_delete(EntityInterface $entity) { + Views::viewsData()->clear(); +} + +/** + * Implements hook_ENTITY_TYPE_insert(). + */ +function views_base_field_override_insert(EntityInterface $entity) { + Views::viewsData()->clear(); +} + +/** + * Implements hook_ENTITY_TYPE_update(). + */ +function views_base_field_override_update(EntityInterface $entity) { + Views::viewsData()->clear(); +} + +/** + * Implements hook_ENTITY_TYPE_delete(). + */ +function views_base_field_override_delete(EntityInterface $entity) { Views::viewsData()->clear(); } diff --git a/core/modules/views/views.views.inc b/core/modules/views/views.views.inc index 4f28122..c5af71e 100644 --- a/core/modules/views/views.views.inc +++ b/core/modules/views/views.views.inc @@ -8,6 +8,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\Sql\SqlContentEntityStorage; +use Drupal\field\Entity\FieldConfig; use Drupal\field\FieldConfigInterface; use Drupal\field\FieldStorageConfigInterface; use Drupal\system\ActionConfigEntityInterface; @@ -338,6 +339,40 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora ); } + // Determine if the field instances are translatable. + $bundles_names = $field_storage->getBundles(); + $translation_join_type = FALSE; + $field_configs = []; + $translatable_configs = []; + $untranslatable_configs = []; + $untranslatable_config_bundles = []; + + foreach ($bundles_names as $bundle) { + $field_configs[$bundle] = FieldConfig::loadByName($entity_type->id(), $bundle, $field_name); + } + foreach ($field_configs as $bundle => $config) { + if ($config->isTranslatable()) { + $translatable_configs[$bundle] = $config; + } + else { + $untranslatable_configs[$bundle] = $config; + } + } + + // If the field is translatable on all the bundles, there will be a join on + // the langcode. + if (!empty($translatable_configs) && empty($untranslatable_configs)) { + $translation_join_type = 'language'; + } + // If the field is translatable only on certain bundles, there will be a join + // on langcode OR bundle name. + elseif (!empty($translatable_configs) && !empty($untranslatable_configs)) { + foreach ($untranslatable_configs as $config) { + $untranslatable_config_bundles[] = $config->getTargetBundle(); + } + $translation_join_type = 'language_bundle'; + } + // Build the relationships between the field table and the entity tables. $table_alias = $field_tables[EntityStorageInterface::FIELD_LOAD_CURRENT]['alias']; if ($data_table) { @@ -347,7 +382,6 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora 'field' => 'entity_id', 'extra' => array( array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE), - array('left_field' => 'langcode', 'field' => 'langcode'), ), ); } @@ -362,6 +396,24 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora ); } + if ($translation_join_type === 'language_bundle') { + $data[$table_alias]['table']['join'][$data_table]['join_id'] = 'field_or_language_join'; + $data[$table_alias]['table']['join'][$data_table]['extra'][] = array( + 'left_field' => 'langcode', + 'field' => 'langcode', + ); + $data[$table_alias]['table']['join'][$data_table]['extra'][] = array( + 'value' => $untranslatable_config_bundles, + 'field' => 'bundle', + ); + } + elseif ($translation_join_type === 'language') { + $data[$table_alias]['table']['join'][$data_table]['extra'][] = array( + 'left_field' => 'langcode', + 'field' => 'langcode', + ); + } + if ($supports_revisions) { $table_alias = $field_tables[EntityStorageInterface::FIELD_LOAD_REVISION]['alias']; if ($entity_revision_data_table) { @@ -371,7 +423,6 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora 'field' => 'revision_id', 'extra' => array( array('field' => 'deleted', 'value' => 0, 'numeric' => TRUE), - array('left_field' => 'langcode', 'field' => 'langcode'), ), ); } @@ -385,11 +436,26 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora ), ); } + if ($translation_join_type === 'language_bundle') { + $data[$table_alias]['table']['join'][$entity_revision_data_table]['join_id'] = 'field_or_language_join'; + $data[$table_alias]['table']['join'][$entity_revision_data_table]['extra'][] = array( + 'left_field' => 'langcode', + 'field' => 'langcode', + ); + $data[$table_alias]['table']['join'][$entity_revision_data_table]['extra'][] = array( + 'value' => $untranslatable_config_bundles, + 'field' => 'bundle', + ); + } + elseif ($translation_join_type === 'language') { + $data[$table_alias]['table']['join'][$entity_revision_data_table]['extra'][] = array( + 'left_field' => 'langcode', + 'field' => 'langcode', + ); + } } $group_name = $entity_type->getLabel(); - // Get the list of bundles the field appears in. - $bundles_names = $field_storage->getBundles(); // Build the list of additional fields to add to queries. $add_fields = array('delta', 'langcode', 'bundle'); foreach (array_keys($field_columns) as $column) {