<?php
/**
 * @file
 * Provides primary Drupal hook implementations.
 *
 * This module allows field tables to be used as base tables with Views by
 * modifying the definitions of base tables, fields, and joins.
 *
 * On a field settings form, you may select:
 * - to expose the field table as a base table
 * - the columns of the field table to expose (e.g., entity_type and entity_id)
 *
 * Multiple "exposed" field tables may be related by a multi-column join using
 * the primary key columns. This module provides a programmatic interface to
 * trigger this relation. A user interface is provided by the combination of the
 * Field group and Field group views modules,
 *
 * One use case is to generate a table using columns from one or more field
 * tables. As the field tables are treated as standard base tables, the Field
 * API handling of the "field" is not invoked. Thus, by default, the raw value
 * in each column of the field table is displayed.
 *
 * By relating field tables, the individual columns of each table function as if
 * they were part of a single table.
 *
 * @author Jim Berry ("solotandem", http://drupal.org/user/240748)
 */

/**
 * Implements hook_field_info_alter().
 */
function views_field_field_info_alter(&$info) {
  // Add a setting to all field types.
  foreach ($info as $field_type => $field_type_info) {
    $info[$field_type]['settings'] += array(
      'views_base_table' => FALSE,
      'views_base_columns' => array(),
    );
  }
}

/**
 * Implements hook_form_FORM_ID_alter(): field_ui_field_settings_form.
 */
function views_field_form_field_ui_field_settings_form_alter(&$form, &$form_state) {
  $form['#field'] = field_info_field($form['field']['field_name']['#value']);
  views_field_form_field_ui_field_edit_form_alter($form, $form_state);
}

/**
 * Implements hook_form_FORM_ID_alter(): field_ui_field_edit_form.
 */
function views_field_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
  $field = $form['#field'];
  $settings = $field['settings'];

  // Handle fields without existing settings.
  if (isset($form['field']['settings']['#markup'])) {
    $form['field']['settings'] = array();
  }

  // Allow user to expose this field to views as a base table.
  $form['field']['settings']['views_base_table'] = array(
    '#type' => 'checkbox',
    '#title' => t('Expose as base table'),
    '#default_value' => $settings['views_base_table'],
    '#description' => t('Expose the storage table for this field to the Views module as a base table.'),
  );
  // Allow user to select the columns of the field table to expose to views.
  $columns = array();
  foreach ($field['columns'] as $column_name => $attributes) {
    $columns[] = $column_name;
  }
  $columns = array_merge($columns, array('entity_type', 'bundle', 'entity_id', 'revision_id', 'language', 'delta', 'deleted'));
  $form['field']['settings']['views_base_columns'] = array(
    '#type' => 'select',
    '#title' => t('Columns to expose'),
    '#default_value' => $settings['views_base_columns'],
    '#options' => drupal_map_assoc($columns),
    '#description' => t('Expose the selected columns of the storage table for this field to the Views module as fields.'),
    '#multiple' => TRUE,
    '#size' => min(12, count($columns)),
  );
}

/**
 * Implements hook_views_api().
 */
function views_field_views_api() {
  return array(
    'api' => '3.0',
  );
}

/**
 * Implements hook_field_views_data_alter().
 */
function views_field_field_views_data_alter(&$data, $field, $module) {
  if (empty($field['settings']['views_base_table']) || empty($field['settings']['views_base_columns'])) {
    return;
  }

  $base_tables = array(
    'field_data_' . $field['field_name'],
    'field_revision_' . $field['field_name'],
  );
  foreach ($base_tables as $base_table) {
    if (isset($data[$base_table])) {
      module_load_include('inc', 'views_field');
      views_field_add_base_table($data, $field, $module, $base_table);
    }
  }
}
