One Relationship Handler to Rule Them All. (Props to solotandem for the wild idea...
[project/relation.git] / views / relation_handler_relationship.inc
CommitLineData
690a082a
KN
1<?php
2
0cbf252c 3/**
4 * @file
5 * Views relationship support.
6 */
7
e8e00ad3 8class relation_handler_relationship extends views_handler_relationship {
690a082a 9 /**
42905f30
KN
10 * Define r_index option.
11 */
12 function option_definition() {
13 $options = parent::option_definition();
6d4fd43b 14 $options['r_index'] = array('default' => -1);
cab16c0c 15 return $options;
42905f30
KN
16 }
17
18 /**
19 * Let the user choose r_index.
20 */
21 function options_form(&$form, &$form_state) {
22 parent::options_form($form, $form_state);
23
24 $options = $this->options_form_summary_options();
25 if ($this->definition['directional']) {
26 $form['r_index'] = array(
27 '#type' => 'select',
28 '#options' => $options,
33272867 29 '#title' => t('Position of the relationship base'),
42905f30 30 '#default_value' => $this->options['r_index'],
c9121485
KN
31 // check_plain()'d in the definition.
32 '#description' => t('Select whether the entity you are adding the relationship to is source or target of !relation_type_label relation.', array('!relation_type_label' => $this->definition['label'])),
42905f30
KN
33 );
34 }
35 }
36
37 /**
38 * Return the main options, which are shown in the summary title.
39 */
40 function options_form_summary_options() {
41 return $this->definition['directional'] ? array(
42 -1 => t('Any'),
43 0 => t('Source'),
44 1 => t('Target'),
45 ) : array();
46 }
690a082a 47
e8e00ad3
KN
48 function query() {
49 $field = field_info_field('endpoints');
50 $relation_data_table_name = _field_sql_storage_tablename($field);
51 $entity_id_field_name = _field_sql_storage_columnname('endpoints', 'entity_id');
52 $entity_type_field_name = _field_sql_storage_columnname('endpoints', 'entity_type');
53 $r_index_field_name = _field_sql_storage_columnname('endpoints', 'r_index');
54 $join_type = empty($this->options['required']) ? 'LEFT' : 'INNER';
55 $endpoints_twice = isset($this->definition['entity_type_left']) && isset($this->definition['entity_type_right']);
56
57 $this->ensure_my_table();
eb4575d4
KN
58 // Join the left table with the entity type to the endpoints field data table.
59 $join = new views_join();
60 $join->definition = array(
61 'left_table' => $this->table_alias,
62 'left_field' => $this->real_field,
e8e00ad3
KN
63 'table' => $relation_data_table_name,
64 'field' => isset($this->definition['entity_type_left']) ? $entity_id_field_name : 'entity_id',
65 'type' => $join_type,
eb4575d4
KN
66 'extra' => array(
67 array(
68 'field' => 'bundle',
06b0cf1f 69 'value' => $this->definition['relation_type'],
eb4575d4 70 ),
eb4575d4
KN
71 ),
72 );
e8e00ad3
KN
73 if (isset($this->definition['entity_type_left'])) {
74 $join->definition['extra'][] = array(
75 'field' => $entity_type_field_name,
76 'value' => $this->definition['entity_type_left'],
77 );
78 }
eb4575d4
KN
79 if ($this->definition['directional'] && $this->options['r_index'] > -1) {
80 $join->definition['extra'][] = array(
e8e00ad3 81 'field' => $r_index_field_name,
eb4575d4
KN
82 'value' => $this->options['r_index'],
83 );
84 }
85 $join->construct();
86 $join->adjusted = TRUE;
e8e00ad3 87 $l = $this->query->add_table($relation_data_table_name, $this->relationship, $join);
77c38430 88
e8e00ad3 89 if ($endpoints_twice) {
4fa7ba75
KN
90 // Execute a self-join.
91 $join = new views_join();
92 $join->definition = array(
e8e00ad3 93 'left_table' => $l,
4fa7ba75 94 'left_field' => 'entity_id',
e8e00ad3 95 'table' => $relation_data_table_name,
4fa7ba75 96 'field' => 'entity_id',
e8e00ad3 97 'type' => $join_type,
4fa7ba75
KN
98 'extra' => array(
99 array(
e8e00ad3 100 'field' => $entity_type_field_name,
4fa7ba75
KN
101 'value' => $this->definition['entity_type_right'],
102 ),
103 ),
104 );
105 $join->construct();
106 $join->adjusted = TRUE;
e8e00ad3 107 $r = $this->query->add_table($relation_data_table_name, $this->relationship, $join);
4fa7ba75
KN
108 }
109 else {
e8e00ad3
KN
110 $r = $l;
111 }
112 $join = new views_join();
113 $join->definition = array(
114 'left_table' => $r,
115 'left_field' => isset($this->definition['entity_type_right']) ? $entity_id_field_name : 'entity_id',
116 'table' => $this->definition['base'],
117 'field' => $this->definition['base field'],
118 'type' => $join_type,
119 );
120 // There is no query where these conditions could be added earlier:
121 // $r might be just $l.
122 if ($endpoints_twice && $this->definition['entity_type_left'] == $this->definition['entity_type_right']) {
123 $join->definition['extra'][] = array(
124 // This definition is a bit funny but there's no other way to tell
125 // Views to use this as it is.
126 'table' => NULL,
127 'field' => "$r.$r_index_field_name != $l.$r_index_field_name AND 1",
128 'value' => 1,
129 );
130 }
131 if (isset($this->definition['entity_type_right'])) {
132 $join->definition['extra'][] = array(
133 'table' => $r,
134 'field' => $entity_type_field_name,
135 'value' => $this->definition['entity_type_right'],
136 );
4fa7ba75 137 }
28e651b3 138
e8e00ad3
KN
139 $join->construct();
140 $join->adjusted = TRUE;
141 // use a short alias for this:
142 $alias = $this->definition['base'] . '_' . $this->table;
143 $this->alias = $this->query->add_relationship($alias, $join, $this->definition['base'], $this->relationship);
4fa7ba75 144 }
5e198c72 145}