field_collection_table.module in Field Collection Table 7
Module implementing a field-collection table formatter.
File
field_collection_table.moduleView source
<?php
/**
* @file
* Module implementing a field-collection table formatter.
*/
/**
* Implements hook_field_formatter_info().
*/
function field_collection_table_field_formatter_info() {
return array(
'field_collection_table_view' => array(
'label' => t('Table of field collection items'),
'field types' => array(
'field_collection',
),
'settings' => array(
'edit' => t('Edit'),
'delete' => t('Delete'),
'add' => t('Add'),
'description' => TRUE,
'view_mode' => 'full',
'hide_empty' => FALSE,
'empty' => TRUE,
'caption' => NULL,
'orientation' => 'columns',
'header_column' => 'none',
),
),
);
}
/**
* Implements hook_field_formatter_view().
*/
function field_collection_table_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
$settings = $display['settings'];
if (empty($items) && !empty($settings['hide_empty'])) {
return $element;
}
if ($settings['orientation'] === 'columns') {
_field_collection_table_column_mode($element, $settings, $entity_type, $entity, $field, $instance, $langcode, $items, $display);
}
if ($settings['orientation'] === 'rows') {
_field_collection_table_row_mode($element, $settings, $entity_type, $entity, $field, $instance, $langcode, $items, $display);
}
field_collection_field_formatter_links($element, $entity_type, $entity, $field, $instance, $langcode, $items, $display);
return $element;
}
/**
* Helper function to build the table in column mode.
*/
function _field_collection_table_column_mode(&$element, $settings, $entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$view_mode = !empty($display['settings']['view_mode']) ? $display['settings']['view_mode'] : 'default';
$header = array();
$field_names = array();
foreach (field_info_instances('field_collection_item', $field['field_name']) as $field_collection_item) {
$item_view_mode = !empty($field_collection_item['display'][$view_mode]) ? $view_mode : 'default';
if ($field_collection_item['display'][$item_view_mode]['type'] !== 'hidden') {
$weight = $field_collection_item['display'][$item_view_mode]['weight'];
$field_names[$weight] = $field_collection_item['field_name'];
if ($field_collection_item['display'][$item_view_mode]['label'] !== 'hidden') {
$header[$weight] = array(
'data' => module_exists('i18n_field') ? i18n_field_translate_property($field_collection_item, 'label') : $field_collection_item['label'],
'class' => drupal_html_class($field_names[$weight]),
);
}
else {
$header[$weight] = '';
}
}
}
if (module_exists('ds')) {
$fields_ds = ds_get_fields('field_collection_item');
$fields_ds_settings = ds_get_field_settings('field_collection_item', $field['field_name'], $view_mode);
foreach ($fields_ds_settings as $name => $ds_settings) {
if (isset($fields_ds[$name])) {
$weight = $ds_settings['weight'];
$field_names[$weight] = $name;
$header[$weight] = array(
'data' => $ds_settings['label'] !== 'hidden' ? $fields_ds[$name]['title'] : NULL,
'class' => drupal_html_class($name),
);
}
elseif (in_array($name, $field_names)) {
$weight = array_search($name, $field_names);
}
// Allow to override field label using DS field format settings.
if (isset($weight, $ds_settings['formatter_settings']['ft']['lb'])) {
$header[$weight]['data'] = t(check_plain($ds_settings['formatter_settings']['ft']['lb']));
}
}
}
ksort($header);
ksort($field_names);
$rows = array();
foreach ($items as $delta => $item) {
$field_collection = field_collection_field_get_entity($item);
if (empty($field_collection)) {
continue;
}
$view = $field_collection
->view($view_mode);
$content = $view['field_collection_item'][$field_collection
->identifier()];
$column = array();
foreach ($field_names as $field_name) {
$cell = array(
'class' => drupal_html_class($field_name),
'data' => array(),
);
if (empty($contents[$field_name])) {
$cell['data'] = array(
'#markup' => '<span class="empty-field"></span>',
'#empty' => TRUE,
);
}
else {
$cell['data'] = $content[$field_name];
$cell['data-title'] = $content[$field_name]['#title'];
}
$column[] = $cell;
}
$links = array(
'#theme' => 'links',
'#theme_wrapper' => 'item_list',
'#attributes' => array(
'class' => array(
'field-collection-view-links',
),
),
);
foreach (array(
'edit',
'delete',
) as $op) {
if (!empty($settings[$op]) && !(module_exists('field_permissions') && !user_access($op . ' ' . $field['field_name'])) && entity_access($op === 'edit' ? 'update' : $op, 'field_collection_item', $field_collection)) {
$links['#links'][$op] = array(
'title' => t($settings[$op]),
'href' => $field_collection
->path() . '/' . $op,
'query' => drupal_get_destination(),
);
$header['operations'] = t('Operations');
}
}
if (!empty($links['#links'])) {
$column[] = array(
'data' => $links,
'class' => 'field-operations',
);
}
$rows[] = array(
'data' => $column,
'class' => array(
'field-collection-item',
),
);
}
// Remove header if all labels are hidden.
if (!array_filter($header)) {
$header = array();
}
$element[0] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#caption' => !empty($settings['caption']) ? t($settings['caption']) : NULL,
'#attributes' => array(
'class' => array(
'field-collection-table-view',
drupal_clean_css_identifier('view-mode-' . $view_mode),
),
),
);
if (!empty($settings['empty'])) {
$element[0]['#theme'] = 'table__field_collection_table';
$element[0]['#settings']['empty'] = TRUE;
}
return $element;
}
/**
* Helper function to build the table in row mode.
*/
function _field_collection_table_row_mode(&$element, $settings, $entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$view_mode = !empty($display['settings']['view_mode']) ? $display['settings']['view_mode'] : 'default';
$labels = array();
$field_names = array();
foreach (field_info_instances('field_collection_item', $field['field_name']) as $field_collection_item) {
$item_view_mode = !empty($field_collection_item['display'][$view_mode]) ? $view_mode : 'default';
if ($field_collection_item['display'][$item_view_mode]['type'] !== 'hidden') {
$weight = $field_collection_item['display'][$item_view_mode]['weight'];
$field_names[$weight] = $field_collection_item['field_name'];
$labels[$field_collection_item['field_name']] = module_exists('i18n_field') ? i18n_field_translate_property($field_collection_item, 'label') : $field_collection_item['label'];
}
}
if (module_exists('ds')) {
$fields_ds = ds_get_fields('field_collection_item');
$fields_ds_settings = ds_get_field_settings('field_collection_item', $field['field_name'], $view_mode);
foreach ($fields_ds_settings as $name => $ds_settings) {
if (isset($fields_ds[$name])) {
$weight = $ds_settings['weight'];
$labels[$name] = $ds_settings['label'] !== 'hidden' ? $fields_ds[$name]['title'] : NULL;
$field_names[$weight] = $name;
}
// Allow to override field label using DS field format settings.
if (isset($weight, $ds_settings['formatter_settings']['ft']['lb'])) {
$labels[$name] = t(check_plain($ds_settings['formatter_settings']['ft']['lb']));
}
}
}
ksort($field_names);
$header = array();
if ($settings['header_column'] !== 'none') {
$header = array(
array(
'class' => array(
'field-label',
),
'data' => $labels[$settings['header_column']],
),
);
}
$rows = array();
foreach ($items as $delta => $item) {
$field_collection = field_collection_field_get_entity($item);
if (empty($field_collection)) {
continue;
}
$view = $field_collection
->view();
$content = $view['field_collection_item'][$field_collection
->identifier()];
foreach ($field_names as $field_name) {
if (isset($content[$field_name])) {
$content[$field_name]['#label_display'] = 'hidden';
}
else {
$content[$field_name] = array(
'#markup' => '<span class="empty-field"></span>',
'#empty' => TRUE,
);
}
if ($settings['header_column'] === $field_name) {
unset($labels[$field_name]);
$header[] = array(
'data' => $content[$field_name],
);
continue;
}
$rows[$field_name]['data'][$delta] = array(
'data' => $content[$field_name],
);
$rows[$field_name]['class'] = array(
drupal_html_class($field_name),
);
$links = array(
'#theme' => 'links',
'#theme_wrapper' => 'item_list',
'#attributes' => array(
'class' => array(
'field-collection-view-links',
),
),
);
foreach (array(
'edit',
'delete',
) as $op) {
if (!empty($settings[$op]) && field_collection_item_access($op === 'edit' ? 'update' : $op, $field_collection)) {
$links['#links'][$op] = array(
'title' => $settings[$op],
'href' => $field_collection
->path() . '/' . $op,
'query' => drupal_get_destination(),
);
}
}
if (!empty($links['#links'])) {
$operations[$delta] = array(
'data' => $links,
'class' => 'field-operations',
);
}
}
}
foreach ($labels as $field_name => $data) {
array_unshift($rows[$field_name]['data'], array(
'class' => 'field-label',
'data' => $data,
));
}
if (!empty($operations)) {
array_unshift($operations, array(
'class' => array(
'field-label',
),
'data' => t('Operations'),
));
$rows['operations'] = array(
'class' => array(
'operations',
),
'data' => $operations,
);
}
$element[0] = array(
'#theme' => 'table',
'#header' => $header,
'#rows' => $rows,
'#caption' => !empty($settings['caption']) ? t($settings['caption']) : NULL,
'#attributes' => array(
'class' => array(
'field-collection-table-view',
drupal_clean_css_identifier('view-mode-' . $view_mode),
),
),
);
if (!empty($settings['empty'])) {
$element[0]['#theme'] = 'table__field_collection_table';
$element[0]['#settings']['empty'] = TRUE;
}
}
/**
* Implements hook_field_formatter_settings_form().
*/
function field_collection_table_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$element = field_collection_field_formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
$field_collections = field_info_instances('field_collection_item', $instance['field_name']);
$field_options = array(
'none' => t('None'),
);
foreach ($field_collections as $key => $value) {
$field_options[$key] = $value['label'];
}
if (!empty($element['view_mode'])) {
$element['view_mode']['#description'] = t('Used to determine which fields should be displayed.');
}
$element['hide_empty'] = array(
'#type' => 'checkbox',
'#title' => t('Hide empty collection'),
'#default_value' => $settings['hide_empty'],
'#description' => t('If enabled, nothing will be displayed for an empty collection (not even the add link).'),
);
$element['empty'] = array(
'#type' => 'checkbox',
'#title' => t('Hide empty columns'),
'#description' => t('If checked, hides empty table columns.'),
'#default_value' => $settings['empty'],
);
$element['caption'] = array(
'#type' => 'textfield',
'#title' => t('Table caption'),
'#description' => t('Displayed in the caption element above the table'),
'#default_value' => $settings['caption'],
);
$element['orientation'] = array(
'#type' => 'select',
'#title' => t('Orientation'),
'#description' => t('Set the orientation of the table'),
'#options' => array(
'columns' => t('Columns'),
'rows' => t('Rows'),
),
'#default_value' => $settings['orientation'],
);
$element['header_column'] = array(
'#type' => 'select',
'#title' => t('Header field'),
'#description' => t('The selected field value will be used as the horizontal table header'),
'#options' => $field_options,
'#states' => array(
'visible' => array(
':input[name="fields[field_fc][settings_edit_form][settings][orientation]"]' => array(
'value' => 'rows',
),
),
),
);
return $element;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function field_collection_table_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$output = field_collection_field_formatter_settings_summary($field, $instance, $view_mode);
if ($display['type'] === 'field_collection_table_view') {
$output .= '<br>';
$output .= !empty($settings['hide_empty']) ? t('Empty collections: Hidden') : t('Empty collections: Shown');
$output .= '<br>';
$output .= !empty($settings['empty']) ? t('Empty columns: Hidden') : t('Empty columns: Shown');
$output .= !empty($settings['caption']) ? '<br>' . t('Caption: %caption', array(
'%caption' => t($settings['caption']),
)) : '';
$orientations = array(
'columns' => t('Column'),
'rows' => t('Row'),
);
$output .= '<br />';
$output .= !empty($settings['empty']) ? t('Empty columns: Hidden') : t('Empty columns: Shown');
if (isset($settings['orientation'])) {
$output .= '<br />';
$output .= t('Format fields as <strong>!orientation</strong>.', array(
'!orientation' => $orientations[$settings['orientation']],
));
}
if (isset($settings['orientation']) && $settings['orientation'] === 'rows') {
$output .= '<br />';
if (isset($settings['header_column']) && $settings['header_column'] !== 'none') {
$output .= '<br />';
$output .= t('Field @field value is used as the header', array(
'@field' => $settings['header_column'],
));
}
}
}
return $output;
}
/**
* Implements hook_theme().
*/
function field_collection_table_theme($existing, $type, $theme, $path) {
$base = array(
'file' => 'theme.inc',
'path' => $path . '/theme',
);
return array(
'field_collection_table_multiple_value_field' => $base + array(
'render element' => 'element',
),
'field_collection_table_multiple_value_fields' => $base + array(
'render element' => 'element',
),
'table__field_collection_table' => $base + array(
'variables' => array(
'header' => NULL,
'rows' => NULL,
'attributes' => array(),
'caption' => NULL,
'colgroups' => array(),
'sticky' => TRUE,
'empty' => '',
'settings' => array(),
),
),
);
}
/**
* Implements hook_field_attach_form().
*/
function field_collection_table_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
// Host entity edit.
foreach (field_info_instances($entity_type, $bundle) as $field_name => $instance) {
if (isset($form[$field_name]) && $instance['widget']['type'] === 'field_collection_table') {
$language = $form[$field_name]['#language'];
$form[$field_name][$language]['#theme'] = 'field_collection_table_multiple_value_fields';
$form[$field_name][$language]['#custom_settings'] = $instance['widget']['settings'];
$form[$field_name][$language]['#pre_render'][] = 'field_collection_table_pre_render_multiple_fields';
}
$field = field_info_field($field_name);
if ($field['type'] === 'field_collection' && isset($form[$field_name]) && $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed']) && $instance['widget']['type'] === 'field_collection_table' && field_access('edit', $field, $entity_type)) {
$element_langcode = $form[$field_name]['#language'];
$element_wrapper = $form[$field_name][$element_langcode]['add_more']['#ajax']['wrapper'];
for ($i = 0; $i <= $form[$field_name][$element_langcode]['#max_delta']; $i++) {
if (isset($form[$field_name][$element_langcode][$i]['remove_button'])) {
$form[$field_name][$element_langcode][$i]['remove_button']['#ajax']['wrapper'] = $element_wrapper;
}
}
}
}
// Individual field collection item edit.
if ($entity_type === 'field_collection_item') {
$instance = $entity
->instanceInfo();
if ($instance['widget']['type'] === 'field_collection_table') {
$form['#theme'] = 'field_collection_table_multiple_value_field';
$form['#pre_render'][] = 'field_collection_table_pre_render_field';
}
}
}
/**
* Callback for #pre_render for a single row, hide the titles for each field.
*/
function field_collection_table_pre_render_field($element) {
if (isset($element['#entity_type'], $element['#bundle'])) {
foreach (field_info_instances($element['#entity_type'], $element['#bundle']) as $field_name => $instance) {
if (empty($element[$field_name])) {
continue;
}
$field =& $element[$field_name];
$language = $field['#language'];
if (isset($field[$language])) {
// Set the most common places for a title to display invisible.
$field['#title_display'] = 'invisible';
$field[$language]['#title_display'] = 'invisible';
$children = element_children($field[$language]);
if ($children) {
foreach ($children as $child) {
if (array_key_exists('#type', $field[$language][$child]) && !in_array($field[$language][$child]['#type'], [
'radio',
'checkbox',
])) {
$field[$language][$child]['#title_display'] = 'invisible';
}
$field[$language][$child]['value']['#title_display'] = 'invisible';
}
}
}
else {
$field['#label_display'] = 'hidden';
}
}
}
return $element;
}
/**
* Callback for #pre_render for multiple rows, hide the titles for each field.
*/
function field_collection_table_pre_render_multiple_fields($element) {
foreach (element_children($element) as $key) {
// Skip the 'add_more' element.
if (is_numeric($key)) {
$element[$key] = field_collection_table_pre_render_field($element[$key]);
}
}
return $element;
}
/**
* Implements hook_field_widget_info().
*/
function field_collection_table_field_widget_info() {
return array(
'field_collection_table' => array(
'label' => t('Table'),
'field types' => array(
'field_collection',
),
'settings' => array(
'nodragging' => FALSE,
'hide_title' => FALSE,
),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
'default value' => FIELD_BEHAVIOR_NONE,
),
),
);
}
/**
* Implements hook_field_widget_form().
*/
function field_collection_table_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
// Changing this variable so we build the form from field_collection_embed.
$instance['widget']['type'] = 'field_collection_embed';
$element = field_collection_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
return $element;
}
/**
* Implements hook_field_widget_settings_form().
*/
function field_collection_table_field_widget_settings_form($field, $instance) {
$widget = $instance['widget'];
$settings = $widget['settings'];
$form['nodragging'] = array(
'#type' => 'checkbox',
'#title' => t('Disable drag and drop'),
'#description' => t('If checked, users cannot rearrange the rows.'),
'#default_value' => $settings['nodragging'],
'#weight' => 2,
);
$form['hide_title'] = array(
'#type' => 'checkbox',
'#title' => t('Hide title'),
'#description' => t('If checked, the field title will be hidden.'),
'#default_value' => $settings['hide_title'],
'#weight' => 3,
);
return $form;
}