field_example.module
Same filename in other branches
An example field using the Field Types API.
File
-
field_example/
field_example.module
View source
<?php
/**
* @file
* An example field using the Field Types API.
*/
/**
* @defgroup field_example Example: Field Types API
* @ingroup examples
* @{
* Examples using Field Types API.
*
* Providing a field requires:
* - Defining a field:
* - hook_field_info()
* - hook_field_schema()
* - hook_field_validate()
* - hook_field_is_empty()
*
* - Defining a formatter for the field (the portion that outputs the field for
* display):
* - hook_field_formatter_info()
* - hook_field_formatter_view()
*
* - Defining a widget for the edit form:
* - hook_field_widget_info()
* - hook_field_widget_form()
*
* Our module defines the field in field_example_field_info(),
* field_example_field_validate() and field_example_field_is_empty().
* field_example_field_schema() is implemented in field_example.install.
*
* Our module sets up a formatter in field_example_field_formatter_info() and
* field_example_field_formatter_view(). These are the API hooks that present
* formatted and themed output to the user.
*
* And finally, our module defines the widget in
* field_example_field_widget_info() and field_example_field_widget_form().
* The widget is the form element used to receive input from the user
* when the field is being populated.
*
* @see field_types
* @see field
*/
/***************************************************************
* Field Type API hooks
***************************************************************/
/**
* Implements hook_field_info().
*
* Provides the description of the field.
*/
function field_example_field_info() {
return array(
// We name our field as the associative name of the array.
'field_example_rgb' => array(
'label' => t('Example Color RGB'),
'description' => t('Demonstrates a field composed of an RGB color.'),
'default_widget' => 'field_example_3text',
'default_formatter' => 'field_example_simple_text',
),
);
}
/**
* Implements hook_field_validate().
*
* This hook gives us a chance to validate content that's in our
* field. We're really only interested in the $items parameter, since
* it holds arrays representing content in the field we've defined.
* We want to verify that the items only contain RGB hex values like
* this: #RRGGBB. If the item validates, we do nothing. If it doesn't
* validate, we add our own error notification to the $errors parameter.
*
* @see field_example_field_widget_error()
*/
function field_example_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
foreach ($items as $delta => $item) {
if (!empty($item['rgb'])) {
if (!preg_match('@^#[0-9a-f]{6}$@', $item['rgb'])) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'field_example_invalid',
'message' => t('Color must be in the HTML format #abcdef.'),
);
}
}
}
}
/**
* Implements hook_field_is_empty().
*
* hook_field_is_empty() is where Drupal asks us if this field is empty.
* Return TRUE if it does not contain data, FALSE if it does. This lets
* the form API flag an error when required fields are empty.
*/
function field_example_field_is_empty($item, $field) {
return empty($item['rgb']);
}
/**
* Implements hook_field_formatter_info().
*
* We need to tell Drupal that we have two different types of formatters
* for this field. One will change the text color, and the other will
* change the background color.
*
* @see field_example_field_formatter_view()
*/
function field_example_field_formatter_info() {
return array(
// This formatter just displays the hex value in the color indicated.
'field_example_simple_text' => array(
'label' => t('Simple text-based formatter'),
'field types' => array(
'field_example_rgb',
),
),
// This formatter changes the background color of the content region.
'field_example_color_background' => array(
'label' => t('Change the background of the output text'),
'field types' => array(
'field_example_rgb',
),
),
);
}
/**
* Implements hook_field_formatter_view().
*
* Two formatters are implemented.
* - field_example_simple_text just outputs markup indicating the color that
* was entered and uses an inline style to set the text color to that value.
* - field_example_color_background does the same but also changes the
* background color of div.region-content.
*
* @see field_example_field_formatter_info()
*/
function field_example_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
switch ($display['type']) {
// This formatter simply outputs the field as text and with a color.
case 'field_example_simple_text':
foreach ($items as $delta => $item) {
$element[$delta] = array(
// We create a render array to produce the desired markup,
// "<p style="color: #hexcolor">The color code ... #hexcolor</p>".
// See theme_html_tag().
'#type' => 'html_tag',
'#tag' => 'p',
'#attributes' => array(
'style' => 'color: ' . $item['rgb'],
),
'#value' => t('The color code in this field is @code', array(
'@code' => $item['rgb'],
)),
);
}
break;
// This formatter adds css to the page changing the '.region-content' area's
// background color. If there are many fields, the last one will win.
case 'field_example_color_background':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => t('The content area color has been changed to @code', array(
'@code' => $item['rgb'],
)),
'#attached' => array(
'css' => array(
array(
'data' => 'div.region-content { background-color:' . $item['rgb'] . ';}',
'type' => 'inline',
),
),
),
);
}
break;
}
return $element;
}
/**
* Implements hook_field_widget_info().
*
* Three widgets are provided.
* - A simple text-only widget where the user enters the '#ffffff'.
* - A 3-textfield widget that gathers the red, green, and blue values
* separately.
* - A farbtastic colorpicker widget that chooses the value graphically.
*
* These widget types will eventually show up in hook_field_widget_form,
* where we will have to flesh them out.
*
* @see field_example_field_widget_form()
*/
function field_example_field_widget_info() {
return array(
'field_example_text' => array(
'label' => t('RGB value as #ffffff'),
'field types' => array(
'field_example_rgb',
),
),
'field_example_3text' => array(
'label' => t('RGB text field'),
'field types' => array(
'field_example_rgb',
),
),
'field_example_colorpicker' => array(
'label' => t('Color Picker'),
'field types' => array(
'field_example_rgb',
),
),
);
}
/**
* Implements hook_field_widget_form().
*
* hook_widget_form() is where Drupal tells us to create form elements for
* our field's widget.
*
* We provide one of three different forms, depending on the widget type of
* the Form API item provided.
*
* The 'field_example_colorpicker' and 'field_example_text' are essentially
* the same, but field_example_colorpicker adds a javascript colorpicker
* helper.
*
* field_example_3text displays three text fields, one each for red, green,
* and blue. However, the field type defines a single text column,
* rgb, which needs an HTML color spec. Define an element validate
* handler that converts our r, g, and b fields into a simulated single
* 'rgb' form element.
*/
function field_example_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$value = isset($items[$delta]['rgb']) ? $items[$delta]['rgb'] : '';
$widget = $element;
$widget['#delta'] = $delta;
switch ($instance['widget']['type']) {
case 'field_example_colorpicker':
$widget += array(
'#suffix' => '<div class="field-example-colorpicker"></div>',
'#attributes' => array(
'class' => array(
'edit-field-example-colorpicker',
),
),
'#attached' => array(
// Add Farbtastic color picker.
'library' => array(
array(
'system',
'farbtastic',
),
),
// Add javascript to trigger the colorpicker.
'js' => array(
drupal_get_path('module', 'field_example') . '/field_example.js',
),
),
);
// DELIBERATE fall-through: From here on the field_example_text and
// field_example_colorpicker are exactly the same.
case 'field_example_text':
$widget += array(
'#type' => 'textfield',
'#default_value' => $value,
// Allow a slightly larger size that the field length to allow for some
// configurations where all characters won't fit in input field.
'#size' => 7,
'#maxlength' => 7,
);
break;
case 'field_example_3text':
// Convert rgb value into r, g, and b for #default_value.
if (!empty($value)) {
preg_match_all('@..@', substr($value, 1), $match);
}
else {
$match = array(
array(),
);
}
// Make this a fieldset with the three text fields.
$widget += array(
'#type' => 'fieldset',
'#element_validate' => array(
'field_example_3text_validate',
),
// #delta is set so that the validation function will be able
// to access external value information which otherwise would be
// unavailable.
'#delta' => $delta,
'#attached' => array(
'css' => array(
drupal_get_path('module', 'field_example') . '/field_example.css',
),
),
);
// Create a textfield for saturation values for Red, Green, and Blue.
foreach (array(
'r' => t('Red'),
'g' => t('Green'),
'b' => t('Blue'),
) as $key => $title) {
$widget[$key] = array(
'#type' => 'textfield',
'#title' => $title,
'#size' => 2,
'#default_value' => array_shift($match[0]),
'#attributes' => array(
'class' => array(
'rgb-entry',
),
),
'#description' => t('The 2-digit hexadecimal representation of @color saturation, like "a1" or "ff"', array(
'@color' => $title,
)),
);
// Since Form API doesn't allow a fieldset to be required, we
// have to require each field element individually.
if ($instance['required'] == 1) {
$widget[$key]['#required'] = 1;
}
}
break;
}
$element['rgb'] = $widget;
return $element;
}
/**
* Validate the individual fields and then convert to RGB string.
*/
function field_example_3text_validate($element, &$form_state) {
// @todo: Isn't there a better way to find out which element?
$delta = $element['#delta'];
$field = $form_state['field'][$element['#field_name']][$element['#language']]['field'];
$field_name = $field['field_name'];
if (isset($form_state['values'][$field_name][$element['#language']][$delta]['rgb'])) {
$values = $form_state['values'][$field_name][$element['#language']][$delta]['rgb'];
foreach (array(
'r',
'g',
'b',
) as $colorfield) {
$colorfield_value = hexdec($values[$colorfield]);
// If they left any empty, we'll set the value empty and quit.
if (strlen($values[$colorfield]) == 0) {
form_set_value($element, '', $form_state);
return;
}
// If they gave us anything that's not hex, reject it.
if (strlen($values[$colorfield]) != 2 || $colorfield_value < 0 || $colorfield_value > 255) {
form_error($element[$colorfield], t("Saturation value must be a 2-digit hexadecimal value between 00 and ff."));
}
}
$value = sprintf('#%02s%02s%02s', $values['r'], $values['g'], $values['b']);
form_set_value($element, $value, $form_state);
}
}
/**
* Implements hook_field_widget_error().
*
* hook_field_widget_error() lets us figure out what to do with errors
* we might have generated in hook_field_validate(). Generally, we'll just
* call form_error().
*
* @see field_example_field_validate()
* @see form_error()
*/
function field_example_field_widget_error($element, $error, $form, &$form_state) {
switch ($error['error']) {
case 'field_example_invalid':
form_error($element, $error['message']);
break;
}
}
/**
* Implements hook_menu().
*
* Provides a simple user interface that tells the developer where to go.
*/
function field_example_menu() {
$items['examples/field_example'] = array(
'title' => 'Field Example',
'page callback' => '_field_example_page',
'access callback' => TRUE,
);
return $items;
}
/**
* A simple page to explain to the developer what to do.
*/
function _field_example_page() {
return t("The Field Example provides a field composed of an HTML RGB value, like #ff00ff. To use it, add the field to a content type.");
}
/**
* @} End of "defgroup field_example".
*/
Functions
Title | Deprecated | Summary |
---|---|---|
field_example_3text_validate | Validate the individual fields and then convert to RGB string. | |
field_example_field_formatter_info | Implements hook_field_formatter_info(). | |
field_example_field_formatter_view | Implements hook_field_formatter_view(). | |
field_example_field_info | Implements hook_field_info(). | |
field_example_field_is_empty | Implements hook_field_is_empty(). | |
field_example_field_validate | Implements hook_field_validate(). | |
field_example_field_widget_error | Implements hook_field_widget_error(). | |
field_example_field_widget_form | Implements hook_field_widget_form(). | |
field_example_field_widget_info | Implements hook_field_widget_info(). | |
field_example_menu | Implements hook_menu(). | |
_field_example_page | A simple page to explain to the developer what to do. |