function tripal_views_views_data
2.x tripal_views.views.inc | tripal_views_views_data() |
1.x tripal_views.views.inc | tripal_views_views_data() |
Implements hook_views_data().
Generates a dynamic data array for Views
This function is a hook used by the Views module. It populates and returns a data array that specifies for the Views module the base table, the tables it joins with and handlers. The data array is populated using the data stored in the tripal_views tables.
Return value
a data array formatted for the Views module
D7 @todo: Add support for materialized views relationships using the new method
Related topics
File
- tripal_views/
tripal_views.views.inc, line 51 - Tripal Views Integration
Code
function tripal_views_views_data() {
$data = array();
// Manually integrate the drupal.tripal_views* tables
$data = tripal_views_views_data_tripal_views_tables($data);
// Determine the name of the chado schema
$chado_schema = tripal_get_schema_name('chado');
// MAKE SURE ALL CHADO TABLES ARE INTEGRATED
tripal_views_integrate_all_chado_tables();
// DEFINE GLOBAL FIELDS
// Filter handler that lets the admin say:
// "Show no results until they enter search parameters"
$data['views']['search_results'] = array(
'title' => t('Delay Results'),
'help' => t('Delay results until Apply/Search is clicked by the user.'),
'filter' => array(
'handler' => 'tripal_views_handler_filter_no_results',
),
);
$data['views']['action_links_area'] = array(
'title' => t('Action Links'),
'help' => t('Add action links to the view.'),
'area' => array(
'handler' => 'tripal_views_handler_area_action_links',
),
);
$tvi_query = db_query('SELECT * FROM {tripal_views}');
// INTEGRATE THE LIGHTEST SETUP FOR EACH TABLE
foreach ($tvi_query as $tvi_row) {
// check to see if this is the lightest (drupal-style) priority setup for this table
// if not then don't use this definition
$lightest_priority_setup = tripal_is_lightest_priority_setup($tvi_row->setup_id, $tvi_row->table_name);
if (!$lightest_priority_setup) {
continue;
}
// ids we'll use for queries
$setup_id = $tvi_row->setup_id;
$mview_id = $tvi_row->mview_id;
// holds the base table name and fields
$base_table = '';
$base_fields = array();
// indicated whether the current table is a base table or not
$is_base_table = $tvi_row->base_table;
// POPULATE THE BASE TABLE NAME AND FIELDS
// If an $mview_id is given then get the materialized view info,
// otherwise get the Chado table info
$legacy_mview = FALSE;
if ($mview_id) {
// get the base table name from the materialized view
// D7 TODO: Check DBTNG changes work
$sql = "SELECT name, mv_specs FROM {tripal_mviews} WHERE mview_id = :id";
$mview_table = db_query($sql, array(':id' => $mview_id));
$mview_table = $mview_table->fetchObject();
$base_table = $mview_table->name;
if (!empty($mview_table->mv_specs)) {
$legacy_mview = TRUE;
}
}
if ($legacy_mview) {
// get the columns in this materialized view. They are separated by commas
// where the first word is the column name and the rest is the type
$columns = explode(",", $mview_table->mv_specs);
foreach ($columns as $column) {
$column = trim($column); // trim trailing and leading spaces
preg_match("/^(.*?)\ (.*?)$/", $column, $matches);
$column_name = $matches[1];
$column_type = $matches[2];
$base_fields[$column_name] = array(
'column_name' => $column_name,
'type' => $column_type,
);
}
// get the field name and descriptions
// D7 TODO: Check DBTNG changes work
$sql = "SELECT * FROM {tripal_views_field} WHERE setup_id=:setup";
$query = db_query($sql, array(':setup' => $setup_id));
foreach ($query as $field) {
$base_fields[$field->column_name]['name'] = $field->name;
$base_fields[$field->column_name]['help'] = $field->description;
}
}
// if this is not a legacy materialized view
else {
$base_table = $tvi_row->table_name;
// get the table description
$table_desc = chado_get_schema($base_table);
$fields = $table_desc['fields'];
if (!is_array($fields)) {
$fields = array();
}
foreach ($fields as $column => $attrs) {
$base_fields[$column] = array(
'column_name' => $column,
// Add a default for type since module developers may sometimes need to use a
// PostgreSQL-specific type.
'type' => (isset($attrs['type'])) ? $attrs['type'] : 'text',
);
// If PostgreSQL-specifc types are needed the module developer should be given
// a way to set the most closely matching type for views. They should also be
// allowed to override the type for views. This can be done by adding a views_type
// to the schema definition :-).
if (isset($attrs['views_type'])) {
$base_fields[$column]['type'] = $attrs['views_type'];
}
// Tell admin about this feature and warn them that we made an assumption for them.
if (!isset($attrs['type']) AND !isset($attrs['views_type'])) {
tripal_report_error(
'tripal_views',
TRIPAL_WARNING,
"Unable to determine the type for %column thus we have defaulted to type 'text'.
Tip: This may be due to setting a postgresql-specific type. Solution: Add a
'views_type' to your schema definition to specify what type should be used.",
array('%column' => $column)
);
}
}
// get the field name and descriptions
$sql = "SELECT * FROM {tripal_views_field} WHERE setup_id=:setup";
$query = db_query($sql, array(':setup' => $setup_id));
foreach ($query as $field) {
$base_fields[$field->column_name]['name'] = $field->name;
$base_fields[$field->column_name]['help'] = $field->description;
}
}
// SETUP THE BASE TABLE INFO IN THE DATA ARRAY
$data[$base_table]['table']['group'] = t("$tvi_row->name");
if ($is_base_table) {
$data[$base_table]['table']['base'] = array(
'group' => "$tvi_row->name",
'title' => "$tvi_row->name",
'help' => $tvi_row->comment,
'search_path' => $chado_schema
);
}
else {
$data[$base_table]['table'] = array(
'group' => "$tvi_row->name",
'title' => "$tvi_row->name",
'help' => $tvi_row->comment,
'search_path' => $chado_schema
);
}
// ADD THE FIELDS TO THE DATA ARRAY
foreach ($base_fields as $column_name => $base_field) {
if (!isset($base_field['name'])) {
$data[$base_table][$column_name] = array(
'title' => t($column_name),
'help' => t($column_name),
'field' => array(
'click sortable' => TRUE,
),
);
tripal_report_error(
'tripal_views',
TRIPAL_DEBUG,
"The name and help were not set for %table.%column. As a consequence the column
name has been used... You should ensure that the 'name' and 'help' keys for
this field are set in the integration array (priority = %priority)",
array(
'%table' => $base_table,
'%column' => $column_name,
'%priority' => $tvi_row->priority
)
);
}
else {
$data[$base_table][$column_name] = array(
'title' => t($base_field['name']),
'help' => t($base_field['help']),
'field' => array(
'click sortable' => TRUE,
),
);
}
// now add the handlers
$sql = "SELECT * FROM {tripal_views_handlers} WHERE setup_id = :setup AND column_name = :column";
$handlers = db_query($sql, array(':setup' => $setup_id, ':column' => $column_name));
$num_handlers = 0;
foreach ($handlers as $handler) {
$num_handlers++;
$data[$base_table][$column_name][$handler->handler_type]['handler'] = $handler->handler_name;
// Add in any additional arguments
// This should be a serialized array including (at a minimum) name => <handler name>
if ($handler->arguments) {
$data[$base_table][$column_name][$handler->handler_type] = array_merge($data[$base_table][$column_name][$handler->handler_type], unserialize($handler->arguments));
}
}
// If there were no handlers applied to the current field then warn the administrator!
if ($num_handlers == 0) {
tripal_report_error(
'tripal_views',
TRIPAL_DEBUG,
"No handlers were registered for %table.%column. This means there is no views
functionality for this column. To register handlers, make sure the 'handlers'
key for this field is set in the integration array (priority = %priority).
The supported keys include 'field', 'filter', 'sort', 'relationship'. Look
at the tripal_add_views_integration() for additional details.",
array(
'%table' => $base_table,
'%column' => $column_name,
'%priority' => $tvi_row->priority
)
);
}
}
// ADD JOINS & RELATIONSHIPS TO DATA ARRAY
// only add joins if this is a base table
// this keeps the list of available fields manageable
// all other tables should be added via relationships
$sql = "SELECT * FROM {tripal_views_join} WHERE setup_id = :setup";
$joins = db_query($sql, array(':setup' => $setup_id));
if (!isset($joins)) {
$joins = array();
}
foreach ($joins as $join) {
$left_table = $join->left_table;
$left_field = $join->left_field;
$base_table = $join->base_table;
$base_field = $join->base_field;
$handler = $join->handler;
$base_title = ucwords(str_replace('_', ' ', $base_table));
$left_title = ucwords(str_replace('_', ' ', $left_table));
// if the 'node' table is in our integrated list then
// we want to skip it. It shouldn't be there.
if ($left_table == 'node') {
continue;
}
// add join entry
if (!$join->relationship_only) {
$data[$left_table]['table']['join'][$base_table] = array(
'left_field' => $base_field,
'field' => $left_field,
);
if ($handler) {
$data[$left_table]['table']['join'][$base_table]['handler'] = $handler;
}
if (!empty($join->arguments)) {
array_merge($data[$left_table]['table']['join'][$base_table], unserialize($join->arguments));
}
}
// warn if deprecated method of relationship addition was used (ie: through handlers)
if (isset($data[$base_table][$base_field]['relationship'])) {
tripal_report_error('tripal_views', TRIPAL_NOTICE,
'DEPRECATED: Currently using tripal_views_handlers to store relationship for %base => %left when you should be using tripal_views_joins.',
array('%base' => $base_table, '%left' => $left_table));
}
// Add relationship entry.
// NOTE: we use a fake field name to allow us to have multiple
// relationships for the same field (ie: feature.feature_id has many
// Many relationships but views only supports a single one).
$fake_field = $base_field . '_to_' . $left_table;
// Bug Fix: The old $fake_field used above doesn't take into account
// multiple relationships to the same left table. To keep backwards
// compatibility, this old fake_field needs to continue to be used for
// the LAST recorded relationship. However, for all previously set
// relationships we can use an improved fake name which takes into
// account the left field and ensures all relationships for a single
// left table are not condensed into a single relationship.
if (array_key_exists($fake_field, $data[$base_table])) {
// Again, note that we can't just change the fake_name after finding
// there is more than one relationship because then the FIRST
// relationship would keep the old fake_name rather than the LAST
// which keeps backwards compatiblity since the old naming caused all
// previous relationships be be overridden by the next one.
// Thus we first need to determine the left field of the previous
// join for this table combination and then use that to form our
// improved fake field.
$previous_left_field = $data[$base_table][$fake_field]['relationship']['base field'];
$improved_fake_field = $base_field . '_to_' . $left_table . "." . $previous_left_field;
$data[$base_table][$improved_fake_field] = $data[$base_table][$fake_field];
}
$data[$base_table][$fake_field] = array(
'title' => "$base_title.$base_field => $left_title.$left_field",
'help' => t("Joins @base to @left", array('@base' => "$base_title.$base_field", '@left' => "$left_title.$left_field")),
'relationship' => array(
'handler' => $join->relationship_handler,
'title' => t("$base_field => $left_title ($left_field)"),
'label' => t("$base_field => $left_title ($left_field)"),
'real field' => $base_field,
'base' => $left_table,
'base field' => $left_field
)
);
if (!empty($join->arguments)) {
array_merge($data[$base_table][$fake_field]['relationship'], unserialize($join->arguments));
}
}
}
return $data;
}