summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaroly Negyesi2011-12-06 16:25:44 (GMT)
committer Karoly Negyesi2011-12-06 16:25:44 (GMT)
commit77c38430f4f90a6a72dc4c63c7f8077d782a7c4d (patch)
tree2f7ba16cbdb37f7a1164ed7b1ae3753f0aee1d72
parent606d433f65fbb511511397e52a35ea75bb3b5fcc (diff)
Replace relationship definitions to cover all the bases and so Relation plays well with Views. #1361780 by solotandem, dereine and chx. Needs followups
-rw-r--r--tests/relation.views.test46
-rw-r--r--views/relation.views.inc91
-rw-r--r--views/relation_handler_relationship.inc84
3 files changed, 103 insertions, 118 deletions
diff --git a/tests/relation.views.test b/tests/relation.views.test
index af57b82..a9e9161 100644
--- a/tests/relation.views.test
+++ b/tests/relation.views.test
@@ -30,6 +30,7 @@ class RelationViewsTestCase extends RelationTestCase {
if (!module_exists('views')) {
return;
}
+/*
// Relations as a base table.
foreach (array('symmetric', 'directional', 'octopus') as $relation_type) {
$view = new view;
@@ -74,19 +75,25 @@ class RelationViewsTestCase extends RelationTestCase {
break;
}
}
-
+*/
// Symmetric.
foreach (array(3, 1) as $required => $count) {
$view = new view;
$handler = $view->new_display('default');
- $handler->display->display_options['relationships']['relation_symmetric_node']['id'] = 'relation_symmetric_node';
- $handler->display->display_options['relationships']['relation_symmetric_node']['table'] = 'node';
- $handler->display->display_options['relationships']['relation_symmetric_node']['field'] = 'relation_symmetric_node';
- $handler->display->display_options['relationships']['relation_symmetric_node']['required'] = $required;
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_endpoints_node']['id'] = 'endpoints_base_symmetric_right_endpoints_node';
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_endpoints_node']['table'] = 'field_data_endpoints';
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_endpoints_node']['field'] = 'endpoints_base_symmetric_right_endpoints_node';
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_endpoints_node']['required'] = $required;
+ /* Relationship: Endpoints: symmetric (relation[symmetric] -> node) */
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_node']['id'] = 'endpoints_base_symmetric_right_node';
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_node']['table'] = 'field_data_endpoints';
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_node']['field'] = 'endpoints_base_symmetric_right_node';
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_node']['relationship'] = 'endpoints_base_symmetric_right_endpoints_node';
+ $handler->display->display_options['relationships']['endpoints_base_symmetric_right_node']['required'] = $required;
$handler->display->display_options['fields']['nid']['id'] = 'nid';
$handler->display->display_options['fields']['nid']['table'] = 'node';
$handler->display->display_options['fields']['nid']['field'] = 'nid';
- $handler->display->display_options['fields']['nid']['relationship'] = 'relation_symmetric_node';
+ $handler->display->display_options['fields']['nid']['relationship'] = 'endpoints_base_symmetric_right_node';
$handler->display->display_options['arguments']['nid']['id'] = 'nid';
$handler->display->display_options['arguments']['nid']['table'] = 'node';
$handler->display->display_options['arguments']['nid']['field'] = 'nid';
@@ -96,9 +103,9 @@ class RelationViewsTestCase extends RelationTestCase {
$this->assertEqual(count($view->result), $count);
$match_count = 0;
foreach ($view->result as $result) {
- if (isset($result->node_node_nid)) {
+ if (isset($result->node_field_data_endpoints_nid)) {
$match_count++;
- $this->assertEqual($result->node_node_nid, $this->node4->nid);
+ $this->assertEqual($result->node_field_data_endpoints_nid, $this->node4->nid);
}
}
$this->assertEqual($match_count, 1);
@@ -108,15 +115,20 @@ class RelationViewsTestCase extends RelationTestCase {
for ($r_index = -1; $r_index < 2; $r_index++) {
$view = new view;
$handler = $view->new_display('default');
- $handler->display->display_options['relationships']['relation_directional_node']['id'] = 'relation_directional_node';
- $handler->display->display_options['relationships']['relation_directional_node']['table'] = 'node';
- $handler->display->display_options['relationships']['relation_directional_node']['field'] = 'relation_directional_node';
- $handler->display->display_options['relationships']['relation_directional_node']['required'] = 1;
- $handler->display->display_options['relationships']['relation_directional_node']['r_index'] = $r_index;
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_endpoints_node']['id'] = 'endpoints_base_directional_right_endpoints_node';
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_endpoints_node']['table'] = 'field_data_endpoints';
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_endpoints_node']['field'] = 'endpoints_base_directional_right_endpoints_node';
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_endpoints_node']['required'] = 1;
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_endpoints_node']['r_index'] = $r_index;
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_node']['id'] = 'endpoints_base_directional_right_node';
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_node']['table'] = 'field_data_endpoints';
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_node']['field'] = 'endpoints_base_directional_right_node';
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_node']['relationship'] = 'endpoints_base_directional_right_endpoints_node';
+ $handler->display->display_options['relationships']['endpoints_base_directional_right_node']['required'] = 1;
$handler->display->display_options['fields']['nid']['id'] = 'nid';
$handler->display->display_options['fields']['nid']['table'] = 'node';
$handler->display->display_options['fields']['nid']['field'] = 'nid';
- $handler->display->display_options['fields']['nid']['relationship'] = 'relation_directional_node';
+ $handler->display->display_options['fields']['nid']['relationship'] = 'endpoints_base_directional_right_node';
$handler->display->display_options['arguments']['nid']['id'] = 'nid';
$handler->display->display_options['arguments']['nid']['table'] = 'node';
$handler->display->display_options['arguments']['nid']['field'] = 'nid';
@@ -129,19 +141,19 @@ class RelationViewsTestCase extends RelationTestCase {
$this->assertEqual(count($view->result), 2);
$matches = array($this->node1->nid => TRUE, $this->node4->nid => TRUE);
foreach ($view->result as $result) {
- unset($matches[$result->node_node_nid]);
+ unset($matches[$result->node_field_data_endpoints_nid]);
}
$this->assertFalse($matches);
break;
case 0:
// Source. This finds the 3->4 relation.
$this->assertEqual(count($view->result), 1);
- $this->assertEqual($view->result[0]->node_node_nid, $this->node4->nid);
+ $this->assertEqual($view->result[0]->node_field_data_endpoints_nid, $this->node4->nid);
break;
case 1:
// Target. This finds the 1->3 relation.
$this->assertEqual(count($view->result), 1);
- $this->assertEqual($view->result[0]->node_node_nid, $this->node1->nid);
+ $this->assertEqual($view->result[0]->node_field_data_endpoints_nid, $this->node1->nid);
break;
}
}
diff --git a/views/relation.views.inc b/views/relation.views.inc
index 9765c1e..c07344e 100644
--- a/views/relation.views.inc
+++ b/views/relation.views.inc
@@ -156,14 +156,10 @@ function relation_views_data() {
'handler' => 'views_handler_sort',
),
);
- return $data;
-}
+ // Define the base group of this table.
+ $data['field_data_endpoints']['table']['group'] = t('Endpoints');
-/**
- * Implements hook_views_data_alter().
- */
-function relation_views_data_alter(&$data) {
// Find out which entity type has which base table.
$entity_infos = entity_get_info();
$entity_tables = array();
@@ -189,63 +185,66 @@ function relation_views_data_alter(&$data) {
'@left' => $entity_type_left,
'@relation_type_label' => $relation_type->label,
);
- $data[$base_table_left]['relation_base_left_' . $type] = array(
- 'title' => t('Relation: @relation_type_label (@left -> relation)', $t_arguments),
- 'help' => t('Provides a relationship from @left to the relation table via the relation @relation_type_label', $t_arguments),
- 'relationship' => array(
- // relation_handler_relationship::options_form() relies on this check_plain().
- 'label' => check_plain($relation_type->label),
- 'base' => 'relation',
- 'base field' => 'rid',
- 'relationship field' => $relationship_field,
- 'handler' => 'views_handler_relationship',
- 'relation_type' => $type,
- 'entity_type_left' => $entity_type_left,
- 'entity_type_right' => 'relation',
- 'directional' => $relation_type->directional,
- 'join_handler' => 'relation_handler_base_left_join',
- ),
- );
foreach ($relation_type->$target_index as $target_bundle) {
$target_bundle = explode(':', $target_bundle, 2);
$entity_type_right = $target_bundle[0];
$base_table_right = $entity_tables[$entity_type_right];
$t_arguments['@right'] = $entity_type_right;
- $data[$base_table_left]['relation_' . $type . '_' . $entity_type_right] = array(
- 'title' => t('Relation: @relation_type_label (@left <-> @right)', $t_arguments),
- 'help' => t('Provides a relationship from @left to @right via the relation @relation_type_label', $t_arguments),
+ // Define [join and] relationship from relation to endpoints.
+ $data['relation']['relation_base_' . $type . '_right_endpoints'] = array(
+ 'title' => t('Endpoints: @relation_type_label (relation -> endpoints)', $t_arguments),
+ 'help' => t('Provides a relationship from the relation table to endpoints relative to the "@relation_type_label" relation', $t_arguments),
'relationship' => array(
// relation_handler_relationship::options_form() relies on this check_plain().
- 'label' => check_plain($relation_type->label),
- 'base' => $base_table_right,
- 'base field' => $entity_infos[$entity_type_right]['entity keys']['id'],
- 'relationship field' => $relationship_field,
- 'handler' => 'relation_handler_relationship',
- 'relation_type' => $type,
- 'entity_type_left' => $entity_type_left,
- 'entity_type_right' => $entity_type_right,
+ 'label' => check_plain('Endpoints::' . $relation_type->label),
+ 'base' => 'field_data_endpoints',
+ 'base field' => 'entity_id',
+ 'handler' => 'relation_handler_relationship', // To choose the r_index option.
+ 'relation_type' => $type, // USE THIS as bundle
+ 'entity_type_right' => $entity_type_right, // Use this as endpoint_entity_type.
'directional' => $relation_type->directional,
- 'join_handler' => 'relation_handler_join',
+ 'max_arity' => $relation_type->max_arity,
+ 'join_handler' => 'relation_handler_relation_endpoint_join', // To add the r_index condition to join.
+ ),
+ );
+
+ // Define join and relationship from endpoints to entity.
+ $data['field_data_endpoints']['table']['join'] = array(
+ // Directly links to the $entity_type_right table.
+ $entity_type_right => array(
+ 'left_field' => $entity_infos[$entity_type_right]['entity keys']['id'],
+ 'field' => 'endpoints_entity_id',
),
);
- $data['relation']['relation_base_right_' . $entity_type_right] = array(
- 'title' => t('Relation: @relation_type_label (relation -> @right)', $t_arguments),
- 'help' => t('Provides a relationship from the relation table to @right via the relation @relation_type_label', $t_arguments),
+ $data['field_data_endpoints']['endpoints_base_' . $type . '_right_' . $entity_type_right] = array(
+ 'title' => t('@relation_type_label (relation[@relation_type_label] -> @right)', $t_arguments),
+ 'help' => t('Provides a relationship from the relation to @right using "@relation_type_label" relation', $t_arguments),
'relationship' => array(
- // relation_handler_relationship::options_form() relies on this check_plain().
- 'label' => check_plain($relation_type->label),
+ 'label' => check_plain('Endpoints::' . $relation_type->label),
'base' => $base_table_right,
'base field' => $entity_infos[$entity_type_right]['entity keys']['id'],
- 'relationship field' => $relationship_field,
- 'handler' => 'views_handler_relationship',
- 'relation_type' => $type,
- 'entity_type_left' => 'relation',
- 'entity_type_right' => $entity_type_right,
+ 'relationship field' => 'endpoints_entity_id',
+ ),
+ );
+
+ // Define [join and] relationship from endpoints to endpoints.
+ $data['field_data_endpoints']['endpoints_base_' . $type . '_right_endpoints_' . $entity_type_right] = array(
+ 'title' => t('@relation_type_label (@left -> relation[@relation_type_label])', $t_arguments),
+ 'help' => t('Provides a relationship from @left to the relation using to the "@relation_type_label" relation', $t_arguments),
+ 'relationship' => array(
+ // relation_handler_relationship::options_form() relies on this check_plain().
+ 'label' => check_plain('Endpoints::' . $relation_type->label),
+ 'base' => 'field_data_endpoints',
+ 'base field' => 'entity_id',
+ 'handler' => 'relation_handler_relationship',
+ 'relation_type' => $type, // USE THIS as bundle
+ 'entity_type_right' => $entity_type_right, // Use this as endpoint_entity_type.
'directional' => $relation_type->directional,
- 'join_handler' => 'relation_handler_base_right_join',
+ 'join_handler' => 'relation_handler_endpoint_endpoint_join',
),
);
}
}
}
+ return $data;
}
diff --git a/views/relation_handler_relationship.inc b/views/relation_handler_relationship.inc
index 001addc..dcdd8a5 100644
--- a/views/relation_handler_relationship.inc
+++ b/views/relation_handler_relationship.inc
@@ -46,78 +46,52 @@ class relation_handler_relationship extends views_handler_relationship {
}
}
-class relation_handler_join extends views_join {
+class relation_handler_endpoint_endpoint_join extends views_join {
/**
* Build the SQL for the join this object represents.
+ *
+ * This does an endpoint to endpoint join relative to a relation.
*/
function build_join($select_query, $table, $view_query) {
- $field = field_info_field('endpoints');
- $relation_data_table_name = _field_sql_storage_tablename($field);
- $entity_id_field_name = _field_sql_storage_columnname('endpoints', 'entity_id');
$entity_type_field_name = _field_sql_storage_columnname('endpoints', 'entity_type');
$r_index_field_name = _field_sql_storage_columnname('endpoints', 'r_index');
- // Join the left table with the entity type to the endpoints field data table.
- $left = $view_query->get_table_info($this->left_table);
- $entity_type_left = $this->definition['entity_type_left'];
- $conditions = "$left[alias].$this->left_field = %alias.$entity_id_field_name AND %alias.$entity_type_field_name = '$entity_type_left'";
- if ($this->definition['directional'] && $this->options['r_index'] > -1) {
- $conditions .= " AND %alias.$r_index_field_name = " . $this->options['r_index'];
- }
- // Left join alias.
- $l = $select_query->addJoin($this->type, $relation_data_table_name, NULL, $conditions);
- // Execute a self-join.
$entity_type_right = $this->definition['entity_type_right'];
- // entity_id here is the ID of the relation entity.
$relation_type = $this->definition['relation_type'];
- $conditions = "%alias.entity_id = $l.entity_id AND %alias.$r_index_field_name != $l.$r_index_field_name AND %alias.$entity_type_field_name = '$entity_type_right' AND %alias.bundle = '$relation_type'";
- // Right join alias.
- $r = $select_query->addJoin($this->type, $relation_data_table_name, NULL, $conditions);
- // Join the right table to the relation_data table.
- $conditions = "%alias.$this->field = $r.$entity_id_field_name";
- $select_query->addJoin($this->type, $table['table'], $table['alias'], $conditions);
- }
-}
+ // Note: the Views naming convention on left versus right is opposite the
+ // actual order in the join clause.
-class relation_handler_base_left_join extends views_join {
- /**
- * Build the SQL for the join this object represents.
- */
- function build_join($select_query, $table, $view_query) {
- $field = field_info_field('endpoints');
- $relation_data_table_name = _field_sql_storage_tablename($field);
- $entity_id_field_name = _field_sql_storage_columnname('endpoints', 'entity_id');
- $entity_type_field_name = _field_sql_storage_columnname('endpoints', 'entity_type');
- $r_index_field_name = _field_sql_storage_columnname('endpoints', 'r_index');
- // Join the left table with the entity type to the relation table.
- $left = $view_query->get_table_info($this->left_table);
- $entity_type_left = $this->definition['entity_type_left'];
- $conditions = "$left[alias].$this->left_field = %alias.$entity_id_field_name AND %alias.$entity_type_field_name = '$entity_type_left' AND %alias.$r_index_field_name = 0";
- // Left join alias.
- $l = $select_query->addJoin($this->type, $relation_data_table_name, NULL, $conditions);
- // entity_id here is the ID of the relation entity.
- $relation_type = $this->definition['relation_type'];
- $conditions = "%alias.rid = $l.entity_id AND %alias.relation_type = '$relation_type'";
+ // The aliased name of the existing endpoint table we are joining to.
+ $l = $this->left_table;
+ // The aliased name of the current endpoint table.
+ $r = $table['alias'];
+
+ // Self-join the endpoints table but grab a different endpoint (r_index).
+ $conditions = "$r.entity_id = $l.entity_id AND $r.$r_index_field_name != $l.$r_index_field_name";
+ if ($this->options['r_index'] > -1) {
+ // Grab a specific index.
+ $conditions .= " AND $l.$r_index_field_name = " . $this->options['r_index'];
+ }
+ // Restrict the join to the proper entity type and bundle.
+ $conditions .= " AND $r.$entity_type_field_name = '$entity_type_right' AND $r.bundle = '$relation_type'";
+
+ // Add a self-join.
$select_query->addJoin($this->type, $table['table'], $table['alias'], $conditions);
}
}
-class relation_handler_base_right_join extends views_join {
+class relation_handler_relation_endpoint_join extends views_join {
/**
- * Build the SQL for the join this object represents.
+ * Construct the views_join object.
+ *
+ * This does a relation to endpoint join.
*/
- function build_join($select_query, $table, $view_query) {
- $field = field_info_field('endpoints');
- $relation_table = $view_query->get_table_info($this->left_table);
- $relation_data_table_name = _field_sql_storage_tablename($field);
- $entity_id_field_name = _field_sql_storage_columnname('endpoints', 'entity_id');
- $entity_type_field_name = _field_sql_storage_columnname('endpoints', 'entity_type');
+ function construct($table = NULL, $left_table = NULL, $left_field = NULL, $field = NULL, $extra = array(), $type = 'LEFT') {
+ parent::construct($table, $left_table, $left_field, $field, $extra, $type);
$r_index_field_name = _field_sql_storage_columnname('endpoints', 'r_index');
- $conditions = "$relation_table[alias].rid = %alias.entity_id AND %alias.$r_index_field_name = 1";
- $l = $select_query->addJoin($this->type, $relation_data_table_name, NULL, $conditions);
- $entity_type_right = $this->definition['entity_type_right'];
- $conditions = "$l.$entity_type_field_name = '$entity_type_right' AND %alias.$this->field = $l.$entity_id_field_name";
- $select_query->addJoin($this->type, $table['table'], $table['alias'], $conditions);
+ if ($this->options['r_index'] > -1) {
+ $this->extra = array(array('field' => $r_index_field_name, 'value' => $this->options['r_index']));
+ }
}
}