field_extractor.module in Field Extractor 7
Provides a formatter that displays a field from the referenced entities.
File
field_extractor.moduleView source
<?php
/**
* @file
* Provides a formatter that displays a field from the referenced entities.
*/
/**
* Implements hook_views_api().
*/
function field_extractor_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'field_extractor') . '/views',
);
}
/**
* Implements hook_field_formatter_info().
*/
function field_extractor_field_formatter_info() {
$formatters = array(
'field_extractor' => array(
'label' => t('Field Extractor'),
'field types' => array(
'commerce_product_reference',
'entityreference',
'taxonomy_term_reference',
),
'module' => 'field_extractor',
'settings' => array(
'field_name' => '',
'formatter' => '',
'settings' => array(),
),
),
);
return $formatters;
}
/**
* Implements hook_field_formatter_settings_form().
*/
function field_extractor_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$settings = field_extractor_settings($field, $instance);
$display = $instance['display'][$view_mode];
$extractor_settings = $display['settings'];
// If the form was rebuilt via AJAX, use the values from the form state.
if (!empty($form_state['values']['fields'][$field['field_name']]['settings_edit_form'])) {
$defaults = array(
'field_name' => '',
'formatter' => '',
'settings' => array(),
);
$extractor_settings = $form_state['values']['fields'][$field['field_name']]['settings_edit_form']['settings'] + $defaults;
}
// Build a list of available fields for all bundles available to the field.
$fields = array();
foreach (field_info_instances($settings['entity_type']) as $bundle => $instances) {
if (in_array($bundle, $settings['bundles'])) {
foreach ($instances as $field_name => $field_instance) {
$fields[$field_name] = $field_name;
}
}
}
// If no field has been selected yet, or the current one is no longer
// available, default to the first one.
if (empty($extractor_settings['field_name']) || !isset($fields[$extractor_settings['field_name']])) {
$field_names = array_keys($fields);
$extractor_settings['field_name'] = reset($field_names);
}
// Determine if the formatter settings are being embedded inside Views.
// That is not supported.
if ($instance['entity_type'] == 'ctools' && $instance['bundle'] == 'ctools') {
return array(
'#markup' => t("This formatter can't be used inside Views. Use the provided Views field instead."),
);
}
$id = 'field-extractor-' . $instance['entity_type'] . '-' . $field['field_name'];
$element = array();
$element['#prefix'] = '<div id="' . $id . '">';
$element['#suffix'] = '</div>';
$element['field_name'] = array(
'#type' => 'select',
'#title' => t('Field'),
'#options' => $fields,
'#default_value' => $extractor_settings['field_name'],
'#ajax' => array(
'wrapper' => $id,
'callback' => 'field_extractor_ajax',
),
// Data for the #ajax callback.
'#reference_field' => $field['field_name'],
);
$selected_field = field_info_field($extractor_settings['field_name']);
$formatters = _field_extractor_formatters($selected_field['type']);
// No recursion.
unset($formatters['field_extractor']);
// If no formatter has been selected yet, or doesn't fit the current field,
// default to the first one.
if (empty($extractor_settings['formatter']) || !isset($formatters[$extractor_settings['formatter']])) {
$formatter_names = array_keys($formatters);
$extractor_settings['formatter'] = reset($formatter_names);
}
$element['formatter'] = array(
'#type' => 'select',
'#title' => t('Formatter'),
'#options' => $formatters,
'#default_value' => $extractor_settings['formatter'],
'#ajax' => array(
'wrapper' => $id,
'callback' => 'field_extractor_ajax',
),
// Data for the #ajax callback.
'#reference_field' => $field['field_name'],
);
$formatter = field_info_formatter_types($extractor_settings['formatter']);
$formatter_settings = $extractor_settings['settings'] + field_info_formatter_settings($extractor_settings['formatter']);
// Provide an instance array for hook_field_formatter_settings_form().
ctools_include('fields');
$instance = ctools_fields_fake_field_instance($extractor_settings['field_name'], '_dummy', $formatter, $formatter_settings);
// Store the settings in a '_dummy' view mode.
$instance['display']['_dummy'] = array(
'type' => $extractor_settings['formatter'],
'settings' => $formatter_settings,
);
// Get the settings form.
$settings_form = array(
'#value' => array(),
);
$function = $formatter['module'] . '_field_formatter_settings_form';
if (function_exists($function)) {
$settings_form = $function($selected_field, $instance, '_dummy', $element, $form_state);
}
$element['settings'] = array(
'#type' => 'fieldset',
'#title' => t('Formatter settings'),
) + $settings_form;
return $element;
}
/**
* #ajax callback: Returns the updated formatter settings form.
*/
function field_extractor_ajax($form, $form_state) {
$field_name = $form_state['triggering_element']['#reference_field'];
return $form['fields'][$field_name]['format']['settings_edit_form']['settings'];
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function field_extractor_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
if (!empty($settings['field_name']) && !empty($settings['formatter'])) {
$field = field_info_field($settings['field_name']);
$formatters = _field_extractor_formatters($field['type']);
$formatter = $formatters[$settings['formatter']];
return t('Field: %field_name. Formatter: %formatter', array(
'%field_name' => $settings['field_name'],
'%formatter' => $formatter,
));
}
else {
return t('No field selected.');
}
}
/**
* Implements hook_field_formatter_view().
*/
function field_extractor_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$settings = field_extractor_settings($field, $instance);
$extractor_settings = $display['settings'];
// The formatter hasn't been configured, abort.
if (empty($extractor_settings['field_name']) || empty($extractor_settings['formatter'])) {
return array();
}
// Extract the entity IDs from the items array and load the entities.
$entity_ids = array();
foreach ($items as $item) {
$entity_ids[] = $item[$settings['column']];
}
// No entities found, nothing to do here.
if (empty($entity_ids)) {
return array();
}
// Retrieve the weight and the label from the view mode settings.
$instance_display = array(
'label' => $display['label'],
'weight' => $display['weight'],
);
// Build an alterable EFQ.
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', $settings['entity_type'])
->entityCondition('entity_id', $entity_ids)
->addTag('field_extractor')
->addMetaData('field_extractor_entity', $entity);
$results = $query
->execute();
if (empty($results[$settings['entity_type']])) {
return array();
}
$entities = entity_load($settings['entity_type'], array_keys($results[$settings['entity_type']]));
return field_extractor_build_element($entities, $settings['entity_type'], $extractor_settings, $instance_display);
}
/**
* Implements hook_entity_query_alter().
*/
function field_extractor_entity_query_alter($query) {
if (!empty($query->tags) && isset($query->tags['field_extractor'])) {
switch ($query->entityConditions['entity_type']['value']) {
case 'commerce_product':
case 'node':
$query
->propertyCondition('status', 1);
}
}
}
/**
* Builds a renderable array representing the extracted field.
*
* @param $entities
* An array of entities from which the field data will be taken.
* @param $entity_type
* The type of passed $entities.
* @param $extractor_settings
* An array of settings ('field_name', 'formatter', 'settings', 'langcode').
* @param $instance_display
* The display settings to use, as found in the 'display' entry of instance
* definitions.
*/
function field_extractor_build_element($entities, $entity_type, $extractor_settings, $instance_display = array()) {
$field_name = $extractor_settings['field_name'];
$formatter_name = $extractor_settings['formatter'];
$formatter_settings = $extractor_settings['settings'];
$element = array();
foreach ($entities as $loaded_entity) {
if (!empty($loaded_entity->{$field_name})) {
$formatter = field_info_formatter_types($formatter_name);
$field_display = $instance_display + array(
'label' => 'hidden',
'type' => $formatter_name,
'settings' => $formatter_settings + $formatter['settings'],
'module' => $formatter['module'],
'weight' => 0,
);
// Call the formatter for the selected field on the loaded entity.
$field_element = field_view_field($entity_type, $loaded_entity, $field_name, $field_display);
// Use the first returned element as the base, append all next.
if (empty($element)) {
$element = $field_element;
}
else {
foreach (element_children($field_element) as $key) {
if (!empty($field_element['#items'])) {
// This item already exists, skip it.
if (in_array($field_element['#items'][$key], $element['#items'], TRUE)) {
continue;
}
$element['#items'][] = $field_element['#items'][$key];
}
$element[] = $field_element[$key];
}
}
}
}
return $element;
}
/**
* Introspects field and instance settings, and determines the correct settings
* for the functioning of the formatter.
*
* Settings:
* - entity_type - The entity_type being loaded.
* - bundles - Bundles available to be referenced.
* - column - The name of the ref. field column that stores the entity id.
*/
function field_extractor_settings($field, $instance) {
$settings = array(
'entity_type' => NULL,
'bundles' => array(),
'column' => NULL,
);
if ($field['type'] == 'commerce_product_reference') {
$settings['entity_type'] = 'commerce_product';
$settings['column'] = 'product_id';
// Make sure 'referenceable_types' is set.
$instance['settings'] += array(
'referenceable_types' => array(),
);
// The product reference field has its bundle setting, use it.
$types = array_filter($instance['settings']['referenceable_types']);
if (!empty($types)) {
$settings['bundles'] = array_values($types);
}
}
elseif ($field['type'] == 'entityreference') {
$settings['entity_type'] = $field['settings']['target_type'];
$settings['column'] = 'target_id';
if (!empty($field['settings']['handler_settings']['target_bundles'])) {
$bundles = array_filter($field['settings']['handler_settings']['target_bundles']);
if (!empty($bundles)) {
$settings['bundles'] = array_values($bundles);
}
}
}
elseif ($field['type'] == 'taxonomy_term_reference') {
$settings['entity_type'] = 'taxonomy_term';
$settings['column'] = 'tid';
}
// By default, allow entities of all bundles to be created.
if (empty($settings['bundles'])) {
$info = entity_get_info($settings['entity_type']);
if (!empty($info['bundles'])) {
foreach ($info['bundles'] as $bundle_name => $bundle_info) {
$settings['bundles'][] = $bundle_name;
}
}
}
return $settings;
}
/**
* Helper function: Return an array of formatters for a field type.
*
* Borrowed from views.
*/
function _field_extractor_formatters($field_type = NULL) {
$options =& drupal_static(__FUNCTION__);
if (!isset($options)) {
$field_types = field_info_field_types();
$options = array();
foreach (field_info_formatter_types() as $name => $formatter) {
foreach ($formatter['field types'] as $formatter_field_type) {
// Check that the field type exists.
if (isset($field_types[$formatter_field_type])) {
$options[$formatter_field_type][$name] = $formatter['label'];
}
}
}
}
if ($field_type) {
return !empty($options[$field_type]) ? $options[$field_type] : array();
}
return $options;
}
Functions
Name![]() |
Description |
---|---|
field_extractor_ajax | #ajax callback: Returns the updated formatter settings form. |
field_extractor_build_element | Builds a renderable array representing the extracted field. |
field_extractor_entity_query_alter | Implements hook_entity_query_alter(). |
field_extractor_field_formatter_info | Implements hook_field_formatter_info(). |
field_extractor_field_formatter_settings_form | Implements hook_field_formatter_settings_form(). |
field_extractor_field_formatter_settings_summary | Implements hook_field_formatter_settings_summary(). |
field_extractor_field_formatter_view | Implements hook_field_formatter_view(). |
field_extractor_settings | Introspects field and instance settings, and determines the correct settings for the functioning of the formatter. |
field_extractor_views_api | Implements hook_views_api(). |
_field_extractor_formatters | Helper function: Return an array of formatters for a field type. |