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/views.views.inc b/core/modules/views/views.views.inc index ea865e2..ed872d1 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,38 @@ 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 +380,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 +394,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 +421,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 +434,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) {