diff --git a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php index 051955e..0a3a711 100644 --- a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php +++ b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php @@ -260,6 +260,7 @@ public function buildJoin($select_query, $table, $view_query) { 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 = NULL; } $condition = "$left_field = $table[alias].$this->field"; @@ -267,96 +268,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) { - if (empty($info['operator'])) { - $operator = '='; - } - else { - $operator = $info['operator'] == 'NOT IN' ? '!=' : '='; - } - $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, $left, $select_query); + } + + $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 $left + * The left table. + * + * @param $select_query + * The current select query being built. + */ + protected function joinAddExtra(&$arguments, &$condition, $table, $left = NULL, $select_query) { + if (is_array($this->extra)) { + $extras = array(); + foreach ($this->extra as $extra) { + $extras[] = $this->buildExtra($extra, $arguments, $table, $left, $select_query); + } - 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 $left + * The left table. + * + * @param $select_query + * The current select query being built. + * + * @return string + * The extra condition + */ + protected function buildExtra($extra, &$arguments, $table, $left, $select_query) { + // 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) && $left['table'] == $extra['table']) { + $join_table = $left['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[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[alias].$extra[left_field]"; + $arguments[$placeholder] = $extra['value']; + } + + return "$join_table_field $operator $placeholder"; } }