Thursday, April 7, 2011

How to create a custom field for Drupal 7 ?

As you may be aware, the CCK (Content Creation Kit) module has been integrated into Drupal 7 as the Field module. This article is the first in a three part series on creating a custom field using the Drupal 7 Field API. I will be using the Integer date field contributed module as an example thruout this series. You can learn more about the Field API by reading through the Field API documentation.
In this article I will look at creating a simple field formatter. A field formatter is what you choose on a content type's "Manage Display" tab to format the content of a field when a node is displayed. I am starting with the field formatter because it is the easiest of the three components of a field (field type, field widget, field formatter) to implement correctly, and because you may wish to build a formatter for an existing field without building a widget.

** n.b: If you like this post, then please click on any one of the ad links on the top or side panel. Your small help will encourage me to deliver more useful and good tutorial resources for Drupal in this blog.

The Integer date field module

The Integer date field module defines a field type that stores integer values, a widget to allow users to enter dates to be converted into integers, and a formatter to display integers as dates. The conversion between date and integer is performed using the PHP strtotime() function and the conversion between integer and date is performed using the Drupal Core format_date() function.

Hooks required for a field formatter

The following list of hooks are required to implement a field formatter, I will discuss their implementation in the Integer date field module in further detail in the sections to follow.

Implementing hook_field_formatter_info()

/**
 * Implements hook_field_formatter_info().
 */
function integerdate_field_formatter_info() {
  return array(
    'integerdate_date_default' => array(
      'label' => t('Default formatted date'),
      'field types' => array('integerdate_date',),
      'settings' => array(
        'format_custom_string' => '',
        'format_option' => 'short',
      ),
    ),
  );
}
The hook_field_formatter_info() function is required to register a formatter with the Field API. The above implementation registers a formatter with the machine readable name 'integerdate_date_default', defines the field types to which the formatter can be applied, sets a human readable label and description, and pre-defines default settings for the formatter. The formatter settings will be 'format_option' and 'format_custom_string', which will be described in the next section. The above implementation provides that the formatter can be applied to the integerdate_date field type. This field type is defined in integerdate.module and will be discussed in the third article of this series. The 'field type' value above could just as easily have been set to the Drupal number_integer field type so that the formatter could be applied to a Drupal integer field.

Implementing hook_field_formatter_settings_form()

/**
 * Implements hook_field_formatter_settings_form().
 */
function integerdate_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  
  $element = array();
  
  $element['format_option'] = array(
    '#type' => 'select',
    '#title' => t('Select date format'),
    '#description' => t('Select the date format for this instance'),
    '#options' => array(
      'short' => integerdate_field_formatter_format_date(REQUEST_TIME, 'short'),
      'medium' => integerdate_field_formatter_format_date(REQUEST_TIME, 'medium'),
      'long' => integerdate_field_formatter_format_date(REQUEST_TIME, 'long'),
      'html5_date' => format_date(REQUEST_TIME, 'custom', 'Y\-m\-d') . ' (HTML5 )',
      'html5_month' => format_date(REQUEST_TIME, 'custom', 'Y\-m') . ' (HTML5 )',
      'custom' => t(''),
    ),
    '#default_value' => $settings['format_option'],
    '#multiple' => FALSE,
  );
  
  $element['format_custom_string'] = array(
    '#type' => 'textfield',
    '#title' => t('Custom format string'),
    '#description' => t('Enter a custom format string, to be used if "Custom format" is selected'),
    '#default_value' => $settings['format_custom_string'],
  );
  
  return $element;
}
The hook_field_formatter_settings_form() function is required to provide a settings form for the formatter. The implementation above implements two form elements:
  • format_option: a select element providing several default options for how the field will be displayed.
  • format_custom_string: a textfield element allowing administrators to define their own date format using a PHP date format string.
The displayed values of the format_option select element options are generated by the integerdate_field_formatter_format_date() function, which is a simple wrapper for Drupal's format_date() function, which itself is a wrapper for the PHP date() function. You can look in integerdate.module to see the source for this function.

Implementing hook_field_formatter_settings_summary()

/**
 * Implements hook_field_formatter_settings_summary().
 */
function integerdate_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $summary = integerdate_field_formatter_format_date(REQUEST_TIME, $settings['format_option'], $settings['format_custom_string']);
  return $summary;
}
The hook_field_formatter_settings_summary() function is required to display a summary of the formatter settings on a content type's "Manage display" tab, and is also required to expose the settings "Edit" control, without which administrators cannot modify the formatter's settings. The function returns a string representing a summary of the formatter settings. The implementation above returns the page request time formatted using the selected format option.

Implementing hook_field_formatter_view()

/** * Implements hook_field_formatter_view(). */ function integerdate_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { $settings = $display['settings']; $element = array(); $formatted_date = integerdate_field_formatter_format_date($items[0]['value'], $settings['format_option'], $settings['format_custom_string']); $element[0] = array('#markup' => $formatted_date); return $element; } The hook_field_formatter_view() function is required to display the formatted field value. This function is where the magic of formatting a field happens when a node is displayed. The implementation above performs almost exactly the same behavior as the implementation of hook_field_formatter_settings_summary(). However, in order to format the field value it passes $items[0]['value'] to the date formatting function, instead of passing the page request time. $items is an array representing all of the field values to be formatted. As this field type currently only allows for a single value the function is hard coded to use the 0th array index. $items[0]['value'] is the value of the integerdate_date and number_integer field types. This key varies depending on which field type you are using. It is a good practice to read the documentation, including the hook_field_schema() implementation for any field type for which you intend to build a formatter.

7 comments:

  1. the title is a bit misleading, should b "How to create a custom field formatter for Drupal 7 ?"

    ReplyDelete
  2. Also... "Implementing hook_field_formatter_view()" shows up as a block of text on my screen... would love to have the formatted text show up properly.

    ReplyDelete
  3. Here's the last hook block :


    /**
    * Implements hook_field_formatter_view().
    */
    function integerdate_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
    $settings = $display['settings']; $element = array();
    $formatted_date = integerdate_field_formatter_format_date($items[0]['value'], $settings['format_option'], $settings['format_custom_string']);
    $element[0] = array('#markup' => $formatted_date);
    return $element;
    }
    The hook_field_formatter_view() function is required to display the formatted field value.
    This function is where the magic of formatting a field happens when a node is displayed.
    The implementation above performs almost exactly the same behavior as the implementation of hook_field_formatter_settings_summary().
    However, in order to format the field value it passes $items[0]['value'] to the date formatting function, instead of passing the page request time.
    $items is an array representing all of the field values to be formatted.
    As this field type currently only allows for a single value the function is hard coded to use the 0th array index.
    $items[0]['value'] is the value of the integerdate_date and number_integer field types.
    This key varies depending on which field type you are using.
    It is a good practice to read the documentation, including the hook_field_schema() implementation for any field type for which you intend to build a formatter.

    ReplyDelete
  4. Thanks. I am looking for this

    ReplyDelete
  5. Excellent article, I will bookmark your page for future reference.
    Magento Development Company

    ReplyDelete