optionwidgets.module in Content Construction Kit (CCK) 6
Same filename and directory in other branches
Defines selection, check box and radio button widgets for text and numeric fields.
File
modules/optionwidgets/optionwidgets.moduleView source
<?php
/**
* @file
* Defines selection, check box and radio button widgets for text and numeric fields.
*/
function optionwidgets_form_alter(&$form, $form_state, $form_id) {
if ($form_id == '_content_admin_field') {
$output = '<p>' . t('Create a list of options as a list in <strong>Allowed values</strong> or as an array in PHP code. These values will be the same for %field in all content types.', array(
'%field' => $form['widget']['label']['#default_value'],
)) . '</p>';
if ($form['widget']['widget_type']['#default_value'] == 'optionwidgets_onoff') {
$output .= '<p>' . t("For a 'single on/off checkbox' widget, define the 'off' value first, then the 'on' value in the <strong>Allowed values</strong> section. Note that the checkbox will be labeled with the label of the 'on' value.") . '</p>';
}
elseif ($form['widget']['widget_type']['#default_value'] == 'optionwidgets_buttons') {
$output .= '<p>' . t("The 'checkboxes/radio buttons' widget will display checkboxes if the multiple values option is selected for this field, otherwise radios will be displayed.") . '</p>';
}
if (in_array($form['type']['#value'], array(
'text',
'number_integer',
'number_float',
'number_decimal',
)) && in_array($form['widget']['widget_type']['#default_value'], array(
'optionwidgets_onoff',
'optionwidgets_buttons',
'optionwidgets_select',
))) {
$form['field']['allowed_values_fieldset']['#collapsed'] = FALSE;
$form['field']['allowed_values_fieldset']['#description'] = $output;
}
}
}
/**
* Implementation of hook_theme().
*/
function optionwidgets_theme() {
return array(
'optionwidgets_select' => array(
'arguments' => array(
'element' => NULL,
),
),
'optionwidgets_buttons' => array(
'arguments' => array(
'element' => NULL,
),
),
'optionwidgets_onoff' => array(
'arguments' => array(
'element' => NULL,
),
),
'optionwidgets_none' => array(
'arguments' => array(
'widget_type' => NULL,
'field_name' => NULL,
'node_type' => NULL,
),
),
);
}
/**
* Implementation of hook_widget_info().
*
* We need custom handling of multiple values because we need
* to combine them into a options list rather than display
* multiple elements. We will use the content module's default
* handling for default values.
*
* Callbacks can be omitted if default handing is used.
* They're included here just so this module can be used
* as an example for custom modules that might do things
* differently.
*/
function optionwidgets_widget_info() {
return array(
'optionwidgets_select' => array(
'label' => t('Select list'),
'field types' => array(
'text',
'number_integer',
'number_decimal',
'number_float',
),
'multiple values' => CONTENT_HANDLE_MODULE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_DEFAULT,
),
),
'optionwidgets_buttons' => array(
'label' => t('Check boxes/radio buttons'),
'field types' => array(
'text',
'number_integer',
'number_decimal',
'number_float',
),
'multiple values' => CONTENT_HANDLE_MODULE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_DEFAULT,
),
),
'optionwidgets_onoff' => array(
'label' => t('Single on/off checkbox'),
'field types' => array(
'text',
'number_integer',
'number_decimal',
'number_float',
),
'multiple values' => CONTENT_HANDLE_MODULE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_DEFAULT,
),
),
);
}
/**
* Implementation of FAPI hook_elements().
*
* Any FAPI callbacks needed for individual widgets can be declared here,
* and the element will be passed to those callbacks for processing.
*
* Drupal will automatically theme the element using a theme with
* the same name as the hook_elements key.
*/
function optionwidgets_elements() {
return array(
'optionwidgets_select' => array(
'#input' => TRUE,
'#columns' => array(
'value',
),
'#delta' => 0,
'#element_validate' => array(
'optionwidgets_validate',
),
'#process' => array(
'optionwidgets_select_process',
),
),
'optionwidgets_buttons' => array(
'#input' => TRUE,
'#columns' => array(
'value',
),
'#delta' => 0,
'#element_validate' => array(
'optionwidgets_validate',
),
'#process' => array(
'optionwidgets_buttons_process',
),
),
'optionwidgets_onoff' => array(
'#input' => TRUE,
'#columns' => array(
'value',
),
'#delta' => 0,
'#element_validate' => array(
'optionwidgets_validate',
),
'#process' => array(
'optionwidgets_onoff_process',
),
),
);
}
/**
* Implementation of hook_widget().
*
* Attach a single form element to the form. It will be built out and
* validated in the callback(s) listed in hook_elements. We build it
* out in the callbacks rather than here in hook_widget so it can be
* plugged into any module that can provide it with valid
* $field information.
*
* Content module will set the weight, field name and delta values
* for each form element. This is a change from earlier CCK versions
* where the widget managed its own multiple values.
*
* If there are multiple values for this field, the content module will
* call this function as many times as needed.
*
* @param $form
* the entire form array, $form['#node'] holds node information
* @param $form_state
* the form_state, $form_state['values'] holds the form values.
* @param $field
* the field array
* @param $items
* an array of default values for this element
* @param $delta
* the order of this item in the array of subelements (0, 1, 2, etc)
*
* @return
* the form item for a single element for this field
*/
function optionwidgets_widget(&$form, &$form_state, $field, $items, $delta = NULL) {
$element = array(
'#type' => $field['widget']['type'],
'#default_value' => !empty($items) ? $items : array(),
);
return $element;
}
/**
* Process an individual element.
*
* Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set.
*
* The $fields array is in $form['#field_info'][$element['#field_name']].
*/
function optionwidgets_buttons_process($element, $edit, &$form_state, $form) {
$field_name = $element['#field_name'];
$field = $form['#field_info'][$field_name];
$field_key = $element['#columns'][0];
if (!$form_state['submitted']) {
$element['#value'] = optionwidgets_data2form($element, $element['#default_value'], $field);
}
$options = optionwidgets_options($field);
$element[$field_key] = array(
'#type' => $field['multiple'] ? 'checkboxes' : 'radios',
'#title' => $element['#title'],
'#description' => $element['#description'],
'#required' => $field['required'],
'#multiple' => $field['multiple'],
'#options' => $options,
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
);
// Make sure field info will be available to the validator which
// does not get the values in $form.
$form_state['#field_info'][$field['field_name']] = $field;
return $element;
}
/**
* Process an individual element.
*
* Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set.
*
* The $fields array is in $form['#field_info'][$element['#field_name']].
*/
function optionwidgets_select_process($element, $edit, &$form_state, $form) {
$field_name = $element['#field_name'];
$field = $form['#field_info'][$field_name];
$field_key = $element['#columns'][0];
if (!$form_state['submitted']) {
$element['#value'] = optionwidgets_data2form($element, $element['#default_value'], $field);
}
$options = optionwidgets_options($field);
$element[$field_key] = array(
'#type' => 'select',
'#title' => $element['#title'],
'#description' => $element['#description'],
'#required' => $field['required'],
'#multiple' => $field['multiple'],
'#options' => $options,
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
);
// Make sure field info will be available to the validator which
// does not get the values in $form.
// TODO for some reason putting the $field array into $form_state['storage']
// causes the node's hook_form_alter to be invoked twice, garbling the
// results. Need to investigate why that is happening (a core bug?), but
// in the meantime avoid using $form_state['storage'] to store anything.
$form_state['#field_info'][$field['field_name']] = $field;
return $element;
}
/**
* Process an individual element.
*
* Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set.
*
* The $fields array is in $form['#field_info'][$element['#field_name']].
*/
function optionwidgets_onoff_process($element, $edit, &$form_state, $form) {
$field_name = $element['#field_name'];
$field = $form['#field_info'][$field_name];
$field_key = $element['#columns'][0];
if (!$form_state['submitted']) {
$element['#value'] = optionwidgets_data2form($element, $element['#value'], $field);
}
$options = optionwidgets_options($field);
$keys = array_keys($options);
$on_value = !empty($keys) ? $keys[1] : NULL;
$element[$field_key] = array(
'#type' => 'checkbox',
'#title' => $options[$on_value],
'#description' => t($field['widget']['description']),
'#default_value' => isset($element['#value'][$field_key][0]) ? $element['#value'][$field_key][0] == $on_value : FALSE,
'#return_value' => $on_value,
);
// Make sure field info will be available to the validator which
// does not get the values in $form.
$form_state['#field_info'][$field['field_name']] = $field;
return $element;
}
/**
* FAPI function to validate optionwidgets element.
*
* Transpose selections from field => delta to delta => field,
* turning multiple selected options into multiple parent elements.
* Immediate parent is the delta, need to get back to parent's parent
* to create multiple elements.
*/
function optionwidgets_validate($element, &$form_state) {
$field = $form_state['#field_info'][$element['#field_name']];
$updated = optionwidgets_form2data($element, $element['#value'], $field);
form_set_value($element, $updated, $form_state);
}
/**
* Helper function to transpose the values as stored in the database
* to the format the widget needs. Can be called anywhere this
* transformation is needed.
*/
function optionwidgets_data2form($element, $items, $field) {
$field_key = $element['#columns'][0];
$options = optionwidgets_options($field);
$items_transposed = content_transpose_array_rows_cols($items);
$values = isset($items_transposed[$field_key]) && is_array($items_transposed[$field_key]) ? $items_transposed[$field_key] : array();
$keys = array();
foreach ($values as $value) {
$key = array_search($value, array_keys($options));
if (isset($key)) {
$keys[] = $value;
}
}
if ($field['multiple'] || $element['#type'] == 'optionwidgets_onoff') {
return array(
$field_key => $keys,
);
}
else {
return array(
$field_key => reset($keys),
);
}
}
/**
* Helper function to transpose the values returned by submitting the widget
* to the format to be stored in the field. Can be called anywhere this
* transformation is needed.
*/
function optionwidgets_form2data($element, $items, $field) {
$field_key = $element['#columns'][0];
$options = optionwidgets_options($field);
$keys = isset($items[$field_key]) ? $items[$field_key] : array();
if (!is_array($keys)) {
$keys = array(
$keys,
);
}
$values = array();
foreach ($keys as $key => $value) {
if (array_key_exists($value, $options)) {
$values[] = $value;
}
}
if (empty($values)) {
if ($element['#type'] == 'optionwidgets_onoff') {
$keys = array_keys($options);
$values[] = array_key_exists(0, $keys) ? $keys[0] : '';
}
else {
$values[] = NULL;
}
}
return content_transpose_array_rows_cols(array(
$field_key => $values,
));
}
/**
* Helper function for finding the allowed values list for a field.
*
* See if there is a module hook for the option values.
* Otherwise, try content_allowed_values() for an options list.
*/
function optionwidgets_options($field) {
$function = $field['module'] . '_allowed_values';
$options = function_exists($function) ? $function($field) : (array) content_allowed_values($field);
// Add an empty choice for non required radios and single-selects.
if ($field['widget']['type'] != 'optionwidgets_onoff' && !$field['required'] && !$field['multiple']) {
$options = array(
'' => theme('optionwidgets_none', $field),
) + $options;
}
return $options;
}
/**
* Theme the label for the empty value for options that are not required.
* The default theme will display N/A for a radio list and blank for a select.
*/
function theme_optionwidgets_none($field) {
switch ($field['widget']['type']) {
case 'optionwidgets_buttons':
return t('N/A');
default:
return '';
}
}
/**
* FAPI themes for optionwidgets.
*
* The select, checkboxes or radios are already rendered by the
* select, checkboxes, or radios themes and the HTML output
* lives in $element['#children']. Override this theme to
* make custom changes to the output.
*
* $element['#field_name'] contains the field name
* $element['#delta] is the position of this element in the group
*/
function theme_optionwidgets_select($element) {
return $element['#children'];
}
function theme_optionwidgets_onoff($element) {
return $element['#children'];
}
function theme_optionwidgets_buttons($element) {
return $element['#children'];
}
Functions
Name | Description |
---|---|
optionwidgets_buttons_process | Process an individual element. |
optionwidgets_data2form | Helper function to transpose the values as stored in the database to the format the widget needs. Can be called anywhere this transformation is needed. |
optionwidgets_elements | Implementation of FAPI hook_elements(). |
optionwidgets_form2data | Helper function to transpose the values returned by submitting the widget to the format to be stored in the field. Can be called anywhere this transformation is needed. |
optionwidgets_form_alter | @file Defines selection, check box and radio button widgets for text and numeric fields. |
optionwidgets_onoff_process | Process an individual element. |
optionwidgets_options | Helper function for finding the allowed values list for a field. |
optionwidgets_select_process | Process an individual element. |
optionwidgets_theme | Implementation of hook_theme(). |
optionwidgets_validate | FAPI function to validate optionwidgets element. |
optionwidgets_widget | Implementation of hook_widget(). |
optionwidgets_widget_info | Implementation of hook_widget_info(). |
theme_optionwidgets_buttons | |
theme_optionwidgets_none | Theme the label for the empty value for options that are not required. The default theme will display N/A for a radio list and blank for a select. |
theme_optionwidgets_onoff | |
theme_optionwidgets_select | FAPI themes for optionwidgets. |