You are here

extra_field_description.module in Extra Field Description 7

Same filename and directory in other branches
  1. 8 extra_field_description.module

Main module functions for the extra_field_description module.

File

extra_field_description.module
View source
<?php

/**
 * @file
 * Main module functions for the extra_field_description module.
 */

/**
 * Define module path constant.
 */
define("EXTRA_FIELD_DESCRIPTION_MODULE_PATH", drupal_get_path('module', 'extra_field_description'));

/**
 * Implements hook_form_FORM_ID_alter().
 */
function extra_field_description_form_taxonomy_form_vocabulary_alter(&$form, &$form_state) {
  $ed_conf = variable_get('extra_field_description', array());
  $form['extra_description'] = array(
    '#type' => 'text_format',
    '#format' => 'full_html',
    '#title' => t('Taxonomy name extra description'),
    '#description' => t('This text will be displayed above name field.'),
    '#default_value' => !empty($ed_conf['taxonomy_term'][$form['#vocabulary']->machine_name]) ? $ed_conf['taxonomy_term'][$form['#vocabulary']->machine_name] : '',
  );
  $form['#submit'][] = 'extra_field_description_taxonomy_form_vocabulary_submit';
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function extra_field_description_form_node_type_form_alter(&$form, &$form_state) {
  $ed_conf = variable_get('extra_field_description', array());
  $form['submission']['extra_description'] = array(
    '#type' => 'text_format',
    '#format' => 'full_html',
    '#title' => t('Node title extra description'),
    '#description' => t('This text will be displayed above title field.'),
    '#default_value' => !empty($ed_conf['node'][$form['#node_type']->type]) ? $ed_conf['node'][$form['#node_type']->type] : '',
  );
  $form['#submit'][] = 'extra_field_description_node_type_form_submit';
}

/**
 * Taxonomy vocabulary form submit.
 */
function extra_field_description_taxonomy_form_vocabulary_submit($form, $form_state) {
  if (isset($form['extra_description'])) {
    $ed_conf = variable_get('extra_field_description', array());
    if (!empty($form_state['values']['extra_description'])) {
      $ed_conf['taxonomy_term'][$form_state['values']['machine_name']] = $form_state['values']['extra_description'];
    }
    else {
      unset($ed_conf['taxonomy_term'][$form_state['values']['machine_name']]);
    }
    variable_set('extra_field_description', $ed_conf);
  }
}

/**
 * Node type form submit.
 */
function extra_field_description_node_type_form_submit($form, $form_state) {
  if (isset($form['submission']['extra_description'])) {
    $ed_conf = variable_get('extra_field_description', array());
    if (!empty($form_state['values']['extra_description'])) {
      $ed_conf['node'][$form_state['values']['type']] = $form_state['values']['extra_description'];
    }
    else {
      unset($ed_conf['node'][$form_state['values']['type']]);
    }
    variable_set('extra_field_description', $ed_conf);
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function extra_field_description_form_field_ui_field_edit_form_alter(&$form, &$form_state) {

  // Check if we have access to extra fields.
  if (user_access('administer field prefix')) {

    // Append extra fields in field settings form.
    $form['instance']['extra_description'] = array(
      '#type' => 'fieldset',
      '#title' => t("Extra description settings"),
      '#weight' => -4,
    );
    $form['instance']['extra_description']['multiple'] = array(
      '#type' => 'checkbox',
      '#title' => t('For each line'),
      '#description' => t("If field is multiple and specified checkbox selected\n                          - extra description will be written above each field."),
      '#default_value' => !empty($form['#instance']['extra_description']['multiple']) ? $form['#instance']['extra_description']['multiple'] : 0,
    );
    $form['instance']['extra_description']['over_description'] = array(
      '#type' => 'text_format',
      '#format' => 'full_html',
      '#title' => t('Extra description'),
      '#description' => t("Extra description over the field.<br />Allowed HTML tags: @tags", array(
        '@tags' => _field_filter_xss_display_allowed_tags(),
      )),
      '#default_value' => !empty($form['#instance']['extra_description']['over_description']) ? $form['#instance']['extra_description']['over_description'] : '',
    );
  }
}

/**
 * Implements hook_field_attach_form().
 */
function extra_field_description_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
  $include_css = FALSE;

  // Process extra description on title/name fields.
  $ed_conf = variable_get('extra_field_description', array());
  if (in_array($entity_type, array(
    'node',
    'taxonomy_term',
  )) && !empty($ed_conf[$entity_type][$form['#bundle']])) {
    if ($entity_type == 'node' && !empty($form['title'])) {
      _extra_field_description_add_to_title($form['title'], $ed_conf[$entity_type][$form['#bundle']]);
      $include_css = TRUE;
    }
    elseif ($entity_type == 'taxonomy_term' && !empty($form['name'])) {
      _extra_field_description_add_to_title($form['name'], $ed_conf[$entity_type][$form['#bundle']]);
      $include_css = TRUE;
    }
  }

  // Process each field in the form.
  $field_instances = field_info_instances($entity_type, $form['#bundle']);
  foreach ($field_instances as $field_name => $instance) {
    $field = field_info_field($field_name);

    // Skip fields that are not in the $form_state.
    if (!isset($form_state['field'][$field_name])) {
      continue;
    }

    // Skip fields that are not setup correctly.
    if (!isset($form[$field_name][LANGUAGE_NONE])) {
      continue;
    }
    if (empty($instance['extra_description']['over_description'])) {
      continue;
    }

    // For better code readability below.
    $form_field =& $form[$field_name][LANGUAGE_NONE];
    $multi_field = $field['cardinality'] != '1';
    $multi_description = !empty($instance['extra_description']['multiple']);
    $description_text = $instance['extra_description']['over_description'];

    // Various field types put the field data in different places in
    // the FAPI array, sometimes on indexed sub-elements.
    if (!$multi_field) {
      if (isset($form_field[0]['value'])) {
        $form_field =& $form_field[0]['value'];
      }
      elseif (isset($form_field[0]['#type'])) {
        $form_field =& $form_field[0];
      }
    }

    // Checkbox and no matters here if it's multiple or not.
    if (isset($form_field['#type']) && $form_field['#type'] == 'checkbox') {
      _extra_field_description_add_to_checkbox($form_field, $description_text);
      $include_css = TRUE;
    }
    elseif (!$multi_field && !$multi_description) {
      _extra_field_description_add_to_title($form_field, $description_text);
      $include_css = TRUE;
    }
    elseif (!$multi_field && $multi_description) {

      // Special handling for field collections.
      if ($field['type'] == 'field_collection') {

        // In some cases the fieldset elements are at the top level.
        if (isset($form_field[0]['#title'])) {
          $element =& $form_field[0];
        }
        elseif (isset($form_field['#title'])) {
          $element =& $form_field;
        }
        if (isset($element['#type']) && $element['#type'] == 'fieldset') {
          _extra_field_description_add_to_description($element, $description_text);
          $include_css = TRUE;
        }
      }
      else {
        _extra_field_description_add_to_prefix($form_field, $description_text);
        $include_css = TRUE;
      }
    }
    elseif ($multi_field && !$multi_description) {
      _extra_field_description_add_to_title($form_field, $description_text);
      $include_css = TRUE;
    }
    elseif ($multi_field && $multi_description) {

      // Some fields claim to be "multi-fields" but then only have one form
      // element (such as term reference fields and list fields).
      if (isset($form_field['#entity_type'])) {
        if (isset($form_field['#title'])) {
          _extra_field_description_add_to_title($form_field, $description_text);
          $include_css = TRUE;
        }
        else {
          _extra_field_description_add_to_prefix($form_field, $description_text);
          $include_css = TRUE;
        }
      }
      elseif (isset($form_field[0]['#entity_type']) || isset($form_field[0]['value'])) {

        // Cache the subfield weight to speed up the loops
        // for field collections.
        $weight = FALSE;

        // Prepend the extra description to each field in the multiple section.
        foreach (element_children($form_field) as $index) {
          $element =& $form_field[$index];

          // Filter out child elements that aren't actual content fields.
          $element_array = array(
            'remove_button',
            '_weight',
            'add_more',
          );
          if (!in_array('' . $index, $element_array)) {

            // Some simple fields (integers, floats, etc) place their field
            // contents inside an array key called 'value'.
            if (isset($element['value'])) {
              _extra_field_description_add_to_prefix($element['value'], $description_text);
              $include_css = TRUE;
            }
            elseif (isset($element['#type'])) {
              _extra_field_description_add_to_prefix($element, $description_text);
              $include_css = TRUE;
            }
            elseif (isset($element['#entity_type']) && $element['#entity_type'] == 'field_collection_item') {

              // Find the first subfield by scanning for the field with the
              // lowest weight (we cache this value outside the outer loop
              // above for performance when a field collection has many
              // fields).
              if ($weight === FALSE) {
                foreach (element_children($form_field[$index]) as $subfield) {
                  if ($weight === FALSE || $weight > $form_field[$index][$subfield]['#weight']) {
                    $weight = $form_field[$index][$subfield]['#weight'];
                  }
                }
              }

              // Prepend the description text to this subfield.
              $form_field[$index]['extra_description'] = array(
                '#type' => 'markup',
                '#weight' => $weight - 1,
                '#markup' => theme('description_wrapper', array(
                  'raw_string' => $description_text,
                  'new_line' => TRUE,
                  'class' => 'faf',
                )),
              );
              $include_css = TRUE;
            }
          }
        }
      }
    }
  }

  // Include css.
  if ($include_css) {
    extra_field_description_include_css();
  }
}

/**
 * Helper function adds the extra description to the field prefix.
 */
function _extra_field_description_add_to_prefix(&$element, $description) {

  // Initialize the field prefix, if it doesnt already exist. It would be better
  // to use #prefix instead of #field_prefix, but this doesn't work for all
  // fields, namely managed_file type, because of a bug in Drupal core that
  // overwrites #prefix (https://drupal.org/node/1918630).
  if (!isset($element['#field_prefix'])) {
    $element['#field_prefix'] = '';
  }

  // Prepend the extra description to the prefix.
  $element['#field_prefix'] = theme('description_wrapper', array(
    'raw_string' => $description,
    'new_line' => TRUE,
  )) . $element['#field_prefix'];
}

/**
 * Helper function adds the extra description to the field title.
 */
function _extra_field_description_add_to_title(&$element, $description) {

  // Initialize the title field, if it doesn't already exist.
  if (!isset($element['#title'])) {
    $element['#title'] = '';
  }

  // Ensure the required marker in the field label shows up
  // *before* the extra description, not after it, by appending
  // it to the field title here, and then hijacking the required
  // status so it is not added again in the call to the original
  // label theme hook. This is really a horrible hack, but there
  // is no other way to do this without totally re-implementing
  // the entire theme_form_element function. Finally, in case
  // someone is implementing a theme template function and really
  // needs access to the original "real" value, we provide it
  // to the template in a #extra_description_required array key.
  if (!empty($element['#required'])) {
    $element['#title'] .= ' ' . theme('form_required_marker', array(
      'element' => $element,
    )) . ' ';
    $element['#required'] = FALSE;
    $element['#extra_description_required'] = TRUE;
  }
  $element['#title'] .= theme('description_wrapper', array(
    'raw_string' => $description,
    'new_line' => FALSE,
    'class' => 'with-title',
  ));
}

/**
 * Helper function adds the extra description to the checkbox field.
 *
 * Checkbox have should be processed in another way.
 */
function _extra_field_description_add_to_checkbox(&$element, $description) {

  // To append extra description to checkbox input we should append it in
  // form_element preprocess.
  // We can't use #field_prefix because it wrapped in span,
  // but extra_description in future can be full html markup.
  $element['#extra_description'] = theme('description_wrapper', array(
    'raw_string' => $description,
    'new_line' => FALSE,
    'class' => 'with-title',
  ));
}

/**
 * Form element preprocess.
 */
function extra_field_description_preprocess_form_element(&$vars) {

  // Append extra description exactly before checkbox input.
  if (!empty($vars['element']['#type']) && $vars['element']['#type'] == 'checkbox' && !empty($vars['element']['#extra_description'])) {
    $vars['element']['#children'] = $vars['element']['#extra_description'] . $vars['element']['#children'];
  }
}

/**
 * Helper function adds the extra description to a fieldset's description.
 */
function _extra_field_description_add_to_description(&$element, $description) {

  // Fist initialize the #description, if it doesn't already exist.
  if (!isset($element['#description'])) {
    $element['#description'] = '';
  }

  // Then append it.
  $element['#description'] .= theme('description_wrapper', array(
    'raw_string' => $description,
    'new_line' => TRUE,
    'class' => 'with-title',
  ));
}

/**
 * Implements hook_permission().
 */
function extra_field_description_permission() {
  return array(
    'administer field prefix' => array(
      'title' => t('Administer extra description'),
      'description' => t('Append or edit extra description.'),
    ),
  );
}

/**
 * Implements hook_theme().
 */
function extra_field_description_theme() {
  return array(
    'description_wrapper' => array(
      'variables' => array(
        'raw_string' => '',
        'new_line' => FALSE,
        'class' => array(),
      ),
    ),
  );
}

/**
 * Include css for anu administration theme.
 *
 * @param string $theme_name
 *   [optional] Set name of theme to include css: efd.[theme_name].css.
 */
function extra_field_description_include_css($theme_name = '') {

  // Include specified css.
  if ($theme_name) {
    $css = EXTRA_FIELD_DESCRIPTION_MODULE_PATH . "/css/efd.{$theme_name}.css";
    if (file_exists($css)) {

      // Include css.
      drupal_add_css($css);
    }
    return;
  }
  else {
    $admin_theme = variable_get('admin_theme', 0);

    // If admin theme specified.
    if ($admin_theme) {
      $css = EXTRA_FIELD_DESCRIPTION_MODULE_PATH . "/css/efd.{$admin_theme}.css";
      if (file_exists($css)) {

        // Include css.
        drupal_add_css($css);
      }
    }
    else {
      $theme_default = variable_get('theme_default', 'bartik');
      $css = EXTRA_FIELD_DESCRIPTION_MODULE_PATH . "/css/efd.{$theme_default}.css";
      if (file_exists($css)) {

        // Include css.
        drupal_add_css($css);
      }
    }
  }
}

/**
 * Wrapper for extra description.
 *
 * @param array $variables
 *   An associative array containing:
 *   - raw_string: Raw string, which need to wrap.
 *   - new_line: (optional) Set to TRUE, if need append new line
 *     character before.
 *   - class: (optional) Append class to wrapper. Use string for single class
 *     or array for few classes.
 *
 * @return string
 *   Wrapped HTML.
 */
function theme_description_wrapper(array $variables) {
  if ($variables['raw_string']) {
    if (is_string($variables['class'])) {
      $variables['class'] = array(
        $variables['class'],
      );
    }

    // Default classes.
    $default_class = array(
      'extra-description',
    );
    $variables['class'] = array_merge($variables['class'], $default_class);
    $class_string = implode(' ', $variables['class']);
    $html = "<div class='" . $class_string . "'>" . filter_xss($variables['raw_string'], _field_filter_xss_allowed_tags()) . "</div>";
    if ($variables['new_line']) {
      $html = "\n{$html}";
    }
    return $html;
  }
  return '';
}

Functions

Namesort descending Description
extra_field_description_field_attach_form Implements hook_field_attach_form().
extra_field_description_form_field_ui_field_edit_form_alter Implements hook_form_FORM_ID_alter().
extra_field_description_form_node_type_form_alter Implements hook_form_FORM_ID_alter().
extra_field_description_form_taxonomy_form_vocabulary_alter Implements hook_form_FORM_ID_alter().
extra_field_description_include_css Include css for anu administration theme.
extra_field_description_node_type_form_submit Node type form submit.
extra_field_description_permission Implements hook_permission().
extra_field_description_preprocess_form_element Form element preprocess.
extra_field_description_taxonomy_form_vocabulary_submit Taxonomy vocabulary form submit.
extra_field_description_theme Implements hook_theme().
theme_description_wrapper Wrapper for extra description.
_extra_field_description_add_to_checkbox Helper function adds the extra description to the checkbox field.
_extra_field_description_add_to_description Helper function adds the extra description to a fieldset's description.
_extra_field_description_add_to_prefix Helper function adds the extra description to the field prefix.
_extra_field_description_add_to_title Helper function adds the extra description to the field title.

Constants

Namesort descending Description
EXTRA_FIELD_DESCRIPTION_MODULE_PATH Define module path constant.