You are here

multifield_table.module in Multifield table 7

Provides a table formatter and widget for multifield field types.

File

multifield_table.module
View source
<?php

/**
 * @file
 * Provides a table formatter and widget for multifield field types.
 */

/**
 * Implements hook_field_formatter_info().
 */
function multifield_table_field_formatter_info() {
  $info = array();
  $multifields = multifield_load_all();
  if (!empty($multifields)) {
    $info['multifield_table'] = array(
      'label' => t('Table'),
      'field types' => array_merge(array(
        'multifield',
      ), array_keys($multifields)),
      'settings' => array(
        'view_mode' => 'default',
        'header_type' => 'sticky',
      ),
    );
  }
  return $info;
}

/**
 * Implements hook_field_formatter_settings().
 */
function multifield_table_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $element = multifield_field_formatter_settings_form($field, $instance, $view_mode, $form, $form_state);
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $element['header_type'] = array(
    '#type' => 'select',
    '#title' => t('Table header type'),
    '#options' => array(
      'sticky' => t('Sticky table header'),
      'normal' => t('Normal table header (not sticky)'),
      'none' => t('No table header'),
    ),
    '#default_value' => isset($settings['header_type']) ? $settings['header_type'] : 'sticky',
  );
  return $element;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function multifield_table_field_formatter_settings_summary($field, $instance, $view_mode) {
  $summary = multifield_field_formatter_settings_summary($field, $instance, $view_mode);
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $settings += array(
    'header_type' => 'sticky',
  );
  switch ($settings['header_type']) {
    case 'sticky':
      $summary .= "<br />" . t('Use sticky header');
      break;
    case 'normal':
      $summary .= "<br />" . t('Use normal header (not sticky)');
      break;
    case 'none':
      $summary .= "<br />" . t('Do not use a table header');
      break;
  }
  return $summary;
}

/**
 * Implements hook_field_prepare_view().
 */
function multifield_table_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $display = NULL) {
  return multifield_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, $items, $display);
}

/**
 * Implements hook_field_formatter_view().
 */
function multifield_table_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  $settings = $display['settings'];
  if ($items) {
    $header = $rows = array();
    foreach ($items as $item) {

      // Generate the table header.
      if (!$header) {
        $instances = field_info_instances('multifield', $item['#pseudo_entity']->type);
        foreach ($instances as $name => $instance) {
          if ($instance['display'][$settings['view_mode']]['type'] != 'hidden') {
            $fields[$instance['display'][$settings['view_mode']]['weight']] = $name;
          }
        }
        ksort($fields);
        foreach ($fields as $subtype) {
          $header[$subtype] = array(
            'data' => $instances[$subtype]['label'],
            'class' => drupal_clean_css_identifier($subtype),
          );
        }
      }

      // Display field columns.
      $row = array();
      foreach ($fields as $subtype) {
        if ($cell = field_view_field('multifield', $item['#pseudo_entity'], $subtype, $settings['view_mode'], $langcode)) {
          $row[] = render($cell[0]);
        }
        else {
          $row[] = '';
        }
      }
      $rows[] = $row;
    }
    if ($rows) {
      $settings += array(
        'header_type' => 'sticky',
      );
      $element[0] = array(
        '#theme' => 'table',
        '#header' => $settings['header_type'] == 'none' ? array() : $header,
        '#rows' => $rows,
        '#sticky' => $settings['header_type'] == 'sticky',
      );
    }
  }
  return $element;
}

/**
 * Implements hook_theme().
 */
function multifield_table_theme($existing, $type, $theme, $path) {
  $base = array(
    'file' => 'theme.inc',
    'path' => $path . '/theme',
  );
  return array(
    'multifield_table_multiple_value_field' => $base + array(
      'render element' => 'element',
    ),
    'multifield_table_multiple_value_fields' => $base + array(
      'render element' => 'element',
    ),
    'table__multifield_table' => $base + array(
      'variables' => array(
        'header' => NULL,
        'rows' => NULL,
        'attributes' => array(),
        'caption' => NULL,
        'colgroups' => array(),
        'sticky' => TRUE,
        'empty' => '',
        'settings' => array(),
      ),
    ),
  );
}

/**
 * Implements hook_form_alter().
 */
function multifield_table_form_alter(&$form, &$form_state, $form_id) {

  // Host entity edit.
  if (isset($form['#entity_type']) && isset($form['#bundle'])) {
    foreach (field_info_instances($form['#entity_type'], $form['#bundle']) as $field_name => $instance) {
      if (isset($form[$field_name]) && $instance['widget']['type'] == 'multifield_table') {
        $language = $form[$field_name]['#language'];
        $element =& $form[$field_name][$language];
        if (isset($element['#cardinality']) && ($element['#cardinality'] > 1 || $element['#cardinality'] == FIELD_CARDINALITY_UNLIMITED)) {
          $element['#theme'] = 'multifield_table_multiple_value_fields';
          $element['#pre_render'][] = 'multifield_table_pre_render_multiple_fields';
        }
      }
    }
  }
}

/**
 * Callback for #pre_render for a single row, hide the titles for each field.
 */
function multifield_table_pre_render_field($element) {
  $multifield_info = field_info_field($element['#field_name']);
  foreach (multifield_type_get_subfields($multifield_info['type']) as $field_name) {
    if (empty($element[$field_name])) {
      continue;
    }
    $field =& $element[$field_name];
    $field_info = field_info_field($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';
      foreach (element_children($field[$language]) as $child) {
        $field[$language][$child]['#title_display'] = 'invisible';

        // Check the individual columns. Most commonly 'value'.
        foreach ($field_info['columns'] as $column => $column_info) {
          $field[$language][$child][$column]['#title_display'] = 'invisible';

          // The date module sometimes adds its own random titles inside value.
          if (in_array($field_info['type'], array(
            'date',
            'datestamp',
            'datetime',
          ))) {
            foreach (element_children($field[$language][$child][$column]) as $date_child) {
              $field[$language][$child][$column][$date_child]['#title_display'] = 'invisible';
            }
          }
        }
      }
    }
    else {
      $field['#label_display'] = 'hidden';
    }
  }
  return $element;
}

/**
 * Callback for #pre_render for multiple rows, hide the titles for each field.
 */
function multifield_table_pre_render_multiple_fields($element) {
  foreach (element_children($element) as $key) {

    // Skip the 'add_more' element.
    if (is_numeric($key)) {
      $element[$key] = multifield_table_pre_render_field($element[$key]);
    }
  }
  return $element;
}

/**
 * Implements hook_field_widget_info().
 */
function multifield_table_field_widget_info() {
  $multifields = multifield_load_all();
  if ($multifields) {
    return array(
      'multifield_table' => array(
        'label' => t('Table'),
        'field types' => array_merge(array(
          'multifield',
        ), array_keys($multifields)),
        'behaviors' => array(
          'multiple values' => FIELD_BEHAVIOR_DEFAULT,
          'default value' => FIELD_BEHAVIOR_DEFAULT,
        ),
      ),
    );
  }
}

/**
 * Implements hook_field_widget_form().
 */
function multifield_table_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  switch ($instance['widget']['type']) {
    case 'multifield_table':
      $instance['widget']['type'] = 'multifield_default';
      $element = multifield_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
      break;
  }
  return $element;
}