Skip to content

Instantly share code, notes, and snippets.

@infojunkie
Last active December 17, 2015 17:19
Show Gist options
  • Save infojunkie/5645012 to your computer and use it in GitHub Desktop.
Save infojunkie/5645012 to your computer and use it in GitHub Desktop.
A Drupal Views join handler to be used with node translation relationships. This join returns translated nodes *or* the node itself if it is not translated. This is useful to guarantee that some node is returned. To understand the context: http://thereisamoduleforthat.com/content/view-nodes-and-their-translations.
<?php
/**
* Implements hook_views_data_alter().
*/
function views_join_translation_views_data_alter(&$data) {
$data['node']['translation']['relationship']['join_handler'] = 'views_join_translation';
}
/**
* Join handler class for node translations.
*
* Pretty much a copy of views_join::build_join (http://api.drupal.org/api/views/includes!handlers.inc/class/views_join/7)
* except for the PAYLOAD part.
*/
class views_join_translation extends views_join {
function build_join($select_query, $table, $view_query) {
if (empty($this->definition['table formula'])) {
$right_table = $this->table;
}
else {
$right_table = $this->definition['table formula'];
}
if ($this->left_table) {
$left = $view_query->get_table_info($this->left_table);
$left_field = "$left[alias].$this->left_field";
}
else {
// This can be used if left_field is a formula or something. It should be used only *very* rarely.
$left_field = $this->left_field;
}
// *** PAYLOAD ***
// Add condition for empty tnid but same node.
$condition = "($left_field = $table[alias].$this->field OR ($table[alias].$this->field = 0 AND $left[alias].nid = $table[alias].nid))";
$arguments = array();
// Tack on the extra.
if (isset($this->extra)) {
if (is_array($this->extra)) {
$extras = array();
foreach ($this->extra as $info) {
$extra = '';
// 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.
foreach ($info['value'] as $value) {
$placeholder_i = ':views_join_condition_' . $select_query->nextPlaceholder();
$arguments[$placeholder_i] = $value;
}
$operator = !empty($info['operator']) ? $info['operator'] : 'IN';
$placeholder = '( ' . implode(', ', array_keys($arguments)) . ' )';
}
else {
// With a single value, the '=' operator is implicit.
$operator = !empty($info['operator']) ? $info['operator'] : '=';
$placeholder = ':views_join_condition_' . $select_query->nextPlaceholder();
$arguments[$placeholder] = $info['value'];
}
$extras[] = "$join_table$info[field] $operator $placeholder";
}
if ($extras) {
if (count($extras) == 1) {
$condition .= ' AND ' . array_shift($extras);
}
else {
$condition .= ' AND (' . implode(' ' . $this->extra_type . ' ', $extras) . ')';
}
}
}
elseif ($this->extra && is_string($this->extra)) {
$condition .= " AND ($this->extra)";
}
}
$select_query->addJoin($this->type, $right_table, $table['alias'], $condition, $arguments);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment