3 namespace Drupal\views\Plugin\views\join;
5 use Drupal\Core\Database\Query\SelectInterface;
8 * Implementation for the "field OR language" join.
10 * If the extra conditions contain either ".langcode" or ".bundle", they will be
11 * grouped and joined with OR instead of AND. The entire group will then be
12 * joined to the other conditions with AND.
14 * This is needed for configurable fields that are translatable on some bundles
15 * and untranslatable on others. The correct field values to fetch in this case
16 * have a langcode that matches the entity record *or* have a bundle on which
17 * the field is untranslatable. Thus, the entity base table (or data table, or
18 * revision data table, respectively) must join the field data table (or field
19 * revision table) on a matching langcode *or* a bundle where the field is
20 * untranslatable. The following example views data achieves this for a node
21 * field named 'field_tags' which is translatable on an 'article' node type, but
22 * not on the 'news' and 'page' node types:
25 * $data['node__field_tags']['table']['join']['node_field_data'] = [
26 * 'join_id' => 'field_or_language_join',
27 * 'table' => 'node__field_tags',
28 * 'left_field' => 'nid',
29 * 'field' => 'entity_id',
32 * 'field' => 'deleted',
37 * 'left_field' => 'langcode',
38 * 'field' => 'langcode',
41 * 'field' => 'bundle',
42 * 'value' => ['news', 'page'],
48 * The resulting join condition for this example would be the following:
51 * ON node__field_tags.deleted = 0
53 * node_field_data.langcode = node__field_tags.langcode
54 * OR node__field.tags.bundle IN ['news', 'page']
58 * @see views_field_default_views_data()
60 * @ingroup views_join_handlers
62 * @ViewsJoin("field_or_language_join")
64 class FieldOrLanguageJoin extends JoinPluginBase {
69 protected function joinAddExtra(&$arguments, &$condition, $table, SelectInterface $select_query, $left_table = NULL) {
70 if (empty($this->extra)) {
74 if (is_array($this->extra)) {
76 foreach ($this->extra as $extra) {
77 $extras[] = $this->buildExtra($extra, $arguments, $table, $select_query, $left_table);
80 // Remove and store the langcode OR bundle join condition extra.
81 $language_bundle_conditions = [];
82 foreach ($extras as $key => $extra) {
83 if (strpos($extra, '.langcode') !== FALSE || strpos($extra, '.bundle') !== FALSE) {
84 $language_bundle_conditions[] = $extra;
89 if (count($extras) > 1) {
90 $condition .= ' AND (' . implode(' ' . $this->extraOperator . ' ', $extras) . ')';
93 $condition .= ' AND ' . array_shift($extras);
96 // Tack on the langcode OR bundle join condition extra.
97 if (!empty($language_bundle_conditions)) {
98 $condition .= ' AND (' . implode(' OR ', $language_bundle_conditions) . ')';
101 elseif (is_string($this->extra)) {
102 $condition .= " AND ($this->extra)";