class views_many_to_one_helper {
public $placeholders = array();
function __construct(&$handler) {
$this->handler = &$handler;
}
static function option_definition(&$options) {
$options['reduce_duplicates'] = array('default' => FALSE, 'bool' => TRUE);
}
function options_form(&$form, &$form_state) {
$form['reduce_duplicates'] = array(
'#type' => 'checkbox',
'#title' => t('Reduce duplicates'),
'#description' => t('This filter can cause items that have more than one of the selected options to appear as duplicate results. If this filter causes duplicate results to occur, this checkbox can reduce those duplicates; however, the more terms it has to search for, the less performant the query will be, so use this with caution. Shouldn\'t be set on single-value fields, as it may cause values to disappear from display, if used on an incompatible field.'),
'#default_value' => !empty($this->handler->options['reduce_duplicates']),
'#weight' => 4,
);
}
function get_field() {
if (!empty($this->formula)) {
return $this->handler->get_formula();
}
else {
return $this->handler->table_alias . '.' . $this->handler->real_field;
}
}
function add_table($join = NULL, $alias = NULL) {
$field = $this->handler->relationship . '_' . $this->handler->table . '.' . $this->handler->field;
if (empty($join)) {
$join = $this->get_join();
}
$relationship = $this->handler->relationship;
if (empty($this->handler->query->relationships[$relationship])) {
$base_table = $this->handler->query->base_table;
}
else {
$base_table = $this->handler->query->relationships[$relationship]['base'];
}
$r_join = clone $join;
while (!empty($r_join) && $r_join->left_table != $base_table) {
$r_join = views_get_table_join($r_join->left_table, $base_table);
}
if ($r_join->table != $join->table) {
$relationship = $this->handler->query->add_relationship($this->handler->table . '_' . $r_join->table, $r_join, $r_join->table, $this->handler->relationship);
}
$alias = $this->handler->query->add_table($this->handler->table, $relationship, $join, $alias);
if (empty($this->handler->view->many_to_one_tables[$field])) {
$this->handler->view->many_to_one_tables[$field] = $this->handler->value;
}
else {
$this->handler->view->many_to_one_tables[$field] = array_merge($this->handler->view->many_to_one_tables[$field], $this->handler->value);
}
return $alias;
}
function get_join() {
return $this->handler->get_join();
}
function summary_join() {
$field = $this->handler->relationship . '_' . $this->handler->table . '.' . $this->handler->field;
$join = $this->get_join();
$options = $this->handler->options;
$view = &$this->handler->view;
$query = &$this->handler->query;
if (!empty($options['require_value'])) {
$join->type = 'INNER';
}
if (empty($options['add_table']) || empty($view->many_to_one_tables[$field])) {
return $query->ensure_table($this->handler->table, $this->handler->relationship, $join);
}
else {
if (!empty($view->many_to_one_tables[$field])) {
foreach ($view->many_to_one_tables[$field] as $value) {
$join->extra = array(
array(
'field' => $this->handler->real_field,
'operator' => '!=',
'value' => $value,
'numeric' => !empty($this->definition['numeric']),
),
);
}
}
return $this->add_table($join);
}
}
function ensure_my_table() {
if (!isset($this->handler->table_alias)) {
$field = $this->handler->relationship . '_' . $this->handler->table . '.' . $this->handler->field;
if ($this->handler->operator == 'or' && empty($this->handler->options['reduce_duplicates'])) {
if (empty($this->handler->options['add_table']) && empty($this->handler->view->many_to_one_tables[$field])) {
$join = $this->get_join();
if (isset($join)) {
$join->type = 'LEFT';
$group = isset($this->handler->options['group']) ? $this->handler->options['group'] : FALSE;
$group_type = !empty($group) ? $this->handler->query->where[$group]['type'] : FALSE;
$plugin_id = isset($this->handler->options['plugin_id']) ? $this->handler->options['plugin_id'] : FALSE;
if ($group === FALSE || $group_type == 'AND' && $plugin_id && $plugin_id != 'taxonomy_index_tid') {
$join->type = 'INNER';
}
}
$this->handler->table_alias = $this->handler->query->ensure_table($this->handler->table, $this->handler->relationship, $join);
$this->handler->view->many_to_one_tables[$field] = $this->handler->value;
}
else {
$join = $this->get_join();
$join->type = 'LEFT';
if (!empty($this->handler->view->many_to_one_tables[$field])) {
foreach ($this->handler->view->many_to_one_tables[$field] as $value) {
$join->extra = array(
array(
'field' => $this->handler->real_field,
'operator' => '!=',
'value' => $value,
'numeric' => !empty($this->handler->definition['numeric']),
),
);
}
}
$this->handler->table_alias = $this->add_table($join);
}
return $this->handler->table_alias;
}
$this->handler->table_aliases = array();
$values = $this->handler->operator === 'not' ? array($this->handler->value) : $this->handler->value;
foreach ($values as $value) {
$join = $this->get_join();
if ($this->handler->operator == 'and') {
$join->type = 'INNER';
}
if (empty($join->extra)) {
$join->extra = array();
}
$join->extra[] = array(
'field' => $this->handler->real_field,
'value' => $value,
'numeric' => !empty($this->handler->definition['numeric']),
);
if (($this->handler->is_a_group() && is_array($value)) || $this->handler->operator === 'not') {
$value = serialize($value);
}
if (!isset($this->handler->view->many_to_one_aliases[$field][$value])) {
if (!isset($this->handler->view->many_to_one_count[$this->handler->table])) {
$this->handler->view->many_to_one_count[$this->handler->table] = 0;
}
$this->handler->view->many_to_one_aliases[$field][$value] = $this->handler->table . '_value_' . ($this->handler->view->many_to_one_count[$this->handler->table]++);
$alias = $this->handler->table_aliases[$value] = $this->add_table($join,
$this->handler->view->many_to_one_aliases[$field][$value]);
if (empty($this->handler->table_alias)) {
$this->handler->table_alias = $alias;
}
}
else {
$this->handler->table_aliases[$value] = $this->handler->view->many_to_one_aliases[$field][$value];
}
}
}
return $this->handler->table_alias;
}
function placeholder() {
return $this->handler->query->placeholder($this->handler->options['table'] . '_' . $this->handler->options['field']);
}
function add_filter() {
if (empty($this->handler->value)) {
return;
}
$this->handler->ensure_my_table();
$field = $this->get_field();
$options = $this->handler->options;
$operator = $this->handler->operator;
$formula = !empty($this->formula);
$value = $this->handler->value;
if (empty($options['group'])) {
$options['group'] = 0;
}
$add_condition = TRUE;
if ($operator == 'or' && empty($options['reduce_duplicates'])) {
if (count($value) > 1) {
$operator = 'IN';
}
else {
$value = is_array($value) ? array_pop($value) : $value;
if (is_array($value) && count($value) > 1) {
$operator = 'IN';
}
else {
$operator = '=';
}
}
$add_condition = FALSE;
}
elseif ($operator == 'not') {
$value = NULL;
$operator = 'IS NULL';
$add_condition = FALSE;
}
if (!$add_condition) {
if ($formula) {
$placeholder = $this->placeholder();
if ($operator == 'IN') {
$operator = "$operator IN($placeholder)";
}
else {
$operator = "$operator $placeholder";
}
$placeholders = array(
$placeholder => $value,
) + $this->placeholders;
$this->handler->query->add_where_expression($options['group'], "$field $operator", $placeholders);
}
else {
$this->handler->query->add_where($options['group'], $field, $value, $operator);
}
}
if ($add_condition) {
$field = $this->handler->real_field;
$clause = $operator == 'or' ? db_or() : db_and();
foreach ($this->handler->table_aliases as $value => $alias) {
if ($operator == 'not') {
$value = NULL;
}
$clause->condition("$alias.$field", $value);
}
$this->handler->query->add_where($options['group'], $clause);
}
}
}