View source
<?php
function entity_views_data() {
$data = array();
foreach (entity_crud_get_info() as $type => $info) {
if (!isset($info['views controller class'])) {
$info['views controller class'] = isset($info['module']) && !module_hook($info['module'], 'views_data') ? 'EntityDefaultViewsController' : FALSE;
}
if ($info['views controller class']) {
$controller = new $info['views controller class']($type);
foreach ($controller
->views_data() as $table => $table_data) {
$data += array(
$table => array(),
);
$data[$table] = array_merge($data[$table], $table_data);
}
}
}
foreach (entity_get_info() as $type => $info) {
$table = entity_views_table_definition($type);
if ($table) {
$data['entity_' . $type] = $table;
}
$data['views_entity_' . $type] = array();
foreach (entity_get_all_property_info($type) as $key => $property) {
if (!empty($property['entity views field'])) {
entity_views_field_definition($key, $property, $data['views_entity_' . $type]);
}
}
}
foreach (entity_get_info() as $entity_type => $info) {
if (entity_type_supports($entity_type, 'view')) {
$data['views_entity_' . $entity_type]['rendered_entity'] = array(
'title' => t('Rendered @entity-type', array(
'@entity-type' => $info['label'],
)),
'help' => t('The @entity-type of the current relationship rendered using a view mode.', array(
'@entity-type' => $info['label'],
)),
'field' => array(
'handler' => 'entity_views_handler_field_entity',
'type' => $entity_type,
'real field' => 'entity object',
),
);
}
}
$data['entity__global']['table']['group'] = t('Entity');
$data['entity__global']['table']['join'] = array(
'#global' => array(),
);
$data['entity__global']['entity'] = array(
'title' => t('Rendered entity'),
'help' => t('Displays a single chosen entity.'),
'area' => array(
'handler' => 'entity_views_handler_area_entity',
),
);
return $data;
}
function entity_views_table_definition($type, $exclude = TRUE) {
$tables =& drupal_static(__FUNCTION__, array());
if (!isset($tables[$type])) {
if (!class_exists('EntityFieldHandlerHelper')) {
module_load_include('inc', 'entity', 'views/handlers/entity_views_field_handler_helper');
}
$info = entity_get_info($type);
$tables[$type]['table'] = array(
'group' => $info['label'],
'entity type' => $type,
);
foreach (entity_get_all_property_info($type) as $key => $property) {
if (!$exclude || empty($property['entity views field'])) {
entity_views_field_definition($key, $property, $tables[$type]);
}
}
}
return $tables[$type];
}
function entity_views_field_definition($field, array $property_info, array &$table, $title_prefix = '') {
$additional = array();
$additional_field = array();
$key = _entity_views_field_identifier($field, $table);
if ($key != $field) {
$additional['real field'] = $field;
}
$field_name = EntityFieldHandlerHelper::get_selector_field_name($field);
$field_handlers = entity_views_get_field_handlers();
$property_info += entity_property_info_defaults();
$type = entity_property_extract_innermost_type($property_info['type']);
$title = $title_prefix . $property_info['label'];
if ($info = entity_get_info($type)) {
$additional['relationship'] = array(
'handler' => $field_handlers['relationship'],
'base' => 'entity_' . $type,
'base field' => $info['entity keys']['id'],
'relationship field' => $field,
'label' => $title,
);
if ($property_info['type'] != $type) {
$additional['relationship']['multiple'] = TRUE;
}
if (!isset($field_handlers[$type])) {
$type = 'entity';
}
}
elseif (!empty($property_info['field'])) {
$type = 'field';
$additional_field['field_name'] = $field_name;
$additional_field['entity_tables'] = array();
$additional_field['entity type'] = $table['table']['entity type'];
$additional_field['is revision'] = FALSE;
}
elseif (isset($property_info['options list']) && is_callable($property_info['options list'])) {
$type = 'options';
$additional_field['options callback'] = array(
'function' => $property_info['options list'],
'info' => $property_info,
);
}
elseif ($type == 'decimal') {
$additional_field['float'] = TRUE;
}
if (isset($field_handlers[$type])) {
$table += array(
$key => array(),
);
$table[$key] += array(
'title' => $title,
'help' => empty($property_info['description']) ? t('(No information available)') : $property_info['description'],
'field' => array(),
);
$table[$key]['field'] += array(
'handler' => $field_handlers[$type],
'type' => $property_info['type'],
);
$table[$key] += $additional;
$table[$key]['field'] += $additional_field;
}
if (!empty($property_info['property info'])) {
foreach ($property_info['property info'] as $nested_key => $nested_property) {
entity_views_field_definition($field . ':' . $nested_key, $nested_property, $table, $title . ' » ');
}
}
}
function entity_views_get_field_handlers() {
$field_handlers = drupal_static(__FUNCTION__);
if (!isset($field_handlers)) {
$field_handlers = array(
'text' => 'entity_views_handler_field_text',
'token' => 'entity_views_handler_field_text',
'integer' => 'entity_views_handler_field_numeric',
'decimal' => 'entity_views_handler_field_numeric',
'date' => 'entity_views_handler_field_date',
'duration' => 'entity_views_handler_field_duration',
'boolean' => 'entity_views_handler_field_boolean',
'uri' => 'entity_views_handler_field_uri',
'options' => 'entity_views_handler_field_options',
'field' => 'entity_views_handler_field_field',
'entity' => 'entity_views_handler_field_entity',
'relationship' => 'entity_views_handler_relationship',
);
drupal_alter('entity_views_field_handlers', $field_handlers);
}
return $field_handlers;
}
function _entity_views_field_identifier($field, array $table) {
$key = $base = preg_replace('/[^a-zA-Z0-9]+/S', '_', $field);
$i = 0;
while ($key == 'table' || isset($table[$key]) && (isset($table[$key]['real field']) ? $table[$key]['real field'] : $key) != $field) {
$key = $base . '_' . ++$i;
}
return $key;
}
function entity_views_plugins() {
$data = views_cache_get('entity_base_tables', TRUE);
if (!empty($data->data)) {
$base_tables = $data->data;
}
else {
$base_tables = array();
foreach (views_fetch_data() as $table => $data) {
if (!empty($data['table']['entity type']) && !empty($data['table']['base'])) {
$base_tables[] = $table;
}
}
views_cache_set('entity_base_tables', $base_tables, TRUE);
}
if (!empty($base_tables)) {
return array(
'module' => 'entity',
'row' => array(
'entity' => array(
'title' => t('Rendered entity'),
'help' => t('Renders a single entity in a specific view mode (e.g. teaser).'),
'handler' => 'entity_views_plugin_row_entity_view',
'uses fields' => FALSE,
'uses options' => TRUE,
'type' => 'normal',
'base' => $base_tables,
),
),
);
}
}
class EntityDefaultViewsController {
protected $type, $info, $relationships;
public function __construct($type) {
$this->type = $type;
$this->info = entity_get_info($type);
}
public function views_data() {
$data = array();
$this->relationships = array();
if (!empty($this->info['base table'])) {
$table = $this->info['base table'];
$data[$table]['table']['group'] = drupal_ucfirst($this->info['label']);
$data[$table]['table']['entity type'] = $this->type;
$label = isset($this->info['plural label']) ? $this->info['plural label'] : $this->info['label'];
$data[$table]['table']['base'] = array(
'field' => $this->info['entity keys']['id'],
'access query tag' => $this->type . '_access',
'title' => drupal_ucfirst($label),
'help' => isset($this->info['description']) ? $this->info['description'] : '',
);
$data[$table]['table']['entity type'] = $this->type;
$data[$table] += $this
->schema_fields();
$data += $this->relationships;
}
if (!empty($this->info['revision table']) && !empty($this->info['entity keys']['revision'])) {
$revision_table = $this->info['revision table'];
$data[$table]['table']['default_relationship'] = array(
$revision_table => array(
'table' => $revision_table,
'field' => $this->info['entity keys']['revision'],
),
);
$data[$revision_table]['table']['group'] = drupal_ucfirst($this->info['label']) . ' ' . t('Revisions');
$data[$revision_table]['table']['entity type'] = $this->type;
$label = isset($this->info['plural label']) ? $this->info['plural label'] : $this->info['label'];
$data[$revision_table]['table']['base'] = array(
'field' => $this->info['entity keys']['revision'],
'access query tag' => $this->type . '_access',
'title' => drupal_ucfirst($label) . ' ' . t('Revisions'),
'help' => (isset($this->info['description']) ? $this->info['description'] . ' ' : '') . t('Revisions'),
);
$data[$revision_table]['table']['entity type'] = $this->type;
$data[$revision_table] += $this
->schema_revision_fields();
$data += $this->relationships;
$data[$revision_table]['table']['join'] = array(
$table => array(
'left_field' => $this->info['entity keys']['revision'],
'field' => $this->info['entity keys']['revision'],
),
);
$data[$revision_table]['table']['default_relationship'] = array(
$table => array(
'table' => $table,
'field' => $this->info['entity keys']['id'],
),
);
}
return $data;
}
protected function schema_fields() {
$schema = drupal_get_schema($this->info['base table']);
$properties = entity_get_property_info($this->type) + array(
'properties' => array(),
);
$data = array();
foreach ($properties['properties'] as $name => $property_info) {
if (isset($property_info['schema field']) && isset($schema['fields'][$property_info['schema field']])) {
if ($views_info = $this
->map_from_schema_info($name, $schema['fields'][$property_info['schema field']], $property_info)) {
$data[$name] = $views_info;
}
}
}
return $data;
}
protected function schema_revision_fields() {
$data = array();
if (!empty($this->info['revision table'])) {
$schema = drupal_get_schema($this->info['revision table']);
$properties = entity_get_property_info($this->type) + array(
'properties' => array(),
);
foreach ($properties['properties'] as $name => $property_info) {
if (isset($property_info['schema field']) && isset($schema['fields'][$property_info['schema field']])) {
if ($views_info = $this
->map_from_schema_info($name, $schema['fields'][$property_info['schema field']], $property_info)) {
$data[$name] = $views_info;
}
}
}
}
return $data;
}
protected function map_from_schema_info($property_name, $schema_field_info, $property_info) {
$type = isset($property_info['type']) ? $property_info['type'] : 'text';
$views_field_name = $property_info['schema field'];
$return = array();
if (!empty($schema_field_info['serialize'])) {
return FALSE;
}
$description = array(
'title' => $property_info['label'],
'help' => isset($property_info['description']) ? $property_info['description'] : NULL,
);
if (($info = entity_get_info($type)) && !empty($info['base table'])) {
$label_lowercase = drupal_strtolower($this->info['label'][0]) . drupal_substr($this->info['label'], 1);
$property_label_lowercase = drupal_strtolower($property_info['label'][0]) . drupal_substr($property_info['label'], 1);
$name = !isset($this->relationships[$info['base table']][$this->info['base table']]) ? $this->info['base table'] : $this->info['base table'] . '_' . $views_field_name;
$this->relationships[$info['base table']][$name] = array(
'title' => $this->info['label'],
'help' => t("Associated @label via the @label's @property.", array(
'@label' => $label_lowercase,
'@property' => $property_label_lowercase,
)),
'relationship' => array(
'label' => $this->info['label'],
'handler' => $this
->getRelationshipHandlerClass($this->type, $type),
'base' => $this->info['base table'],
'base field' => $views_field_name,
'relationship field' => isset($info['entity keys']['name']) ? $info['entity keys']['name'] : $info['entity keys']['id'],
),
);
$return['relationship'] = array(
'label' => drupal_ucfirst($info['label']),
'handler' => $this
->getRelationshipHandlerClass($type, $this->type),
'base' => $info['base table'],
'base field' => isset($info['entity keys']['name']) ? $info['entity keys']['name'] : $info['entity keys']['id'],
'relationship field' => $views_field_name,
);
$type = isset($info['entity keys']['name']) ? 'token' : 'integer';
if ($property_name != $views_field_name) {
$description['title'] .= ' ' . $views_field_name;
}
}
switch ($type) {
case 'token':
case 'text':
$return += $description + array(
'field' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_field',
'click sortable' => TRUE,
),
'sort' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_sort',
),
'filter' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_argument_string',
),
);
break;
case 'decimal':
case 'integer':
$return += $description + array(
'field' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_field_numeric',
'click sortable' => TRUE,
'float' => $type == 'decimal',
),
'sort' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_sort',
),
'filter' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_argument_numeric',
),
);
break;
case 'date':
$return += $description + array(
'field' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_field_date',
'click sortable' => TRUE,
),
'sort' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_filter_date',
),
'argument' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_argument_date',
),
);
break;
case 'duration':
$return += $description + array(
'field' => array(
'real field' => $views_field_name,
'handler' => 'entity_views_handler_field_duration',
'click sortable' => TRUE,
),
'sort' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_sort',
),
'filter' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_argument_numeric',
),
);
break;
case 'uri':
$return += $description + array(
'field' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_field_url',
'click sortable' => TRUE,
),
'sort' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_sort',
),
'filter' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_argument_string',
),
);
break;
case 'boolean':
$return += $description + array(
'field' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_field_boolean',
'click sortable' => TRUE,
),
'sort' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_sort',
),
'filter' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_filter_boolean_operator',
),
'argument' => array(
'real field' => $views_field_name,
'handler' => 'views_handler_argument_string',
),
);
break;
}
if (isset($return['filter']) && !empty($property_info['options list'])) {
$return['filter']['handler'] = 'views_handler_filter_in_operator';
$return['filter']['options callback'] = array(
'EntityDefaultViewsController',
'optionsListCallback',
);
$return['filter']['options arguments'] = array(
$this->type,
$property_name,
'view',
);
}
if (isset($return['field']) && !empty($property_info['options list']) && class_exists('views_handler_field_machine_name')) {
$return['field']['handler'] = 'views_handler_field_machine_name';
$return['field']['options callback'] = array(
'EntityDefaultViewsController',
'optionsListCallback',
);
$return['field']['options arguments'] = array(
$this->type,
$property_name,
'view',
);
}
return $return;
}
public function getRelationshipHandlerClass($entity_type, $left_type) {
foreach (entity_get_info() as $type => $info) {
if (!empty($info['bundle of']) && $info['bundle of'] == $entity_type && $type != $left_type) {
return 'entity_views_handler_relationship_by_bundle';
}
}
return 'views_handler_relationship';
}
public static function optionsListCallback($type, $selector, $op = 'view') {
$wrapper = entity_metadata_wrapper($type, NULL);
$parts = explode(':', $selector);
foreach ($parts as $part) {
$wrapper = $wrapper
->get($part);
}
return $wrapper
->optionsList($op);
}
}