Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 83 additions & 1 deletion reference.module
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@
* Defines a field type for referencing other entites.
*/

/**
* Implements hook_autoload_info().
*/
function reference_autoload_info() {
return array(
'reference_plugin_display' => 'views/reference_plugin_display.inc',
'reference_plugin_row_fields' => 'views/reference_plugin_row_fields.inc',
'reference_plugin_style' => 'views/reference_plugin_style.inc',
);
}

/**
* Implements hook_views_api().
*/
function reference_views_api() {
return array(
'api' => 3,
'path' => backdrop_get_path('module', 'reference') . '/views',
);
}

/**
* Implements hook_entity_info_alter().
*
Expand Down Expand Up @@ -425,15 +446,76 @@ function reference_field_views_data($field) {
$target_info = entity_get_info($field['settings']['entity_type']);
// Get the default values of the views config data for this field.
$data = field_views_field_default_views_data($field);

$entity_type = $target_info['label'];
if ($entity_type == t('Node')) {
$entity_type = t('Content');
}
$parameters = array('@type' => $entity_type, '!field_name' => $field['field_name']);

// Alter data for both the field_data and field_revision tables.
foreach ($data as $table_name => $table_data) {
// Add a relationship to the target table from the [field_name]_target_id.
$data[$table_name][$field['field_name'] . '_target_id']['relationship'] = array(
'handler' => 'views_handler_relationship',
'base' => $target_info['base table'],
'base field' => $target_info['entity keys']['id'],
'label' => t('!type referenced by !field_name', array('!type' => $target_info['label'], '!field_name' => $field['field_name'])),
'label' => t('@type referenced by !field_name', $parameters),
'group' => t('Reference'),
'title' => t('Reference to'),
'help' => t('A bridge to the @type that is referenced in the field !field_name', $parameters),
);
}
return $data;
}

/**
* Implements hook_field_views_data_views_data_alter().
*
* Views integration to provide reverse relationships on reference fields.
*/
function reference_field_views_data_views_data_alter(&$data, $field) {
foreach ($field['bundles'] as $entity_type => $bundles) {
if (isset($field['settings']['target_type'])) {
$target_entity_info = entity_get_info($field['settings']['target_type']);
if (isset($target_entity_info['base table'])) {
$entity_info = entity_get_info($entity_type);
$entity = $entity_info['label'];
if ($entity == t('Node')) {
$entity = t('Content');
}
$target_entity = $target_entity_info['label'];
if ($target_entity == t('Node')) {
$target_entity = t('Content');
}

$pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
$replacements = array('@entity' => $entity, '@target_entity' => $target_entity, '!field_name' => $field['field_name']);
$data[$target_entity_info['base table']][$pseudo_field_name]['relationship'] = array(
'handler' => 'views_handler_relationship_entity_reverse',
'field_name' => $field['field_name'],
'field table' => _field_sql_storage_tablename($field),
'field field' => $field['field_name'] . '_target_id',
'base' => $entity_info['base table'],
'base field' => $entity_info['entity keys']['id'],
'label' => t('@entity referencing @target_entity from !field_name', $replacements),
'group' => t('Entity Reference'),
'title' => t('Reference'),
'help' => t('A bridge to the @entity that is referencing @target_entity via !field_name', $replacements),
'join_extra' => array(
0 => array(
'field' => 'entity_type',
'value' => $entity_type,
),
1 => array(
'field' => 'deleted',
'value' => 0,
'numeric' => TRUE,
),
),
);
}
}
}
}

87 changes: 87 additions & 0 deletions reference.views.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php
/**
* @file
* Views integration for Reference.
*/

/**
* Implements hook_field_views_data().
*/
function reference_field_views_data($field) {
// Get info for the entity type this field references to add a relationship.
$target_info = entity_get_info($field['settings']['entity_type']);
// Get the default values of the views config data for this field.
$data = field_views_field_default_views_data($field);

$entity_type = $target_info['label'];
if ($entity_type == t('Node')) {
$entity_type = t('Content');
}
$parameters = array('@type' => $entity_type, '!field_name' => $field['field_name']);

// Alter data for both the field_data and field_revision tables.
foreach ($data as $table_name => $table_data) {
// Add a relationship TO the target table from the [field_name]_target_id.
$data[$table_name][$field['field_name'] . '_target_id']['relationship'] = array(
'handler' => 'views_handler_relationship',
'base' => $target_info['base table'],
'base field' => $target_info['entity keys']['id'],
'label' => t('@type referenced by !field_name', $parameters),
'group' => t('Reference'),
'title' => t('Reference to'),
'help' => t('A bridge to the @type that is referenced in the field <em>!field_name</em>', $parameters),
);
}

return $data;
}

/**
* Implements hook_field_views_data_views_data_alter().
*
* Views integration to provide reverse relationships on reference fields.
*/
function reference_field_views_data_views_data_alter(&$data, $field) {
foreach ($field['bundles'] as $entity_type => $bundles) {
if (array_key_exists('entity_type', $field['settings'])) {
$target_entity_info = entity_get_info($field['settings']['entity_type']);
if (isset($target_entity_info['base table'])) {
$entity_info = entity_get_info($entity_type);
$entity = $entity_info['label'];
if ($entity == t('Node')) {
$entity = t('Content');
}
$target_entity = $target_entity_info['label'];
if ($target_entity == t('Node')) {
$target_entity = t('Content');
}

$pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type;
$replacements = array('@entity' => $entity, '@target_entity' => $target_entity, '!field_name' => $field['field_name']);
$data[$target_entity_info['base table']][$pseudo_field_name]['relationship'] = array(
'handler' => 'views_handler_relationship_entity_reverse',
'field_name' => $field['field_name'],
'field table' => _field_sql_storage_tablename($field),
'field field' => $field['field_name'] . '_target_id',
'base' => $entity_info['base table'],
'base field' => $entity_info['entity keys']['id'],
'label' => t('@entity referencing @target_entity from !field_name', $replacements),
'group' => t('Entity Reference'),
'title' => t('Reference from'),
'help' => t('A bridge to the @entity that has @target_entity in its field <em>!field_name</em>', $replacements),
'join_extra' => array(
0 => array(
'field' => 'entity_type',
'value' => $entity_type,
),
1 => array(
'field' => 'deleted',
'value' => 0,
'numeric' => TRUE,
),
),
);
}
}
}
}
124 changes: 124 additions & 0 deletions views/reference_plugin_display.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php
/**
* @file
* Handler for reference_plugin_display.
*/
class reference_plugin_display extends views_plugin_display {

function option_definition() {
$options = parent::option_definition();

// Force the style plugin to 'reference_style' and the row plugin to
// 'fields'.
$options['style_plugin']['default'] = 'reference_style';
$options['defaults']['default']['style_plugin'] = FALSE;
$options['defaults']['default']['style_options'] = FALSE;
$options['row_plugin']['default'] = 'reference_fields';
$options['defaults']['default']['row_plugin'] = FALSE;
$options['defaults']['default']['row_options'] = FALSE;

// Set the display title to an empty string (not used in this display type).
$options['title']['default'] = '';
$options['defaults']['default']['title'] = FALSE;

return $options;
}

function get_style_type() {
return 'reference';
}

function execute() {
return $this->view->render($this->display->id);
}

function render() {
if (!empty($this->view->result) || !empty($this->view->style_plugin->definition['even empty'])) {
return $this->view->style_plugin->render($this->view->result);
}
return '';
}

function uses_exposed() {
return FALSE;
}

function query() {
$options = $this->get_option('reference_options');

// Play nice with Views UI 'preview' : if the view is not executed through
// reference_SelectionHandler_Views::getReferencableEntities(),
// don't alter the query.
if (empty($options)) {
return;
}

// Make sure the id field is included in the results, and save its alias
// so that references_plugin_style can retrieve it.
$this->id_field_alias = $id_field = $this->view->query->add_field($this->view->base_table, $this->view->base_field);
if (strpos($id_field, '.') === FALSE) {
$id_field = $this->view->base_table . '.' . $this->id_field_alias;
}

// Restrict the autocomplete options based on what's been typed already.
if (isset($options['match'])) {
$style_options = $this->get_option('style_options');
$value = db_like($options['match']) . '%';
if ($options['match_operator'] != 'STARTS_WITH') {
$value = '%' . $value;
}

// Multiple search fields are OR'd together
$conditions = db_or();

// Build the condition using the selected search fields
foreach ($style_options['search_fields'] as $field_alias) {
if (!empty($field_alias)) {

// Get the table and field names for the checked field.
if (empty($this->view->field[$field_alias]->field_info)) {
$field = $this->view->query->fields[$this->view->field[$field_alias]->field_alias];
}
else {
$this->view->query->add_field($this->view->field[$field_alias]->options['table'], $this->view->field[$field_alias]->real_field, $this->view->field[$field_alias]->options['field'], array());
$field = $this->view->query->fields[$this->view->field[$field_alias]->options['field']];
}
// Add an OR condition for the field
$conditions->condition($field['table'] . '.' . $field['field'], $value, 'LIKE');
}
}

$this->view->query->add_where(NULL, $conditions);
}

// Add an IN condition for validation.
if (!empty($options['ids'])) {
$this->view->query->add_where(NULL, $id_field, $options['ids']);
}

$this->view->set_items_per_page($options['limit']);
}

/**
* Extend the default validation.
*/
function validate() {
$errors = parent::validate();
// Verify that search fields are set up.
$style_options = $this->get_option('style_options');
if (!isset($style_options['search_fields'])) {
$errors[] = t('Display "@display" needs a selected search fields to work properly. See the settings for the Entity Reference list format.', array('@display' => $this->display->display_title));
}
else {
// Verify that the search fields used actually exist.
//$fields = array_keys($this->view->get_items('field'));
$fields = array_keys($this->handlers['field']);
foreach ($style_options['search_fields'] as $field_alias => $enabled) {
if ($enabled && !in_array($field_alias, $fields)) {
$errors[] = t('Display "@display" uses field %field as search field, but the field is no longer present. See the settings for the Entity Reference list format.', array('@display' => $this->display->display_title, '%field' => $field_alias));
}
}
}
return $errors;
}
}
35 changes: 35 additions & 0 deletions views/reference_plugin_row_fields.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php
/**
* @file
* Handler for reference_plugin_row_fields.
*/
class reference_plugin_row_fields extends views_plugin_row_fields {

function option_definition() {
$options = parent::option_definition();

$options['separator'] = array('default' => '-');

return $options;
}

/**
* Provide a form for setting options.
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);

// Expand the description of the 'Inline field' checkboxes.
$form['inline']['#description'] .= '<br />' . t("<strong>Note:</strong> In 'Entity Reference' displays, all fields will be displayed inline unless an explicit selection of inline fields is made here." );
}

function pre_render($row) {
// Force all fields to be inline by default.
if (empty($this->options['inline'])) {
$fields = $this->view->get_items('field', $this->display->id);
$this->options['inline'] = backdrop_map_assoc(array_keys($fields));
}

return parent::pre_render($row);
}
}
Loading