#361683 follow-up by sun: Remove more windows line endings.

merge-requests/26/head
Angie Byron 2009-02-05 03:42:58 +00:00
parent 8bac2dd319
commit f3ed3283db
21 changed files with 5890 additions and 5890 deletions

View File

@ -2006,10 +2006,10 @@ function template_preprocess_node(&$variables) {
} }
// Clean up name so there are no underscores. // Clean up name so there are no underscores.
$variables['template_files'][] = 'node-' . str_replace('_', '-', $node->type); $variables['template_files'][] = 'node-' . str_replace('_', '-', $node->type);
$variables['template_files'][] = 'node-' . $node->nid; $variables['template_files'][] = 'node-' . $node->nid;
// Add $FIELD_NAME_rendered variables for fields. // Add $FIELD_NAME_rendered variables for fields.
drupal_function_exists('field_attach_preprocess'); drupal_function_exists('field_attach_preprocess');
$variables += field_attach_preprocess('node', $node); $variables += field_attach_preprocess('node', $node);
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,408 +1,409 @@
<?php <?php
// $Id$ // $Id$
// TODO : merge with field.default.inc ?
// TODO : merge with field.default.inc ?
/**
* Create a separate form element for each field. /**
*/ * Create a separate form element for each field.
function field_default_form($obj_type, $object, $field, $instance, $items, &$form, &$form_state, $get_delta = NULL) { */
// This could be called with no object, as when a UI module creates a function field_default_form($obj_type, $object, $field, $instance, $items, &$form, &$form_state, $get_delta = NULL) {
// dummy form to set default values. // This could be called with no object, as when a UI module creates a
if ($object) { // dummy form to set default values.
list($id, ,) = field_attach_extract_ids($obj_type, $object); if ($object) {
} list($id, ,) = field_attach_extract_ids($obj_type, $object);
$addition = array(); }
$addition = array();
$field_name = $field['field_name'];
$field_name = $field['field_name'];
// If the field is not accessible, don't add anything. The field value will
// be left unchanged on update, or considered empty on insert. // If the field is not accessible, don't add anything. The field value will
// TODO : if/when field_attach_insert() takes care of default values, // be left unchanged on update, or considered empty on insert.
// unaccessible fields will automatically get the default value on insert. // TODO : if/when field_attach_insert() takes care of default values,
if (!field_access('edit', $field)) { // unaccessible fields will automatically get the default value on insert.
return $addition; if (!field_access('edit', $field)) {
} return $addition;
}
// Put field information at the top of the form, so that it can be easily
// retrieved. // Put field information at the top of the form, so that it can be easily
// Note : widgets and other form handling code should *always* fetch // retrieved.
// field and instance information from $form['#fields'] rather than from // Note : widgets and other form handling code should *always* fetch
// field_info_field(). This lets us build forms for 'variants' of a field, // field and instance information from $form['#fields'] rather than from
// for instance on admin screens. // field_info_field(). This lets us build forms for 'variants' of a field,
$form['#fields'][$field_name] = array( // for instance on admin screens.
'field' => $field, $form['#fields'][$field_name] = array(
'instance' => $instance, 'field' => $field,
); 'instance' => $instance,
// TODO : why do we need this ? );
$form['#cache'] = FALSE; // TODO : why do we need this ?
$form['#cache'] = FALSE;
// Populate widgets with default values if we're creating a new object.
if (empty($items) && empty($id) && !empty($instance['default_value_function'])) { // Populate widgets with default values if we're creating a new object.
$items = array(); if (empty($items) && empty($id) && !empty($instance['default_value_function'])) {
$function = $instance['default_value_function']; $items = array();
if (drupal_function_exists($function)) { $function = $instance['default_value_function'];
$items = $function($obj_type, $object, $field, $instance); if (drupal_function_exists($function)) {
} $items = $function($obj_type, $object, $field, $instance);
} }
}
$form_element = array();
$form_element = array();
// If field module handles multiple values for this form element,
// and we are displaying an individual element, process the multiple value // If field module handles multiple values for this form element,
// form. // and we are displaying an individual element, process the multiple value
if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) { // form.
$form_element = field_multiple_value_form($field, $instance, $items, $form, $form_state); if (!isset($get_delta) && field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
} $form_element = field_multiple_value_form($field, $instance, $items, $form, $form_state);
// If the widget is handling multiple values (e.g Options), }
// or if we are displaying an individual element, just get a single form // If the widget is handling multiple values (e.g Options),
// element and make it the $delta value. // or if we are displaying an individual element, just get a single form
else { // element and make it the $delta value.
$delta = isset($get_delta) ? $get_delta : 0; else {
$function = $instance['widget']['module'] . '_field_widget'; $delta = isset($get_delta) ? $get_delta : 0;
if (drupal_function_exists($function)) { $function = $instance['widget']['module'] . '_field_widget';
if ($element = $function($form, $form_state, $field, $instance, $items, $delta)) { if (drupal_function_exists($function)) {
$defaults = array( if ($element = $function($form, $form_state, $field, $instance, $items, $delta)) {
'#required' => $get_delta > 0 ? FALSE : $instance['required'], $defaults = array(
'#columns' => array_keys($field['columns']), '#required' => $get_delta > 0 ? FALSE : $instance['required'],
'#title' => check_plain(t($instance['label'])), '#columns' => array_keys($field['columns']),
'#description' => field_filter_xss($instance['description']), '#title' => check_plain(t($instance['label'])),
'#delta' => $delta, '#description' => field_filter_xss($instance['description']),
'#field_name' => $field['field_name'], '#delta' => $delta,
'#bundle' => $instance['bundle'], '#field_name' => $field['field_name'],
); '#bundle' => $instance['bundle'],
$element = array_merge($element, $defaults); );
// If we're processing a specific delta value for a field where the $element = array_merge($element, $defaults);
// field module handles multiples, set the delta in the result. // If we're processing a specific delta value for a field where the
// For fields that handle their own processing, we can't make assumptions // field module handles multiples, set the delta in the result.
// about how the field is structured, just merge in the returned value. // For fields that handle their own processing, we can't make assumptions
if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) { // about how the field is structured, just merge in the returned value.
$form_element[$delta] = $element; if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) {
} $form_element[$delta] = $element;
else { }
$form_element = $element; else {
} $form_element = $element;
} }
} }
} }
}
if ($form_element) {
$defaults = array( if ($form_element) {
'#field_name' => $field['field_name'], $defaults = array(
'#tree' => TRUE, '#field_name' => $field['field_name'],
'#weight' => $instance['weight'], '#tree' => TRUE,
); '#weight' => $instance['weight'],
);
$addition[$field['field_name']] = array_merge($form_element, $defaults);
$form['#fields'][$field['field_name']]['form_path'] = array($field['field_name']); $addition[$field['field_name']] = array_merge($form_element, $defaults);
} $form['#fields'][$field['field_name']]['form_path'] = array($field['field_name']);
}
return $addition;
} return $addition;
}
/**
* Special handling to create form elements for multiple values. /**
* * Special handling to create form elements for multiple values.
* Handles generic features for multiple fields: *
* - number of widgets * Handles generic features for multiple fields:
* - AHAH-'add more' button * - number of widgets
* - drag-n-drop value reordering * - AHAH-'add more' button
*/ * - drag-n-drop value reordering
function field_multiple_value_form($field, $instance, $items, &$form, &$form_state) { */
$field = field_info_field($instance['field_name']); function field_multiple_value_form($field, $instance, $items, &$form, &$form_state) {
$field_name = $field['field_name']; $field = field_info_field($instance['field_name']);
$field_name = $field['field_name'];
switch ($field['cardinality']) {
case FIELD_CARDINALITY_UNLIMITED: switch ($field['cardinality']) {
$filled_items = field_set_empty($field, $items); case FIELD_CARDINALITY_UNLIMITED:
$current_item_count = isset($form_state['field_item_count'][$field_name]) $filled_items = field_set_empty($field, $items);
? $form_state['field_item_count'][$field_name] $current_item_count = isset($form_state['field_item_count'][$field_name])
: count($items); ? $form_state['field_item_count'][$field_name]
// We always want at least one empty icon for the user to fill in. : count($items);
$max = ($current_item_count > count($filled_items)) // We always want at least one empty icon for the user to fill in.
? $current_item_count - 1 $max = ($current_item_count > count($filled_items))
: $current_item_count; ? $current_item_count - 1
: $current_item_count;
break;
default: break;
$max = $field['cardinality'] - 1; default:
break; $max = $field['cardinality'] - 1;
} break;
}
$title = check_plain(t($instance['label']));
$description = field_filter_xss(t($instance['description'])); $title = check_plain(t($instance['label']));
$description = field_filter_xss(t($instance['description']));
$form_element = array(
'#theme' => 'field_multiple_value_form', $form_element = array(
'#multiple' => $field['cardinality'], '#theme' => 'field_multiple_value_form',
'#title' => $title, '#multiple' => $field['cardinality'],
'#required' => $instance['required'], '#title' => $title,
'#description' => $description, '#required' => $instance['required'],
); '#description' => $description,
);
$function = $instance['widget']['module'] . '_field_widget';
if (drupal_function_exists($function)) { $function = $instance['widget']['module'] . '_field_widget';
for ($delta = 0; $delta <= $max; $delta++) { if (drupal_function_exists($function)) {
if ($element = $function($form, $form_state, $field, $instance, $items, $delta)) { for ($delta = 0; $delta <= $max; $delta++) {
$multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED; if ($element = $function($form, $form_state, $field, $instance, $items, $delta)) {
$defaults = array( $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
'#title' => $multiple ? '' : $title, $defaults = array(
'#description' => $multiple ? '' : $description, '#title' => $multiple ? '' : $title,
'#required' => $delta == 0 && $instance['required'], '#description' => $multiple ? '' : $description,
'#weight' => $delta, '#required' => $delta == 0 && $instance['required'],
'#delta' => $delta, '#weight' => $delta,
'#columns' => array_keys($field['columns']), '#delta' => $delta,
'#field_name' => $field_name, '#columns' => array_keys($field['columns']),
'#bundle' => $instance['bundle'], '#field_name' => $field_name,
); '#bundle' => $instance['bundle'],
);
// Add an input field for the delta (drag-n-drop reordering), which will
// be hidden by tabledrag js behavior. // Add an input field for the delta (drag-n-drop reordering), which will
if ($multiple) { // be hidden by tabledrag js behavior.
// We name the element '_weight' to avoid clashing with column names if ($multiple) {
// defined by field modules. // We name the element '_weight' to avoid clashing with column names
$element['_weight'] = array( // defined by field modules.
'#type' => 'weight', $element['_weight'] = array(
'#delta' => $max, // this 'delta' is the 'weight' element's property '#type' => 'weight',
'#default_value' => isset($items[$delta]['_weight']) ? $items[$delta]['_weight'] : $delta, '#delta' => $max, // this 'delta' is the 'weight' element's property
'#weight' => 100, '#default_value' => isset($items[$delta]['_weight']) ? $items[$delta]['_weight'] : $delta,
); '#weight' => 100,
} );
}
$form_element[$delta] = array_merge($element, $defaults);
} $form_element[$delta] = array_merge($element, $defaults);
} }
}
// Add AHAH add more button, if not working with a programmed form.
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form['#programmed'])) { // Add AHAH add more button, if not working with a programmed form.
// Make sure the form is cached so ahah can work. if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form['#programmed'])) {
$form['#cache'] = TRUE; // Make sure the form is cached so ahah can work.
$bundle_name_url_str = str_replace('_', '-', $instance['bundle']); $form['#cache'] = TRUE;
$field_name_url_str = str_replace('_', '-', $field_name); $bundle_name_url_str = str_replace('_', '-', $instance['bundle']);
$field_name_url_str = str_replace('_', '-', $field_name);
$form_element[$field_name . '_add_more'] = array(
'#type' => 'submit', $form_element[$field_name . '_add_more'] = array(
'#name' => $field_name . '_add_more', '#type' => 'submit',
'#value' => t('Add another item'), '#name' => $field_name . '_add_more',
'#weight' => $instance['weight'] + $max + 1, '#value' => t('Add another item'),
// Submit callback for disabled JavaScript. '#weight' => $instance['weight'] + $max + 1,
'#submit' => array('field_add_more_submit'), // Submit callback for disabled JavaScript.
'#ahah' => array( '#submit' => array('field_add_more_submit'),
'path' => 'field/js_add_more/' . $bundle_name_url_str . '/' . $field_name_url_str, '#ahah' => array(
'wrapper' => $field_name_url_str . '-items', 'path' => 'field/js_add_more/' . $bundle_name_url_str . '/' . $field_name_url_str,
'method' => 'replace', 'wrapper' => $field_name_url_str . '-items',
'effect' => 'fade', 'method' => 'replace',
), 'effect' => 'fade',
// When JS is disabled, the field_add_more_submit handler will find ),
// the relevant field using these entries. // When JS is disabled, the field_add_more_submit handler will find
'#field_name' => $field_name, // the relevant field using these entries.
'#bundle' => $instance['bundle'], '#field_name' => $field_name,
); '#bundle' => $instance['bundle'],
);
// Add wrappers for the fields and 'more' button.
$form_element['#prefix'] = '<div class="clear-block" id="' . $field_name_url_str . '-add-more-wrapper"><div id="' . $field_name_url_str . '-items">'; // Add wrappers for the fields and 'more' button.
$form_element[$field_name . '_add_more']['#prefix'] = '<div class="field-add-more">'; $form_element['#prefix'] = '<div class="clear-block" id="' . $field_name_url_str . '-add-more-wrapper"><div id="' . $field_name_url_str . '-items">';
$form_element[$field_name . '_add_more']['#suffix'] = '</div></div></div>'; $form_element[$field_name . '_add_more']['#prefix'] = '<div class="field-add-more">';
} $form_element[$field_name . '_add_more']['#suffix'] = '</div></div></div>';
} }
return $form_element; }
} return $form_element;
}
/**
* Theme an individual form element. /**
* * Theme an individual form element.
* Combine multiple values into a table with drag-n-drop reordering. *
* TODO : convert to a template. * Combine multiple values into a table with drag-n-drop reordering.
*/ * TODO : convert to a template.
function theme_field_multiple_value_form($element) { */
$output = ''; function theme_field_multiple_value_form($element) {
$output = '';
if ($element['#multiple'] > 1 || $element['#multiple'] == FIELD_CARDINALITY_UNLIMITED) {
$table_id = $element['#field_name'] . '_values'; if ($element['#multiple'] > 1 || $element['#multiple'] == FIELD_CARDINALITY_UNLIMITED) {
$order_class = $element['#field_name'] . '-delta-order'; $table_id = $element['#field_name'] . '_values';
$required = !empty($element['#required']) ? '<span class="form-required" title="' . t('This field is required. ') . '">*</span>' : ''; $order_class = $element['#field_name'] . '-delta-order';
$required = !empty($element['#required']) ? '<span class="form-required" title="' . t('This field is required. ') . '">*</span>' : '';
$header = array(
array( $header = array(
'data' => t('!title: !required', array('!title' => $element['#title'], '!required' => $required)), array(
'colspan' => 2 'data' => t('!title: !required', array('!title' => $element['#title'], '!required' => $required)),
), 'colspan' => 2
t('Order'), ),
); t('Order'),
$rows = array(); );
$rows = array();
// Sort items according to '_weight' (needed when the form comes back after
// preview or failed validation) // Sort items according to '_weight' (needed when the form comes back after
$items = array(); // preview or failed validation)
foreach (element_children($element) as $key) { $items = array();
if ($key !== $element['#field_name'] . '_add_more') { foreach (element_children($element) as $key) {
$items[] = &$element[$key]; if ($key !== $element['#field_name'] . '_add_more') {
} $items[] = &$element[$key];
} }
usort($items, '_field_sort_items_value_helper'); }
usort($items, '_field_sort_items_value_helper');
// Add the items as table rows.
foreach ($items as $key => $item) { // Add the items as table rows.
$item['_weight']['#attributes']['class'] = $order_class; foreach ($items as $key => $item) {
$delta_element = drupal_render($item['_weight']); $item['_weight']['#attributes']['class'] = $order_class;
$cells = array( $delta_element = drupal_render($item['_weight']);
array('data' => '', 'class' => 'field-multiple-drag'), $cells = array(
drupal_render($item), array('data' => '', 'class' => 'field-multiple-drag'),
array('data' => $delta_element, 'class' => 'delta-order'), drupal_render($item),
); array('data' => $delta_element, 'class' => 'delta-order'),
$rows[] = array( );
'data' => $cells, $rows[] = array(
'class' => 'draggable', 'data' => $cells,
); 'class' => 'draggable',
} );
}
$output .= theme('table', $header, $rows, array('id' => $table_id, 'class' => 'field-multiple-table'));
$output .= $element['#description'] ? '<div class="description">' . $element['#description'] . '</div>' : ''; $output .= theme('table', $header, $rows, array('id' => $table_id, 'class' => 'field-multiple-table'));
$output .= drupal_render($element[$element['#field_name'] . '_add_more']); $output .= $element['#description'] ? '<div class="description">' . $element['#description'] . '</div>' : '';
$output .= drupal_render($element[$element['#field_name'] . '_add_more']);
drupal_add_tabledrag($table_id, 'order', 'sibling', $order_class);
} drupal_add_tabledrag($table_id, 'order', 'sibling', $order_class);
else { }
foreach (element_children($element) as $key) { else {
$output .= drupal_render($element[$key]); foreach (element_children($element) as $key) {
} $output .= drupal_render($element[$key]);
} }
}
return $output;
} return $output;
}
/**
* Submit handler to add more choices to a field form. This handler is used when /**
* JavaScript is not available. It makes changes to the form state and the * Submit handler to add more choices to a field form. This handler is used when
* entire form is rebuilt during the page reload. * JavaScript is not available. It makes changes to the form state and the
*/ * entire form is rebuilt during the page reload.
function field_add_more_submit($form, &$form_state) { */
// Set the form to rebuild and run submit handlers. function field_add_more_submit($form, &$form_state) {
if (isset($form['#builder_function']) && drupal_function_exists($form['#builder_function'])) { // Set the form to rebuild and run submit handlers.
$form['#builder_function']($form, $form_state); if (isset($form['#builder_function']) && drupal_function_exists($form['#builder_function'])) {
$form['#builder_function']($form, $form_state);
// Make the changes we want to the form state.
$field_name = $form_state['clicked_button']['#field_name']; // Make the changes we want to the form state.
if ($form_state['values'][$field_name][$field_name . '_add_more']) { $field_name = $form_state['clicked_button']['#field_name'];
$form_state['field_item_count'][$field_name] = count($form_state['values'][$field_name]); if ($form_state['values'][$field_name][$field_name . '_add_more']) {
} $form_state['field_item_count'][$field_name] = count($form_state['values'][$field_name]);
} }
} }
}
/**
* Menu callback for AHAH addition of new empty widgets. /**
*/ * Menu callback for AHAH addition of new empty widgets.
function field_add_more_js($bundle_name, $field_name) { */
// Arguments are coming from the url, so we translate back dashes. function field_add_more_js($bundle_name, $field_name) {
$field_name = str_replace('-', '_', $field_name); // Arguments are coming from the url, so we translate back dashes.
$field_name = str_replace('-', '_', $field_name);
$invalid = FALSE;
if (empty($_POST['form_build_id'])) { $invalid = FALSE;
// Invalid request. if (empty($_POST['form_build_id'])) {
$invalid = TRUE; // Invalid request.
} $invalid = TRUE;
}
// Retrieve the cached form.
$form_state = array('submitted' => FALSE); // Retrieve the cached form.
$form_build_id = $_POST['form_build_id']; $form_state = array('submitted' => FALSE);
$form = form_get_cache($form_build_id, $form_state); $form_build_id = $_POST['form_build_id'];
if (!$form) { $form = form_get_cache($form_build_id, $form_state);
// Invalid form_build_id. if (!$form) {
$invalid = TRUE; // Invalid form_build_id.
} $invalid = TRUE;
}
// Retrieve field information.
$field = $form['#fields'][$field_name]['field']; // Retrieve field information.
$instance = $form['#fields'][$field_name]['instance']; $field = $form['#fields'][$field_name]['field'];
$form_path = $form['#fields'][$field_name]['form_path']; $instance = $form['#fields'][$field_name]['instance'];
if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) { $form_path = $form['#fields'][$field_name]['form_path'];
// Ivnalid if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
$invalid = TRUE; // Ivnalid
} $invalid = TRUE;
}
if ($invalid) {
drupal_json(array('data' => '')); if ($invalid) {
exit; drupal_json(array('data' => ''));
} exit;
}
// We don't simply return a new empty widget row to append to existing ones,
// because: // We don't simply return a new empty widget row to append to existing ones,
// - ahah.js won't simply let us add a new row to a table // because:
// - attaching the 'draggable' behavior won't be easy // - ahah.js won't simply let us add a new row to a table
// So we resort to rebuilding the whole table of widgets including the // - attaching the 'draggable' behavior won't be easy
// existing ones, which makes us jump through a few hoops. // So we resort to rebuilding the whole table of widgets including the
// existing ones, which makes us jump through a few hoops.
// The form that we get from the cache is unbuilt. We need to build it so
// that _value callbacks can be executed and $form_state['values'] populated. // The form that we get from the cache is unbuilt. We need to build it so
// We only want to affect $form_state['values'], not the $form itself // that _value callbacks can be executed and $form_state['values'] populated.
// (built forms aren't supposed to enter the cache) nor the rest of // We only want to affect $form_state['values'], not the $form itself
// $form_state, so we use copies of $form and $form_state. // (built forms aren't supposed to enter the cache) nor the rest of
$form_copy = $form; // $form_state, so we use copies of $form and $form_state.
$form_state_copy = $form_state; $form_copy = $form;
$form_copy['#post'] = array(); $form_state_copy = $form_state;
form_builder($_POST['form_id'], $form_copy, $form_state_copy); $form_copy['#post'] = array();
// Just grab the data we need. form_builder($_POST['form_id'], $form_copy, $form_state_copy);
$form_state['values'] = $form_state_copy['values']; // Just grab the data we need.
// Reset cached ids, so that they don't affect the actual form we output. $form_state['values'] = $form_state_copy['values'];
form_clean_id(NULL, TRUE); // Reset cached ids, so that they don't affect the actual form we output.
form_clean_id(NULL, TRUE);
// Sort the $form_state['values'] we just built *and* the incoming $_POST data
// according to d-n-d reordering. // Sort the $form_state['values'] we just built *and* the incoming $_POST data
unset($form_state['values'][$field_name][$field['field_name'] . '_add_more']); // according to d-n-d reordering.
foreach ($_POST[$field_name] as $delta => $item) { unset($form_state['values'][$field_name][$field['field_name'] . '_add_more']);
$form_state['values'][$field_name][$delta]['_weight'] = $item['_weight']; foreach ($_POST[$field_name] as $delta => $item) {
} $form_state['values'][$field_name][$delta]['_weight'] = $item['_weight'];
$form_state['values'][$field_name] = _field_sort_items($field, $form_state['values'][$field_name]); }
$_POST[$field_name] = _field_sort_items($field, $_POST[$field_name]); $form_state['values'][$field_name] = _field_sort_items($field, $form_state['values'][$field_name]);
$_POST[$field_name] = _field_sort_items($field, $_POST[$field_name]);
// Build our new form element for the whole field, asking for one more element.
$form_state['field_item_count'] = array($field_name => count($_POST[$field_name]) + 1); // Build our new form element for the whole field, asking for one more element.
$items = $form_state['values'][$field_name]; $form_state['field_item_count'] = array($field_name => count($_POST[$field_name]) + 1);
$form_element = field_default_form(NULL, NULL, $field, $instance, $items, $form, $form_state); $items = $form_state['values'][$field_name];
// Let other modules alter it. $form_element = field_default_form(NULL, NULL, $field, $instance, $items, $form, $form_state);
drupal_alter('form', $form_element, array(), 'field_add_more_js'); // Let other modules alter it.
drupal_alter('form', $form_element, array(), 'field_add_more_js');
// Add the new element at the right location in the (original, unbuilt) form.
$target = &$form; // Add the new element at the right location in the (original, unbuilt) form.
foreach ($form_path as $key) { $target = &$form;
$target = &$target[$key]; foreach ($form_path as $key) {
} $target = &$target[$key];
$target = $form_element[$field_name]; }
$target = $form_element[$field_name];
// Save the new definition of the form.
$form_state['values'] = array(); // Save the new definition of the form.
form_set_cache($form_build_id, $form, $form_state); $form_state['values'] = array();
form_set_cache($form_build_id, $form, $form_state);
// Build the new form against the incoming $_POST values so that we can
// render the new element. // Build the new form against the incoming $_POST values so that we can
$delta = max(array_keys($_POST[$field_name])) + 1; // render the new element.
$_POST[$field_name][$delta]['_weight'] = $delta; $delta = max(array_keys($_POST[$field_name])) + 1;
$form_state = array('submitted' => FALSE); $_POST[$field_name][$delta]['_weight'] = $delta;
$form += array( $form_state = array('submitted' => FALSE);
'#post' => $_POST, $form += array(
'#programmed' => FALSE, '#post' => $_POST,
); '#programmed' => FALSE,
$form = form_builder($_POST['form_id'], $form, $form_state); );
$form = form_builder($_POST['form_id'], $form, $form_state);
// Render the new output.
// We get fetch the form element from the built $form. // Render the new output.
$field_form = $form; // We get fetch the form element from the built $form.
foreach ($form_path as $key) { $field_form = $form;
$field_form = $field_form[$key]; foreach ($form_path as $key) {
} $field_form = $field_form[$key];
// We add a div around the new field to receive the ahah effect. }
$field_form[$delta]['#prefix'] = '<div class="ahah-new-field">' . (isset($field_form[$delta]['#prefix']) ? $field_form[$delta]['#prefix'] : ''); // We add a div around the new field to receive the ahah effect.
$field_form[$delta]['#suffix'] = (isset($field_form[$delta]['#suffix']) ? $field_form[$delta]['#suffix'] : '') . '</div>'; $field_form[$delta]['#prefix'] = '<div class="ahah-new-field">' . (isset($field_form[$delta]['#prefix']) ? $field_form[$delta]['#prefix'] : '');
// TODO : this causes duplication of the wrapping divs $field_form[$delta]['#suffix'] = (isset($field_form[$delta]['#suffix']) ? $field_form[$delta]['#suffix'] : '') . '</div>';
// TODO : this causes duplication of the wrapping divs
// If a newly inserted widget contains AHAH behaviors, they normally won't
// work because AHAH doesn't know about those - it just attaches to the exact // If a newly inserted widget contains AHAH behaviors, they normally won't
// form elements that were initially specified in the Drupal.settings object. // work because AHAH doesn't know about those - it just attaches to the exact
// The new ones didn't exist then, so we need to update Drupal.settings // form elements that were initially specified in the Drupal.settings object.
// by ourselves in order to let AHAH know about those new form elements. // The new ones didn't exist then, so we need to update Drupal.settings
$javascript = drupal_add_js(NULL, NULL); // by ourselves in order to let AHAH know about those new form elements.
$output_js = isset($javascript['setting']) ? '<script type="text/javascript">jQuery.extend(Drupal.settings, ' . drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) . ');</script>' : ''; $javascript = drupal_add_js(NULL, NULL);
$output_js = isset($javascript['setting']) ? '<script type="text/javascript">jQuery.extend(Drupal.settings, ' . drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) . ');</script>' : '';
$output = theme('status_messages') . drupal_render($field_form) . $output_js;
drupal_json(array('status' => TRUE, 'data' => $output)); $output = theme('status_messages') . drupal_render($field_form) . $output_js;
exit; drupal_json(array('status' => TRUE, 'data' => $output));
} exit;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,388 +1,388 @@
<?php <?php
// $Id$ // $Id$
/** /**
* @file * @file
* Default implementation of the field storage API. * Default implementation of the field storage API.
*/ */
/** /**
* Implementation of hook_help(). * Implementation of hook_help().
*/ */
function field_sql_storage_help($path, $arg) { function field_sql_storage_help($path, $arg) {
switch ($path) { switch ($path) {
case 'admin/help#field_sql_storage': case 'admin/help#field_sql_storage':
$output = '<p>' . t('The Field SQL Storage module stores Field API data in the database. It is the default field storage module, but other field storage modules may be available in the contributions repository.') . '</p>'; $output = '<p>' . t('The Field SQL Storage module stores Field API data in the database. It is the default field storage module, but other field storage modules may be available in the contributions repository.') . '</p>';
return $output; return $output;
} }
} }
/** /**
* Generate a table name for a field data table. * Generate a table name for a field data table.
* *
* @param $name * @param $name
* The name of the field * The name of the field
* @return * @return
* A string containing the generated name for the database table * A string containing the generated name for the database table
*/ */
function _field_sql_storage_tablename($name) { function _field_sql_storage_tablename($name) {
return 'field_data_' . $name; return 'field_data_' . $name;
} }
/** /**
* Generate a table name for a field revision archive table. * Generate a table name for a field revision archive table.
* *
* @param $name * @param $name
* The name of the field * The name of the field
* @return * @return
* A string containing the generated name for the database table * A string containing the generated name for the database table
*/ */
function _field_sql_storage_revision_tablename($name) { function _field_sql_storage_revision_tablename($name) {
return 'field_data_revision_' . $name; return 'field_data_revision_' . $name;
} }
/** /**
* Generate a column name for a field data table. * Generate a column name for a field data table.
* *
* @param $name * @param $name
* The name of the field * The name of the field
* @param $column * @param $column
* The name of the column * The name of the column
* @return * @return
* A string containing a generated column name for a field data * A string containing a generated column name for a field data
* table that is unique among all other fields. * table that is unique among all other fields.
*/ */
function _field_sql_storage_columnname($name, $column) { function _field_sql_storage_columnname($name, $column) {
return $name . '_' . $column; return $name . '_' . $column;
} }
/** /**
* Retrieve or assign an entity type id for an object type. * Retrieve or assign an entity type id for an object type.
* *
* @param $obj_type * @param $obj_type
* The object type, such as 'node' or 'user'. * The object type, such as 'node' or 'user'.
* @return * @return
* The entity type id. * The entity type id.
* *
* TODO: We need to decide on 'entity' or 'object'. * TODO: We need to decide on 'entity' or 'object'.
*/ */
function _field_sql_storage_etid($obj_type) { function _field_sql_storage_etid($obj_type) {
$etid = variable_get('field_sql_storage_' . $obj_type . '_etid', NULL); $etid = variable_get('field_sql_storage_' . $obj_type . '_etid', NULL);
if (is_null($etid)) { if (is_null($etid)) {
$etid = db_insert('field_config_entity_type')->fields(array('type' => $obj_type))->execute(); $etid = db_insert('field_config_entity_type')->fields(array('type' => $obj_type))->execute();
variable_set('field_sql_storage_' . $obj_type . '_etid', $etid); variable_set('field_sql_storage_' . $obj_type . '_etid', $etid);
} }
return $etid; return $etid;
} }
/** /**
* Return the database schema for a field. This may contain one or * Return the database schema for a field. This may contain one or
* more tables. Each table will contain the columns relevant for the * more tables. Each table will contain the columns relevant for the
* specified field. Leave $field['columns'] empty to get only the * specified field. Leave $field['columns'] empty to get only the
* base schema. * base schema.
* *
* @param $field * @param $field
* The field structure for which to generate a database schema. * The field structure for which to generate a database schema.
* @return * @return
* One or more tables representing the schema for the field. * One or more tables representing the schema for the field.
*/ */
function _field_sql_storage_schema($field) { function _field_sql_storage_schema($field) {
$current = array( $current = array(
'description' => 'Data storage for field ' . $field['field_name'], 'description' => 'Data storage for field ' . $field['field_name'],
'fields' => array( 'fields' => array(
'etid' => array( 'etid' => array(
'type' => 'int', 'type' => 'int',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => TRUE, 'not null' => TRUE,
'description' => 'The entity type id this data is attached to', 'description' => 'The entity type id this data is attached to',
), ),
'bundle' => array( 'bundle' => array(
'type' => 'varchar', 'type' => 'varchar',
'length' => 32, 'length' => 32,
'not null' => TRUE, 'not null' => TRUE,
'default' => '', 'default' => '',
'description' => 'The field instance bundle to which this row belongs, used when deleting a field instance', 'description' => 'The field instance bundle to which this row belongs, used when deleting a field instance',
), ),
'deleted' => array( 'deleted' => array(
'type' => 'int', 'type' => 'int',
'size' => 'tiny', 'size' => 'tiny',
'not null' => TRUE, 'not null' => TRUE,
'default' => 0, 'default' => 0,
'description' => 'A boolean indicating whether this data item has been deleted' 'description' => 'A boolean indicating whether this data item has been deleted'
), ),
'entity_id' => array( 'entity_id' => array(
'type' => 'int', 'type' => 'int',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => TRUE, 'not null' => TRUE,
'description' => 'The entity id this data is attached to', 'description' => 'The entity id this data is attached to',
), ),
'revision_id' => array( 'revision_id' => array(
'type' => 'int', 'type' => 'int',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => FALSE, 'not null' => FALSE,
'description' => 'The entity revision id this data is attached to, or NULL if the entity type is not versioned', 'description' => 'The entity revision id this data is attached to, or NULL if the entity type is not versioned',
), ),
'delta' => array( 'delta' => array(
'type' => 'int', 'type' => 'int',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => TRUE, 'not null' => TRUE,
'description' => 'The sequence number for this data item, used for multi-value fields', 'description' => 'The sequence number for this data item, used for multi-value fields',
), ),
), ),
'primary key' => array('etid', 'entity_id', 'deleted', 'delta'), 'primary key' => array('etid', 'entity_id', 'deleted', 'delta'),
// TODO : index on 'bundle' // TODO : index on 'bundle'
); );
// Add field columns. // Add field columns.
foreach ($field['columns'] as $column_name => $attributes) { foreach ($field['columns'] as $column_name => $attributes) {
$current['fields'][_field_sql_storage_columnname($field['field_name'], $column_name)] = $attributes; $current['fields'][_field_sql_storage_columnname($field['field_name'], $column_name)] = $attributes;
} }
// Construct the revision table. The primary key includes // Construct the revision table. The primary key includes
// revision_id but not entity_id so that multiple revision loads can // revision_id but not entity_id so that multiple revision loads can
// use the IN operator. // use the IN operator.
$revision = $current; $revision = $current;
$revision['description'] = 'Revision archive storage for field ' . $field['field_name']; $revision['description'] = 'Revision archive storage for field ' . $field['field_name'];
$revision['revision_id']['description'] = 'The entity revision id this data is attached to'; $revision['revision_id']['description'] = 'The entity revision id this data is attached to';
$revision['primary key'] = array('etid', 'revision_id', 'deleted', 'delta'); $revision['primary key'] = array('etid', 'revision_id', 'deleted', 'delta');
return array( return array(
_field_sql_storage_tablename($field['field_name']) => $current, _field_sql_storage_tablename($field['field_name']) => $current,
_field_sql_storage_revision_tablename($field['field_name']) => $revision, _field_sql_storage_revision_tablename($field['field_name']) => $revision,
); );
} }
function field_sql_storage_field_storage_create_field($field) { function field_sql_storage_field_storage_create_field($field) {
$schema = _field_sql_storage_schema($field); $schema = _field_sql_storage_schema($field);
foreach ($schema as $name => $table) { foreach ($schema as $name => $table) {
db_create_table($ret, $name, $table); db_create_table($ret, $name, $table);
} }
} }
function field_sql_storage_field_storage_delete_field($field_name) { function field_sql_storage_field_storage_delete_field($field_name) {
// Mark all data associated with the field for deletion. // Mark all data associated with the field for deletion.
$table = _field_sql_storage_tablename($field_name); $table = _field_sql_storage_tablename($field_name);
db_update($table) db_update($table)
->fields(array('deleted' => 1)) ->fields(array('deleted' => 1))
->execute(); ->execute();
} }
/** /**
* Load field data for a set of objects from the database. * Load field data for a set of objects from the database.
* *
* @param $obj_type * @param $obj_type
* The entity type of objects being loaded, such as 'node' or * The entity type of objects being loaded, such as 'node' or
* 'user'. * 'user'.
* @param $objects * @param $objects
* The array of objects for which to load data. * The array of objects for which to load data.
* @param $age * @param $age
* FIELD_LOAD_CURRENT to load the most recent revision for all * FIELD_LOAD_CURRENT to load the most recent revision for all
* fields, or FIELD_LOAD_REVISION to load the version indicated by * fields, or FIELD_LOAD_REVISION to load the version indicated by
* each object. * each object.
* @return * @return
* An array of field data for the objects, keyed by entity id, field * An array of field data for the objects, keyed by entity id, field
* name, and item delta number. * name, and item delta number.
*/ */
function field_sql_storage_field_storage_load($obj_type, $objects, $age) { function field_sql_storage_field_storage_load($obj_type, $objects, $age) {
$etid = _field_sql_storage_etid($obj_type); $etid = _field_sql_storage_etid($obj_type);
$load_current = $age == FIELD_LOAD_CURRENT; $load_current = $age == FIELD_LOAD_CURRENT;
// Gather ids needed for each field. // Gather ids needed for each field.
$field_ids = array(); $field_ids = array();
$delta_count = array(); $delta_count = array();
foreach ($objects as $obj) { foreach ($objects as $obj) {
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $obj); list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $obj);
foreach (field_info_instances($bundle) as $instance) { foreach (field_info_instances($bundle) as $instance) {
$field_ids[$instance['field_name']][] = $load_current ? $id : $vid; $field_ids[$instance['field_name']][] = $load_current ? $id : $vid;
$delta_count[$id][$instance['field_name']] = 0; $delta_count[$id][$instance['field_name']] = 0;
} }
} }
$additions = array(); $additions = array();
foreach ($field_ids as $field_name => $ids) { foreach ($field_ids as $field_name => $ids) {
$field = field_info_field($field_name); $field = field_info_field($field_name);
$table = $load_current ? _field_sql_storage_tablename($field_name) : _field_sql_storage_revision_tablename($field_name); $table = $load_current ? _field_sql_storage_tablename($field_name) : _field_sql_storage_revision_tablename($field_name);
$results = db_select($table, 't') $results = db_select($table, 't')
->fields('t') ->fields('t')
->condition('etid', $etid) ->condition('etid', $etid)
->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN') ->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN')
->condition('deleted', 0) ->condition('deleted', 0)
->orderBy('delta') ->orderBy('delta')
->execute(); ->execute();
foreach ($results as $row) { foreach ($results as $row) {
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$field_name] < $field['cardinality']) { if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$field_name] < $field['cardinality']) {
$item = array(); $item = array();
// For each column declared by the field, populate the item // For each column declared by the field, populate the item
// from the prefixed database column. // from the prefixed database column.
foreach ($field['columns'] as $column => $attributes) { foreach ($field['columns'] as $column => $attributes) {
$item[$column] = $row->{_field_sql_storage_columnname($field_name, $column)}; $item[$column] = $row->{_field_sql_storage_columnname($field_name, $column)};
} }
// Add the item to the field values for the entity. // Add the item to the field values for the entity.
$additions[$row->entity_id][$field_name][] = $item; $additions[$row->entity_id][$field_name][] = $item;
$delta_count[$row->entity_id][$field_name]++; $delta_count[$row->entity_id][$field_name]++;
} }
} }
} }
return $additions; return $additions;
} }
function field_sql_storage_field_storage_write($obj_type, $object, $update = FALSE) { function field_sql_storage_field_storage_write($obj_type, $object, $update = FALSE) {
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
$etid = _field_sql_storage_etid($obj_type); $etid = _field_sql_storage_etid($obj_type);
$instances = field_info_instances($bundle); $instances = field_info_instances($bundle);
foreach ($instances as $instance) { foreach ($instances as $instance) {
$field_name = $instance['field_name']; $field_name = $instance['field_name'];
$table_name = _field_sql_storage_tablename($field_name); $table_name = _field_sql_storage_tablename($field_name);
$revision_name = _field_sql_storage_revision_tablename($field_name); $revision_name = _field_sql_storage_revision_tablename($field_name);
$field = field_read_field($field_name); $field = field_read_field($field_name);
// Leave the field untouched if $object comes with no $field_name property. // Leave the field untouched if $object comes with no $field_name property.
// Empty the field if $object->$field_name is NULL or an empty array. // Empty the field if $object->$field_name is NULL or an empty array.
// Function property_exists() is slower, so we catch the more frequent cases // Function property_exists() is slower, so we catch the more frequent cases
// where it's an empty array with the faster isset(). // where it's an empty array with the faster isset().
if (isset($object->$field_name) || property_exists($object, $field_name)) { if (isset($object->$field_name) || property_exists($object, $field_name)) {
// Delete and insert, rather than update, in case a value was added. // Delete and insert, rather than update, in case a value was added.
if ($update) { if ($update) {
db_delete($table_name)->condition('etid', $etid)->condition('entity_id', $id)->execute(); db_delete($table_name)->condition('etid', $etid)->condition('entity_id', $id)->execute();
if (isset($vid)) { if (isset($vid)) {
db_delete($revision_name)->condition('etid', $etid)->condition('entity_id', $id)->condition('revision_id', $vid)->execute(); db_delete($revision_name)->condition('etid', $etid)->condition('entity_id', $id)->condition('revision_id', $vid)->execute();
} }
} }
if ($object->$field_name) { if ($object->$field_name) {
// Prepare the multi-insert query. // Prepare the multi-insert query.
$columns = array('etid', 'entity_id', 'revision_id', 'bundle', 'delta'); $columns = array('etid', 'entity_id', 'revision_id', 'bundle', 'delta');
foreach ($field['columns'] as $column => $attributes) { foreach ($field['columns'] as $column => $attributes) {
$columns[] = _field_sql_storage_columnname($field_name, $column); $columns[] = _field_sql_storage_columnname($field_name, $column);
} }
$query = db_insert($table_name)->fields($columns); $query = db_insert($table_name)->fields($columns);
if (isset($vid)) { if (isset($vid)) {
$revision_query = db_insert($revision_name)->fields($columns); $revision_query = db_insert($revision_name)->fields($columns);
} }
$delta_count = 0; $delta_count = 0;
foreach ($object->$field_name as $delta => $item) { foreach ($object->$field_name as $delta => $item) {
$record = array( $record = array(
'etid' => $etid, 'etid' => $etid,
'entity_id' => $id, 'entity_id' => $id,
'revision_id' => $vid, 'revision_id' => $vid,
'bundle' => $bundle, 'bundle' => $bundle,
'delta' => $delta, 'delta' => $delta,
); );
foreach ($field['columns'] as $column => $attributes) { foreach ($field['columns'] as $column => $attributes) {
$record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL; $record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL;
} }
$query->values($record); $query->values($record);
if (isset($vid)) { if (isset($vid)) {
$revision_query->values($record); $revision_query->values($record);
} }
if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) { if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) {
break; break;
} }
} }
// Execute the insert. // Execute the insert.
$query->execute(); $query->execute();
if (isset($vid)) { if (isset($vid)) {
$revision_query->execute(); $revision_query->execute();
} }
} }
} }
} }
} }
/** /**
* Delete all field data for a single object. This function actually * Delete all field data for a single object. This function actually
* deletes the data from the database. * deletes the data from the database.
* *
* @param $obj_type * @param $obj_type
* The entity type of the object being deleted, such as 'node' or * The entity type of the object being deleted, such as 'node' or
* 'user'. * 'user'.
* @param $object * @param $object
* The object for which to delete field data. * The object for which to delete field data.
*/ */
function field_sql_storage_field_storage_delete($obj_type, $object) { function field_sql_storage_field_storage_delete($obj_type, $object) {
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
$etid = _field_sql_storage_etid($obj_type); $etid = _field_sql_storage_etid($obj_type);
$instances = field_info_instances($bundle); $instances = field_info_instances($bundle);
foreach ($instances as $instance) { foreach ($instances as $instance) {
$field_name = $instance['field_name']; $field_name = $instance['field_name'];
$table_name = _field_sql_storage_tablename($field_name); $table_name = _field_sql_storage_tablename($field_name);
$revision_name = _field_sql_storage_revision_tablename($field_name); $revision_name = _field_sql_storage_revision_tablename($field_name);
db_delete($table_name) db_delete($table_name)
->condition('etid', $etid) ->condition('etid', $etid)
->condition('entity_id', $id) ->condition('entity_id', $id)
->execute(); ->execute();
db_delete($revision_name) db_delete($revision_name)
->condition('etid', $etid) ->condition('etid', $etid)
->condition('entity_id', $id) ->condition('entity_id', $id)
->execute(); ->execute();
} }
} }
/** /**
* Delete field data for a single revision of a single object. * Delete field data for a single revision of a single object.
* Deleting the current (most recently written) revision is not * Deleting the current (most recently written) revision is not
* allowed as has undefined results. This function actually deletes * allowed as has undefined results. This function actually deletes
* the data from the database. * the data from the database.
* *
* @param $obj_type * @param $obj_type
* The entity type of the object being deleted, such as 'node' or * The entity type of the object being deleted, such as 'node' or
* 'user'. * 'user'.
* @param $object * @param $object
* The object for which to delete field data. * The object for which to delete field data.
*/ */
function field_sql_storage_field_storage_delete_revision($obj_type, $object) { function field_sql_storage_field_storage_delete_revision($obj_type, $object) {
list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object); list($id, $vid, $bundle) = field_attach_extract_ids($obj_type, $object);
$etid = _field_sql_storage_etid($obj_type); $etid = _field_sql_storage_etid($obj_type);
if (isset($vid)) { if (isset($vid)) {
$instances = field_info_instances($bundle); $instances = field_info_instances($bundle);
foreach ($instances as $instance) { foreach ($instances as $instance) {
$field_name = $instance['field_name']; $field_name = $instance['field_name'];
$revision_name = _field_sql_storage_revision_tablename($field_name); $revision_name = _field_sql_storage_revision_tablename($field_name);
db_delete($revision_name) db_delete($revision_name)
->condition('etid', $etid) ->condition('etid', $etid)
->condition('entity_id', $id) ->condition('entity_id', $id)
->condition('revision_id', $vid) ->condition('revision_id', $vid)
->execute(); ->execute();
} }
} }
} }
function field_sql_storage_field_storage_delete_instance($field_name, $bundle) { function field_sql_storage_field_storage_delete_instance($field_name, $bundle) {
// Mark all data associated with the field for deletion. // Mark all data associated with the field for deletion.
$table_name = _field_sql_storage_tablename($field_name); $table_name = _field_sql_storage_tablename($field_name);
$revision_name = _field_sql_storage_revision_tablename($field_name); $revision_name = _field_sql_storage_revision_tablename($field_name);
db_update($table_name) db_update($table_name)
->fields(array('deleted' => 1)) ->fields(array('deleted' => 1))
->condition('bundle', $bundle) ->condition('bundle', $bundle)
->execute(); ->execute();
db_update($revision_name) db_update($revision_name)
->fields(array('deleted' => 1)) ->fields(array('deleted' => 1))
->condition('bundle', $bundle) ->condition('bundle', $bundle)
->execute(); ->execute();
} }
function field_sql_storage_field_storage_rename_bundle($bundle_old, $bundle_new) { function field_sql_storage_field_storage_rename_bundle($bundle_old, $bundle_new) {
$instances = field_info_instances($bundle_old); $instances = field_info_instances($bundle_old);
foreach ($instances as $instance) { foreach ($instances as $instance) {
$table_name = _field_sql_storage_tablename($instance['field_name']); $table_name = _field_sql_storage_tablename($instance['field_name']);
$revision_name = _field_sql_storage_revision_tablename($instance['field_name']); $revision_name = _field_sql_storage_revision_tablename($instance['field_name']);
db_update($table_name) db_update($table_name)
->fields(array('bundle' => $bundle_new)) ->fields(array('bundle' => $bundle_new))
->condition('bundle', $bundle_old) ->condition('bundle', $bundle_old)
->execute(); ->execute();
db_update($revision_name) db_update($revision_name)
->fields(array('bundle' => $bundle_new)) ->fields(array('bundle' => $bundle_new))
->condition('bundle', $bundle_old) ->condition('bundle', $bundle_old)
->execute(); ->execute();
} }
} }

View File

@ -3,5 +3,4 @@ name = List
description = Defines list field types. Use with Options to create selection lists. description = Defines list field types. Use with Options to create selection lists.
package = Core - fields package = Core - fields
core = 7.x core = 7.x
files[]=list.module files[]=list.module

View File

@ -1,188 +1,188 @@
<?php <?php
// $Id$ // $Id$
/** /**
* @file * @file
* Defines list field types that can be used with the Options module. * Defines list field types that can be used with the Options module.
*/ */
/** /**
* Implementation of hook_theme(). * Implementation of hook_theme().
*/ */
function list_theme() { function list_theme() {
return array( return array(
'field_formatter_list_default' => array( 'field_formatter_list_default' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
'field_formatter_list_key' => array( 'field_formatter_list_key' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
); );
} }
/** /**
* Implementation of hook_field_info(). * Implementation of hook_field_info().
*/ */
function list_field_info() { function list_field_info() {
return array( return array(
'list' => array( 'list' => array(
'label' => t('List'), 'label' => t('List'),
'description' => t('This field stores numeric keys from key/value lists of allowed values where the key is a simple alias for the position of the value, i.e. 0|First option, 1|Second option, 2|Third option.'), 'description' => t('This field stores numeric keys from key/value lists of allowed values where the key is a simple alias for the position of the value, i.e. 0|First option, 1|Second option, 2|Third option.'),
'settings' => array('allowed_values_function' => ''), 'settings' => array('allowed_values_function' => ''),
'default_widget' => 'options_select', 'default_widget' => 'options_select',
'default_formatter' => 'list_default', 'default_formatter' => 'list_default',
), ),
'list_boolean' => array( 'list_boolean' => array(
'label' => t('Boolean'), 'label' => t('Boolean'),
'description' => t('This field stores simple on/off or yes/no options.'), 'description' => t('This field stores simple on/off or yes/no options.'),
'settings' => array('allowed_values_function' => ''), 'settings' => array('allowed_values_function' => ''),
'default_widget' => 'options_select', 'default_widget' => 'options_select',
'default_formatter' => 'list_default', 'default_formatter' => 'list_default',
), ),
'list_number' => array( 'list_number' => array(
'label' => t('List (numeric)'), 'label' => t('List (numeric)'),
'description' => t('This field stores keys from key/value lists of allowed numbers where the stored numeric key has significance and must be preserved, i.e. \'Lifetime in days\': 1|1 day, 7|1 week, 31|1 month.'), 'description' => t('This field stores keys from key/value lists of allowed numbers where the stored numeric key has significance and must be preserved, i.e. \'Lifetime in days\': 1|1 day, 7|1 week, 31|1 month.'),
'settings' => array('allowed_values_function' => ''), 'settings' => array('allowed_values_function' => ''),
'default_widget' => 'options_select', 'default_widget' => 'options_select',
'default_formatter' => 'list_default', 'default_formatter' => 'list_default',
), ),
'list_text' => array( 'list_text' => array(
'label' => t('List (text)'), 'label' => t('List (text)'),
'description' => t('This field stores keys from key/value lists of allowed values where the stored key has significance and must be a varchar, i.e. \'US States\': IL|Illinois, IA|Iowa, IN|Indiana'), 'description' => t('This field stores keys from key/value lists of allowed values where the stored key has significance and must be a varchar, i.e. \'US States\': IL|Illinois, IA|Iowa, IN|Indiana'),
'settings' => array('allowed_values_function' => ''), 'settings' => array('allowed_values_function' => ''),
'default_widget' => 'options_select', 'default_widget' => 'options_select',
'default_formatter' => 'list_default', 'default_formatter' => 'list_default',
), ),
); );
} }
/** /**
* Implementation of hook_field_schema(). * Implementation of hook_field_schema().
*/ */
function list_field_columns($field) { function list_field_columns($field) {
switch ($field['type']) { switch ($field['type']) {
case 'list_text': case 'list_text':
$columns = array( $columns = array(
'value' => array( 'value' => array(
'type' => 'varchar', 'type' => 'varchar',
'length' => 255, 'length' => 255,
'not null' => FALSE, 'not null' => FALSE,
), ),
); );
break; break;
case 'list_number': case 'list_number':
$columns = array( $columns = array(
'value' => array( 'value' => array(
'type' => 'float', 'type' => 'float',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => FALSE, 'not null' => FALSE,
), ),
); );
break; break;
default: default:
$columns = array( $columns = array(
'value' => array( 'value' => array(
'type' => 'int', 'type' => 'int',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => FALSE, 'not null' => FALSE,
), ),
); );
break; break;
} }
return $columns; return $columns;
} }
/** /**
* Implementation of hook_field_validate(). * Implementation of hook_field_validate().
*/ */
function list_field_validate($obj_type, $object, $field, $instance, $items, $form) { function list_field_validate($obj_type, $object, $field, $instance, $items, $form) {
$allowed_values = list_allowed_values($field); $allowed_values = list_allowed_values($field);
if (is_array($items)) { if (is_array($items)) {
foreach ($items as $delta => $item) { foreach ($items as $delta => $item) {
$error_element = isset($item['_error_element']) ? $item['_error_element'] : ''; $error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']); if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
if (!empty($item['value'])) { if (!empty($item['value'])) {
if (count($allowed_values) && !array_key_exists($item['value'], $allowed_values)) { if (count($allowed_values) && !array_key_exists($item['value'], $allowed_values)) {
form_set_error($error_element, t('%name: illegal value.', array('%name' => t($instance['label'])))); form_set_error($error_element, t('%name: illegal value.', array('%name' => t($instance['label']))));
} }
} }
} }
} }
} }
/** /**
* Implementation of hook_field_is_empty(). * Implementation of hook_field_is_empty().
*/ */
function list_field_is_empty($item, $field) { function list_field_is_empty($item, $field) {
if (empty($item['value']) && (string)$item['value'] !== '0') { if (empty($item['value']) && (string)$item['value'] !== '0') {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
/** /**
* Implementation of hook_field_formatter_info(). * Implementation of hook_field_formatter_info().
*/ */
function list_field_formatter_info() { function list_field_formatter_info() {
return array( return array(
'list_default' => array( 'list_default' => array(
'label' => t('Default'), 'label' => t('Default'),
'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'list_key' => array( 'list_key' => array(
'label' => t('Key'), 'label' => t('Key'),
'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
); );
} }
/** /**
* Theme function for 'default' list field formatter. * Theme function for 'default' list field formatter.
*/ */
function theme_field_formatter_list_default($element) { function theme_field_formatter_list_default($element) {
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
if (($allowed_values = list_allowed_values($field)) && isset($allowed_values[$element['#item']['value']])) { if (($allowed_values = list_allowed_values($field)) && isset($allowed_values[$element['#item']['value']])) {
return $allowed_values[$element['#item']['value']]; return $allowed_values[$element['#item']['value']];
} }
// If no match was found in allowed values, fall back to the key. // If no match was found in allowed values, fall back to the key.
return $element['#item']['safe']; return $element['#item']['safe'];
} }
/** /**
* Theme function for 'key' list field formatter. * Theme function for 'key' list field formatter.
*/ */
function theme_field_formatter_list_key($element) { function theme_field_formatter_list_key($element) {
return $element['#item']['safe']; return $element['#item']['safe'];
} }
/** /**
* Create an array of the allowed values for this field. * Create an array of the allowed values for this field.
* *
* Call the allowed_values_function to retrieve the allowed * Call the allowed_values_function to retrieve the allowed
* values array. * values array.
* *
* TODO Rework this to create a method of selecting plugable allowed values lists. * TODO Rework this to create a method of selecting plugable allowed values lists.
*/ */
function list_allowed_values($field) { function list_allowed_values($field) {
static $allowed_values; static $allowed_values;
if (isset($allowed_values[$field['field_name']])) { if (isset($allowed_values[$field['field_name']])) {
return $allowed_values[$field['field_name']]; return $allowed_values[$field['field_name']];
} }
$allowed_values[$field['field_name']] = array(); $allowed_values[$field['field_name']] = array();
if (isset($field['settings']['allowed_values_function'])) { if (isset($field['settings']['allowed_values_function'])) {
$function = $field['settings']['allowed_values_function']; $function = $field['settings']['allowed_values_function'];
if (drupal_function_exists($function)) { if (drupal_function_exists($function)) {
$allowed_values[$field['field_name']] = $function($field); $allowed_values[$field['field_name']] = $function($field);
} }
} }
return $allowed_values[$field['field_name']]; return $allowed_values[$field['field_name']];
} }

View File

@ -3,5 +3,4 @@ name = Number
description = Defines numeric field types. description = Defines numeric field types.
package = Core - fields package = Core - fields
core = 7.x core = 7.x
files[]=number.module files[]=number.module

View File

@ -1,425 +1,425 @@
<?php <?php
// $Id$ // $Id$
/** /**
* @file * @file
* Defines numeric field types. * Defines numeric field types.
*/ */
/** /**
* Implementation of hook_theme(). * Implementation of hook_theme().
*/ */
function number_theme() { function number_theme() {
return array( return array(
'number' => array('arguments' => array('element' => NULL)), 'number' => array('arguments' => array('element' => NULL)),
'field_formatter_number_integer' => array('arguments' => array('element' => NULL), 'function' => 'theme_field_formatter_number'), 'field_formatter_number_integer' => array('arguments' => array('element' => NULL), 'function' => 'theme_field_formatter_number'),
'field_formatter_number_decimal' => array('arguments' => array('element' => NULL), 'function' => 'theme_field_formatter_number'), 'field_formatter_number_decimal' => array('arguments' => array('element' => NULL), 'function' => 'theme_field_formatter_number'),
'field_formatter_number_unformatted' => array('arguments' => array('element' => NULL)), 'field_formatter_number_unformatted' => array('arguments' => array('element' => NULL)),
); );
} }
/** /**
* Implementation of hook_field_info(). * Implementation of hook_field_info().
*/ */
function number_field_info() { function number_field_info() {
return array( return array(
'number_integer' => array( 'number_integer' => array(
'label' => t('Integer'), 'label' => t('Integer'),
'description' => t('This field stores a number in the database as an integer.'), 'description' => t('This field stores a number in the database as an integer.'),
'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''),
'default_widget' => 'number', 'default_widget' => 'number',
'default_formatter' => 'number_integer', 'default_formatter' => 'number_integer',
), ),
'number_decimal' => array( 'number_decimal' => array(
'label' => t('Decimal'), 'label' => t('Decimal'),
'description' => t('This field stores a number in the database in a fixed decimal format.'), 'description' => t('This field stores a number in the database in a fixed decimal format.'),
'settings' => array('precision' => 10, 'scale' => 2, 'decimal' => ' .'), 'settings' => array('precision' => 10, 'scale' => 2, 'decimal' => ' .'),
'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''),
'default_widget' => 'number', 'default_widget' => 'number',
'default_formatter' => 'number_integer', 'default_formatter' => 'number_integer',
), ),
'number_float' => array( 'number_float' => array(
'label' => t('Float'), 'label' => t('Float'),
'description' => t('This field stores a number in the database in a floating point format.'), 'description' => t('This field stores a number in the database in a floating point format.'),
'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''), 'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''),
'default_widget' => 'number', 'default_widget' => 'number',
'default_formatter' => 'number_integer', 'default_formatter' => 'number_integer',
), ),
); );
} }
function number_field_columns($field) { function number_field_columns($field) {
switch ($field['type']) { switch ($field['type']) {
case 'number_integer' : case 'number_integer' :
$colums = array( $colums = array(
'value' => array( 'value' => array(
'type' => 'int', 'type' => 'int',
'not null' => FALSE 'not null' => FALSE
), ),
); );
break; break;
case 'number_float' : case 'number_float' :
$colums = array( $colums = array(
'value' => array( 'value' => array(
'type' => 'float', 'type' => 'float',
'not null' => FALSE 'not null' => FALSE
), ),
); );
break; break;
case 'number_decimal' : case 'number_decimal' :
$colums = array( $colums = array(
'value' => array( 'value' => array(
'type' => 'numeric', 'type' => 'numeric',
'precision' => $field['settings']['precision'], 'precision' => $field['settings']['precision'],
'scale' => $field['settings']['scale'], 'scale' => $field['settings']['scale'],
'not null' => FALSE 'not null' => FALSE
), ),
); );
break; break;
} }
return $colums; return $colums;
} }
/** /**
* Implementation of hook_field_validate(). * Implementation of hook_field_validate().
*/ */
function number_field_validate($obj_type, $node, $field, $instance, &$items, $form) { function number_field_validate($obj_type, $node, $field, $instance, &$items, $form) {
if (is_array($items)) { if (is_array($items)) {
foreach ($items as $delta => $item) { foreach ($items as $delta => $item) {
$error_element = isset($item['_error_element']) ? $item['_error_element'] : ''; $error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']); if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
if ($item['value'] != '') { if ($item['value'] != '') {
if (is_numeric($instance['settings']['min']) && $item['value'] < $instance['settings']['min']) { if (is_numeric($instance['settings']['min']) && $item['value'] < $instance['settings']['min']) {
form_set_error($error_element, t('%name: the value may be no smaller than %min.', array('%name' => t($instance['label']), '%min' => $instance['settings']['min']))); form_set_error($error_element, t('%name: the value may be no smaller than %min.', array('%name' => t($instance['label']), '%min' => $instance['settings']['min'])));
} }
if (is_numeric($instance['settings']['max']) && $item['value'] > $instance['settings']['max']) { if (is_numeric($instance['settings']['max']) && $item['value'] > $instance['settings']['max']) {
form_set_error($error_element, t('%name: the value may be no larger than %max.', array('%name' => t($instance['label']), '%max' => $instance['settings']['max']))); form_set_error($error_element, t('%name: the value may be no larger than %max.', array('%name' => t($instance['label']), '%max' => $instance['settings']['max'])));
} }
} }
} }
} }
} }
/** /**
* Implementation of hook_content_is_empty(). * Implementation of hook_content_is_empty().
*/ */
function number_field_is_empty($item, $field) { function number_field_is_empty($item, $field) {
if (empty($item['value']) && (string)$item['value'] !== '0') { if (empty($item['value']) && (string)$item['value'] !== '0') {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
/** /**
* Implementation of hook_field_formatter_info(). * Implementation of hook_field_formatter_info().
*/ */
function number_field_formatter_info() { function number_field_formatter_info() {
return array( return array(
'number_integer' => array( 'number_integer' => array(
'label' => t('default'), 'label' => t('default'),
'field types' => array('number_integer'), 'field types' => array('number_integer'),
'settings' => array( 'settings' => array(
'thousand_separator' => ' ', 'thousand_separator' => ' ',
'decimal_separator' => '.', 'decimal_separator' => '.',
'scale' => 0, 'scale' => 0,
'prefix_suffix' => TRUE, 'prefix_suffix' => TRUE,
), ),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'number_decimal' => array( 'number_decimal' => array(
'label' => t('default'), 'label' => t('default'),
'field types' => array('number_decimal', 'number_float'), 'field types' => array('number_decimal', 'number_float'),
'settings' => array( 'settings' => array(
'thousand_separator' => ' ', 'thousand_separator' => ' ',
'decimal_separator' => '.', 'decimal_separator' => '.',
'scale' => 2, 'scale' => 2,
'prefix_suffix' => TRUE, 'prefix_suffix' => TRUE,
), ),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'number_unformatted' => array( 'number_unformatted' => array(
'label' => t('unformatted'), 'label' => t('unformatted'),
'field types' => array('number_integer', 'number_decimal', 'number_float'), 'field types' => array('number_integer', 'number_decimal', 'number_float'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
); );
} }
/** /**
* Theme function for 'unformatted' number field formatter. * Theme function for 'unformatted' number field formatter.
*/ */
function theme_field_formatter_number_unformatted($element) { function theme_field_formatter_number_unformatted($element) {
return $element['#item']['value']; return $element['#item']['value'];
} }
/** /**
* Proxy theme function for number field formatters. * Proxy theme function for number field formatters.
*/ */
function theme_field_formatter_number($element) { function theme_field_formatter_number($element) {
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#field_name'], $element['#bundle']); $instance = field_info_instance($element['#field_name'], $element['#bundle']);
$value = $element['#item']['value']; $value = $element['#item']['value'];
$settings = $element['#settings']; $settings = $element['#settings'];
$formatter_type = $element['#formatter']; $formatter_type = $element['#formatter'];
if (empty($value) && $value !== '0') { if (empty($value) && $value !== '0') {
return ''; return '';
} }
$output = number_format($value, $settings['scale'], $settings['decimal_separator'], $settings['thousand_separator']); $output = number_format($value, $settings['scale'], $settings['decimal_separator'], $settings['thousand_separator']);
if ($settings['prefix_suffix']) { if ($settings['prefix_suffix']) {
$prefixes = isset($instance['settings']['prefix']) ? explode('|', check_plain($instance['settings']['prefix'])) : array(0 => ''); $prefixes = isset($instance['settings']['prefix']) ? explode('|', check_plain($instance['settings']['prefix'])) : array(0 => '');
$suffixes = isset($instance['settings']['suffix']) ? explode('|', check_plain($instance['settings']['suffix'])) : array(0 => ''); $suffixes = isset($instance['settings']['suffix']) ? explode('|', check_plain($instance['settings']['suffix'])) : array(0 => '');
$prefix = (count($prefixes) > 1) ? format_plural($value, $prefixes[0], $prefixes[1]) : $prefixes[0]; $prefix = (count($prefixes) > 1) ? format_plural($value, $prefixes[0], $prefixes[1]) : $prefixes[0];
$suffix = (count($suffixes) > 1) ? format_plural($value, $suffixes[0], $suffixes[1]) : $suffixes[0]; $suffix = (count($suffixes) > 1) ? format_plural($value, $suffixes[0], $suffixes[1]) : $suffixes[0];
$output = $prefix . $output . $suffix; $output = $prefix . $output . $suffix;
} }
return $output; return $output;
} }
/** /**
* Implementation of hook_field_widget_info(). * Implementation of hook_field_widget_info().
* *
* Here we indicate that the Field module will handle * Here we indicate that the Field module will handle
* multiple values for these widgets. * multiple values for these widgets.
* *
* Callbacks can be omitted if default handing is used. * Callbacks can be omitted if default handing is used.
* They're included here just so this module can be used * They're included here just so this module can be used
* as an example for custom modules that might do things * as an example for custom modules that might do things
* differently. * differently.
*/ */
function number_field_widget_info() { function number_field_widget_info() {
return array( return array(
'number' => array( 'number' => array(
'label' => t('Text field'), 'label' => t('Text field'),
'field types' => array('number_integer', 'number_decimal', 'number_float'), 'field types' => array('number_integer', 'number_decimal', 'number_float'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
'default value' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
); );
} }
/** /**
* Implementation of FAPI hook_elements(). * Implementation of FAPI hook_elements().
* *
* Any FAPI callbacks needed for individual widgets can be declared here, * Any FAPI callbacks needed for individual widgets can be declared here,
* and the element will be passed to those callbacks for processing. * and the element will be passed to those callbacks for processing.
* *
* Drupal will automatically theme the element using a theme with * Drupal will automatically theme the element using a theme with
* the same name as the hook_elements key. * the same name as the hook_elements key.
* *
* Includes a regex to check for valid values as an additional parameter * Includes a regex to check for valid values as an additional parameter
* the validator can use. The regex can be overridden if necessary. * the validator can use. The regex can be overridden if necessary.
*/ */
function number_elements() { function number_elements() {
return array( return array(
'number' => array( 'number' => array(
'#input' => TRUE, '#input' => TRUE,
'#columns' => array('value'), '#delta' => 0, '#columns' => array('value'), '#delta' => 0,
'#process' => array('number_process'), '#process' => array('number_process'),
), ),
); );
} }
/** /**
* Implementation of hook_field_widget(). * Implementation of hook_field_widget().
* *
* Attach a single form element to the form. It will be built out and * 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 * 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 * out in the callbacks rather than here in hook_widget so it can be
* plugged into any module that can provide it with valid * plugged into any module that can provide it with valid
* $field information. * $field information.
* *
* Field module will set the weight, field name and delta values * Field module will set the weight, field name and delta values
* for each form element. * for each form element.
* *
* If there are multiple values for this field, the Field module will * If there are multiple values for this field, the Field module will
* call this function as many times as needed. * call this function as many times as needed.
* *
* @param $form * @param $form
* the entire form array, $form['#node'] holds node information * the entire form array, $form['#node'] holds node information
* @param $form_state * @param $form_state
* the form_state, $form_state['values'] holds the form values. * the form_state, $form_state['values'] holds the form values.
* @param $field * @param $field
* The field structure. * The field structure.
* @param $instance * @param $instance
* the field instance array * the field instance array
* @param $delta * @param $delta
* the order of this item in the array of subelements (0, 1, 2, etc) * the order of this item in the array of subelements (0, 1, 2, etc)
* *
* @return * @return
* the form item for a single element for this field * the form item for a single element for this field
*/ */
function number_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { function number_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) {
$element = array( $element = array(
'#type' => $instance['widget']['type'], '#type' => $instance['widget']['type'],
'#default_value' => isset($items[$delta]) ? $items[$delta] : NULL, '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL,
); );
return $element; return $element;
} }
/** /**
* Process an individual element. * Process an individual element.
* *
* Build the form element. When creating a form using FAPI #process, * Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set. * note that $element['#value'] is already set.
* *
* The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
*/ */
function number_process($element, $edit, $form_state, $form) { function number_process($element, $edit, $form_state, $form) {
$field_name = $element['#field_name']; $field_name = $element['#field_name'];
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#field_name'], $element['#bundle']); $instance = field_info_instance($element['#field_name'], $element['#bundle']);
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
$value = isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : ''; $value = isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : '';
if ($field['type'] == 'number_decimal') { if ($field['type'] == 'number_decimal') {
$value = str_replace('.', $field['settings']['decimal'], $value); $value = str_replace('.', $field['settings']['decimal'], $value);
} }
$element[$field_key] = array( $element[$field_key] = array(
'#type' => 'textfield', '#type' => 'textfield',
'#default_value' => $value, '#default_value' => $value,
// Need to allow a slightly larger size that the field length to allow // Need to allow a slightly larger size that the field length to allow
// for some configurations where all characters won't fit in input field. // for some configurations where all characters won't fit in input field.
'#size' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] + 2 : 12, '#size' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] + 2 : 12,
'#maxlength' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] : 10, '#maxlength' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] : 10,
'#attributes' => array('class' => 'number'), '#attributes' => array('class' => 'number'),
// The following values were set by the Field module and need // The following values were set by the Field module and need
// to be passed down to the nested element. // to be passed down to the nested element.
'#title' => $element['#title'], '#title' => $element['#title'],
'#description' => $element['#description'], '#description' => $element['#description'],
'#required' => $element['#required'], '#required' => $element['#required'],
'#field_name' => $element['#field_name'], '#field_name' => $element['#field_name'],
'#bundle' => $element['#bundle'], '#bundle' => $element['#bundle'],
'#delta' => $element['#delta'], '#delta' => $element['#delta'],
'#columns' => $element['#columns'], '#columns' => $element['#columns'],
); );
if (!empty($instance['settings']['prefix'])) { if (!empty($instance['settings']['prefix'])) {
$prefixes = explode('|', $instance['settings']['prefix']); $prefixes = explode('|', $instance['settings']['prefix']);
$element[$field_key]['#field_prefix'] = array_pop($prefixes); $element[$field_key]['#field_prefix'] = array_pop($prefixes);
} }
if (!empty($instance['settings']['suffix'])) { if (!empty($instance['settings']['suffix'])) {
$suffixes = explode('|', $instance['settings']['suffix']); $suffixes = explode('|', $instance['settings']['suffix']);
$element[$field_key]['#field_suffix'] = array_pop($suffixes); $element[$field_key]['#field_suffix'] = array_pop($suffixes);
} }
// Make sure we don't wipe out element validation added elsewhere. // Make sure we don't wipe out element validation added elsewhere.
if (empty($element['#element_validate'])) { if (empty($element['#element_validate'])) {
$element['#element_validate'] = array(); $element['#element_validate'] = array();
} }
switch ($field['type']) { switch ($field['type']) {
case 'number_float': case 'number_float':
$element['#element_validate'][] = 'number_float_validate'; $element['#element_validate'][] = 'number_float_validate';
break; break;
case 'number_integer': case 'number_integer':
$element['#element_validate'][] = 'number_integer_validate'; $element['#element_validate'][] = 'number_integer_validate';
break; break;
case 'number_decimal': case 'number_decimal':
$element['#element_validate'][] = 'number_decimal_validate'; $element['#element_validate'][] = 'number_decimal_validate';
break; break;
} }
// Used so that hook_field('validate') knows where to flag an error. // Used so that hook_field('validate') knows where to flag an error.
$element['_error_element'] = array( $element['_error_element'] = array(
'#type' => 'value', '#type' => 'value',
'#value' => implode('][', array_merge($element['#parents'], array($field_key))), '#value' => implode('][', array_merge($element['#parents'], array($field_key))),
); );
return $element; return $element;
} }
/** /**
* FAPI validation of an individual float element. * FAPI validation of an individual float element.
*/ */
function number_float_validate($element, &$form_state) { function number_float_validate($element, &$form_state) {
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#field_name'], $element['#bundle']); $instance = field_info_instance($element['#field_name'], $element['#bundle']);
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
$value = $element['#value'][$field_key]; $value = $element['#value'][$field_key];
if (($element[$field_key]['#required'] || !empty($value))) { if (($element[$field_key]['#required'] || !empty($value))) {
$start = $value; $start = $value;
$value = preg_replace('@[^-0-9\.]@', '', $value); $value = preg_replace('@[^-0-9\.]@', '', $value);
if ($start != $value) { if ($start != $value) {
$error_field = implode('][', $element['#parents']) . '][' . $field_key; $error_field = implode('][', $element['#parents']) . '][' . $field_key;
form_set_error($error_field, t('Only numbers and decimals are allowed in %field.', array('%field' => t($instance['label'])))); form_set_error($error_field, t('Only numbers and decimals are allowed in %field.', array('%field' => t($instance['label']))));
} }
else { else {
form_set_value($element[$field_key], $value, $form_state); form_set_value($element[$field_key], $value, $form_state);
} }
} }
} }
/** /**
* FAPI validation of an individual integer element. * FAPI validation of an individual integer element.
*/ */
function number_integer_validate($element, &$form_state) { function number_integer_validate($element, &$form_state) {
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#field_name'], $element['#bundle']); $instance = field_info_instance($element['#field_name'], $element['#bundle']);
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
$value = $element['#value'][$field_key]; $value = $element['#value'][$field_key];
if (($element[$field_key]['#required'] || !empty($value))) { if (($element[$field_key]['#required'] || !empty($value))) {
$start = $value; $start = $value;
$value = preg_replace('@[^-0-9]@', '', $value); $value = preg_replace('@[^-0-9]@', '', $value);
if ($start != $value) { if ($start != $value) {
$error_field = implode('][', $element['#parents']) . '][' . $field_key; $error_field = implode('][', $element['#parents']) . '][' . $field_key;
form_set_error($error_field, t('Only numbers are allowed in %field.', array('%field' => t($instance['label'])))); form_set_error($error_field, t('Only numbers are allowed in %field.', array('%field' => t($instance['label']))));
} }
else { else {
form_set_value($element[$field_key], $value, $form_state); form_set_value($element[$field_key], $value, $form_state);
} }
} }
} }
/** /**
* FAPI validation of an individual decimal element. * FAPI validation of an individual decimal element.
*/ */
function number_decimal_validate($element, &$form_state) { function number_decimal_validate($element, &$form_state) {
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#field_name'], $element['#bundle']); $instance = field_info_instance($element['#field_name'], $element['#bundle']);
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
$value = $element['#value'][$field_key]; $value = $element['#value'][$field_key];
if (($element[$field_key]['#required'] || !empty($value))) { if (($element[$field_key]['#required'] || !empty($value))) {
$start = $value; $start = $value;
$value = preg_replace('@[^-0-9\\' . $field['settings']['decimal'] . ']@', '', $value); $value = preg_replace('@[^-0-9\\' . $field['settings']['decimal'] . ']@', '', $value);
if ($start != $value) { if ($start != $value) {
$error_field = implode('][', $element['#parents']) . '][' . $field_key; $error_field = implode('][', $element['#parents']) . '][' . $field_key;
form_set_error($error_field, t('Only numbers and the decimal character (%decimal) are allowed in %field.', array('%decimal' => $field['settings']['decimal'], '%field' => t($instance['label'])))); form_set_error($error_field, t('Only numbers and the decimal character (%decimal) are allowed in %field.', array('%decimal' => $field['settings']['decimal'], '%field' => t($instance['label']))));
} }
else { else {
$value = str_replace($field['settings']['decimal'], ' .', $value); $value = str_replace($field['settings']['decimal'], ' .', $value);
$value = round($value, $field['settings']['scale']); $value = round($value, $field['settings']['scale']);
form_set_value($element[$field_key], $value, $form_state); form_set_value($element[$field_key], $value, $form_state);
} }
} }
} }
/** /**
* FAPI theme for an individual number element. * FAPI theme for an individual number element.
* *
* The textfield is already rendered by the textfield * The textfield is already rendered by the textfield
* theme and the HTML output lives in $element['#children']. * theme and the HTML output lives in $element['#children'].
* Override this theme to make custom changes to the output. * Override this theme to make custom changes to the output.
* *
* $element['#field_name'] contains the field name * $element['#field_name'] contains the field name
* $element['#delta] is the position of this element in the group * $element['#delta] is the position of this element in the group
*/ */
function theme_number($element) { function theme_number($element) {
return $element['#children']; return $element['#children'];
} }

View File

@ -1,422 +1,422 @@
<?php <?php
// $Id$ // $Id$
/** /**
* @file * @file
* Defines selection, check box and radio button widgets for text and numeric fields. * Defines selection, check box and radio button widgets for text and numeric fields.
*/ */
/** /**
* Implementation of hook_theme(). * Implementation of hook_theme().
*/ */
function options_theme() { function options_theme() {
return array( return array(
'options_select' => array( 'options_select' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
'options_buttons' => array( 'options_buttons' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
'options_onoff' => array( 'options_onoff' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
'options_none' => array( 'options_none' => array(
'arguments' => array('widget_type' => NULL, 'field_name' => NULL, 'node_type' => NULL), 'arguments' => array('widget_type' => NULL, 'field_name' => NULL, 'node_type' => NULL),
), ),
); );
} }
/** /**
* Implementation of hook_field_widget_info(). * Implementation of hook_field_widget_info().
* *
* We need custom handling of multiple values because we need * We need custom handling of multiple values because we need
* to combine them into a options list rather than display * to combine them into a options list rather than display
* cardinality elements. We will use the field module's default * cardinality elements. We will use the field module's default
* handling for default values. * handling for default values.
* *
* Callbacks can be omitted if default handing is used. * Callbacks can be omitted if default handing is used.
* They're included here just so this module can be used * They're included here just so this module can be used
* as an example for custom modules that might do things * as an example for custom modules that might do things
* differently. * differently.
*/ */
function options_field_widget_info() { function options_field_widget_info() {
return array( return array(
'options_select' => array( 'options_select' => array(
'label' => t('Select list'), 'label' => t('Select list'),
'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM, 'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'default value' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'options_buttons' => array( 'options_buttons' => array(
'label' => t('Check boxes/radio buttons'), 'label' => t('Check boxes/radio buttons'),
'field types' => array('list', 'list_boolean', 'list_text', 'list_number'), 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM, 'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'default value' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'options_onoff' => array( 'options_onoff' => array(
'label' => t('Single on/off checkbox'), 'label' => t('Single on/off checkbox'),
'field types' => array('list_boolean'), 'field types' => array('list_boolean'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM, 'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'default value' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
); );
} }
/** /**
* Implementation of FAPI hook_elements(). * Implementation of FAPI hook_elements().
* *
* Any FAPI callbacks needed for individual widgets can be declared here, * Any FAPI callbacks needed for individual widgets can be declared here,
* and the element will be passed to those callbacks for processing. * and the element will be passed to those callbacks for processing.
* *
* Drupal will automatically theme the element using a theme with * Drupal will automatically theme the element using a theme with
* the same name as the hook_elements key. * the same name as the hook_elements key.
*/ */
function options_elements() { function options_elements() {
return array( return array(
'options_select' => array( 'options_select' => array(
'#input' => TRUE, '#input' => TRUE,
'#columns' => array('value'), '#delta' => 0, '#columns' => array('value'), '#delta' => 0,
'#process' => array('options_select_process'), '#process' => array('options_select_process'),
), ),
'options_buttons' => array( 'options_buttons' => array(
'#input' => TRUE, '#input' => TRUE,
'#columns' => array('value'), '#delta' => 0, '#columns' => array('value'), '#delta' => 0,
'#process' => array('options_buttons_process'), '#process' => array('options_buttons_process'),
), ),
'options_onoff' => array( 'options_onoff' => array(
'#input' => TRUE, '#input' => TRUE,
'#columns' => array('value'), '#delta' => 0, '#columns' => array('value'), '#delta' => 0,
'#process' => array('options_onoff_process'), '#process' => array('options_onoff_process'),
), ),
); );
} }
/** /**
* Implementation of hook_field_widget(). * Implementation of hook_field_widget().
*/ */
function options_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = NULL) { function options_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = NULL) {
$element = array( $element = array(
'#type' => $instance['widget']['type'], '#type' => $instance['widget']['type'],
'#default_value' => !empty($items) ? $items : array(), '#default_value' => !empty($items) ? $items : array(),
); );
return $element; return $element;
} }
/** /**
* Process an individual element. * Process an individual element.
* *
* Build the form element. When creating a form using FAPI #process, * Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set. * note that $element['#value'] is already set.
* *
* The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
*/ */
function options_buttons_process($element, $edit, &$form_state, $form) { function options_buttons_process($element, $edit, &$form_state, $form) {
$field = $form['#fields'][$element['#field_name']]['field']; $field = $form['#fields'][$element['#field_name']]['field'];
$instance = $form['#fields'][$element['#field_name']]['instance']; $instance = $form['#fields'][$element['#field_name']]['instance'];
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
// See if this element is in the database format or the transformed format, // See if this element is in the database format or the transformed format,
// and transform it if necessary. // and transform it if necessary.
if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) {
$element['#value'] = options_data2form($element, $element['#default_value'], $field); $element['#value'] = options_data2form($element, $element['#default_value'], $field);
} }
$options = options_options($field, $instance); $options = options_options($field, $instance);
$multiple = isset($element['#multiple']) ? $element['#multiple'] : $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED; $multiple = isset($element['#multiple']) ? $element['#multiple'] : $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
$value = array(); $value = array();
foreach ($element['#value'][$field_key] as $key) { foreach ($element['#value'][$field_key] as $key) {
// Multiple (checkboxes) need the default value in the form of an array. // Multiple (checkboxes) need the default value in the form of an array.
if ($multiple) { if ($multiple) {
$value[$key] = 1; $value[$key] = 1;
} }
// Non-multiple (radios) need single default value. // Non-multiple (radios) need single default value.
else { else {
$value = $key; $value = $key;
break; break;
} }
} }
$element[$field_key] = array( $element[$field_key] = array(
'#type' => $multiple ? 'checkboxes' : 'radios', '#type' => $multiple ? 'checkboxes' : 'radios',
'#title' => $element['#title'], '#title' => $element['#title'],
'#description' => $element['#description'], '#description' => $element['#description'],
'#required' => isset($element['#required']) ? $element['#required'] : $instance['required'], '#required' => isset($element['#required']) ? $element['#required'] : $instance['required'],
'#multiple' => $multiple, '#multiple' => $multiple,
'#options' => $options, '#options' => $options,
'#default_value' => $value, '#default_value' => $value,
); );
// Set #element_validate in a way that it will not wipe out other // Set #element_validate in a way that it will not wipe out other
// validation functions already set by other modules. // validation functions already set by other modules.
if (empty($element['#element_validate'])) { if (empty($element['#element_validate'])) {
$element['#element_validate'] = array(); $element['#element_validate'] = array();
} }
array_unshift($element['#element_validate'], 'options_validate'); array_unshift($element['#element_validate'], 'options_validate');
// Make sure field info will be available to the validator which // Make sure field info will be available to the validator which
// does not get the values in $form. // does not get the values in $form.
$form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']];
return $element; return $element;
} }
/** /**
* Process an individual element. * Process an individual element.
* *
* Build the form element. When creating a form using FAPI #process, * Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set. * note that $element['#value'] is already set.
* *
* The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
*/ */
function options_select_process($element, $edit, &$form_state, $form) { function options_select_process($element, $edit, &$form_state, $form) {
$field = $form['#fields'][$element['#field_name']]['field']; $field = $form['#fields'][$element['#field_name']]['field'];
$instance = $form['#fields'][$element['#field_name']]['instance']; $instance = $form['#fields'][$element['#field_name']]['instance'];
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
// See if this element is in the database format or the transformed format, // See if this element is in the database format or the transformed format,
// and transform it if necessary. // and transform it if necessary.
if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) {
$element['#value'] = options_data2form($element, $element['#default_value'], $field); $element['#value'] = options_data2form($element, $element['#default_value'], $field);
} }
$options = options_options($field, $instance); $options = options_options($field, $instance);
$element[$field_key] = array( $element[$field_key] = array(
'#type' => 'select', '#type' => 'select',
'#title' => $element['#title'], '#title' => $element['#title'],
'#description' => $element['#description'], '#description' => $element['#description'],
'#required' => isset($element['#required']) ? $element['#required'] : $instance['required'], '#required' => isset($element['#required']) ? $element['#required'] : $instance['required'],
'#multiple' => isset($element['#multiple']) ? $element['#multiple'] : $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED, '#multiple' => isset($element['#multiple']) ? $element['#multiple'] : $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED,
'#options' => $options, '#options' => $options,
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
); );
// Set #element_validate in a way that it will not wipe out other // Set #element_validate in a way that it will not wipe out other
// validation functions already set by other modules. // validation functions already set by other modules.
if (empty($element['#element_validate'])) { if (empty($element['#element_validate'])) {
$element['#element_validate'] = array(); $element['#element_validate'] = array();
} }
array_unshift($element['#element_validate'], 'options_validate'); array_unshift($element['#element_validate'], 'options_validate');
// Make sure field info will be available to the validator which // Make sure field info will be available to the validator which
// does not get the values in $form. // does not get the values in $form.
$form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']];
return $element; return $element;
} }
/** /**
* Process an individual element. * Process an individual element.
* *
* Build the form element. When creating a form using FAPI #process, * Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set. * note that $element['#value'] is already set.
*/ */
function options_onoff_process($element, $edit, &$form_state, $form) { function options_onoff_process($element, $edit, &$form_state, $form) {
$field = $form['#fields'][$element['#field_name']]['field']; $field = $form['#fields'][$element['#field_name']]['field'];
$instance = $form['#fields'][$element['#field_name']]['instance']; $instance = $form['#fields'][$element['#field_name']]['instance'];
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
// See if this element is in the database format or the transformed format, // See if this element is in the database format or the transformed format,
// and transform it if necessary. // and transform it if necessary.
if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) { if (is_array($element['#value']) && !array_key_exists($field_key, $element['#value'])) {
$element['#value'] = options_data2form($element, $element['#default_value'], $field); $element['#value'] = options_data2form($element, $element['#default_value'], $field);
} }
$options = options_options($field, $instance); $options = options_options($field, $instance);
$keys = array_keys($options); $keys = array_keys($options);
$on_value = (!empty($keys) && isset($keys[1])) ? $keys[1] : NULL; $on_value = (!empty($keys) && isset($keys[1])) ? $keys[1] : NULL;
$element[$field_key] = array( $element[$field_key] = array(
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => isset($options[$on_value]) ? $options[$on_value] : '', '#title' => isset($options[$on_value]) ? $options[$on_value] : '',
'#description' => $element['#description'], '#description' => $element['#description'],
'#default_value' => isset($element['#value'][$field_key][0]) ? $element['#value'][$field_key][0] == $on_value : FALSE, '#default_value' => isset($element['#value'][$field_key][0]) ? $element['#value'][$field_key][0] == $on_value : FALSE,
'#return_value' => $on_value, '#return_value' => $on_value,
); );
// Set #element_validate in a way that it will not wipe out other // Set #element_validate in a way that it will not wipe out other
// validation functions already set by other modules. // validation functions already set by other modules.
if (empty($element['#element_validate'])) { if (empty($element['#element_validate'])) {
$element['#element_validate'] = array(); $element['#element_validate'] = array();
} }
array_unshift($element['#element_validate'], 'options_validate'); array_unshift($element['#element_validate'], 'options_validate');
// Make sure field info will be available to the validator which // Make sure field info will be available to the validator which
// does not get the values in $form. // does not get the values in $form.
$form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']]; $form_state['#fields'][$element['#field_name']] = $form['#fields'][$element['#field_name']];
return $element; return $element;
} }
/** /**
* FAPI function to validate options element. * FAPI function to validate options element.
*/ */
function options_validate($element, &$form_state) { function options_validate($element, &$form_state) {
// Transpose selections from field => delta to delta => field, // Transpose selections from field => delta to delta => field,
// turning cardinality selected options into cardinality parent elements. // turning cardinality selected options into cardinality parent elements.
// Immediate parent is the delta, need to get back to parent's parent // Immediate parent is the delta, need to get back to parent's parent
// to create cardinality elements. // to create cardinality elements.
$field = $form_state['#fields'][$element['#field_name']]['field']; $field = $form_state['#fields'][$element['#field_name']]['field'];
$items = options_form2data($element, $field); $items = options_form2data($element, $field);
form_set_value($element, $items, $form_state); form_set_value($element, $items, $form_state);
// Check we don't exceed the allowed number of values. // Check we don't exceed the allowed number of values.
if ($field['cardinality'] >= 2) { if ($field['cardinality'] >= 2) {
// Filter out 'none' value (if present, will always be in key 0) // Filter out 'none' value (if present, will always be in key 0)
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
if (isset($items[0][$field_key]) && $items[0][$field_key] === '') { if (isset($items[0][$field_key]) && $items[0][$field_key] === '') {
unset($items[0]); unset($items[0]);
} }
if (count($items) > $field['cardinality']) { if (count($items) > $field['cardinality']) {
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
form_error($element[$field_key], t('%name: this field cannot hold more that @count values.', array('%name' => t($field['widget']['label']), '@count' => $field['cardinality']))); form_error($element[$field_key], t('%name: this field cannot hold more that @count values.', array('%name' => t($field['widget']['label']), '@count' => $field['cardinality'])));
} }
} }
} }
/** /**
* Helper function to transpose the values as stored in the database * Helper function to transpose the values as stored in the database
* to the format the widget needs. Can be called anywhere this * to the format the widget needs. Can be called anywhere this
* transformation is needed. * transformation is needed.
*/ */
function options_data2form($element, $items, $field) { function options_data2form($element, $items, $field) {
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#field_name'], $element['#bundle']); $instance = field_info_instance($element['#field_name'], $element['#bundle']);
$options = options_options($field, $instance); $options = options_options($field, $instance);
$items_transposed = options_transpose_array_rows_cols($items); $items_transposed = options_transpose_array_rows_cols($items);
$values = (isset($items_transposed[$field_key]) && is_array($items_transposed[$field_key])) ? $items_transposed[$field_key] : array(); $values = (isset($items_transposed[$field_key]) && is_array($items_transposed[$field_key])) ? $items_transposed[$field_key] : array();
$keys = array(); $keys = array();
foreach ($values as $value) { foreach ($values as $value) {
$key = array_search($value, array_keys($options)); $key = array_search($value, array_keys($options));
if (isset($key)) { if (isset($key)) {
$keys[] = $value; $keys[] = $value;
} }
} }
if ($field['cardinality'] || $element['#type'] == 'options_onoff') { if ($field['cardinality'] || $element['#type'] == 'options_onoff') {
return array($field_key => $keys); return array($field_key => $keys);
} }
else { else {
return !empty($keys) ? array($field_key => $value) : array(); return !empty($keys) ? array($field_key => $value) : array();
} }
} }
/** /**
* Helper function to transpose the values returned by submitting the widget * 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 * to the format to be stored in the field. Can be called anywhere this
* transformation is needed. * transformation is needed.
*/ */
function options_form2data($element, $field) { function options_form2data($element, $field) {
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#field_name'], $element['#bundle']); $instance = field_info_instance($element['#field_name'], $element['#bundle']);
$items = (array) $element[$field_key]['#value']; $items = (array) $element[$field_key]['#value'];
$options = options_options($field, $instance); $options = options_options($field, $instance);
$values = array_values($items); $values = array_values($items);
if ($element['#type'] == 'options_onoff' && ($values[0] === 0)) { if ($element['#type'] == 'options_onoff' && ($values[0] === 0)) {
$keys = array_keys($options); $keys = array_keys($options);
$values = array(array_key_exists(0, $keys) ? $keys[0] : NULL); $values = array(array_key_exists(0, $keys) ? $keys[0] : NULL);
} }
if (empty($values)) { if (empty($values)) {
$values[] = NULL; $values[] = NULL;
} }
$result = options_transpose_array_rows_cols(array($field_key => $values)); $result = options_transpose_array_rows_cols(array($field_key => $values));
return $result; return $result;
} }
/** /**
* Manipulate a 2D array to reverse rows and columns. * Manipulate a 2D array to reverse rows and columns.
* *
* The default data storage for fields is delta first, column names second. * The default data storage for fields is delta first, column names second.
* This is sometimes inconvenient for field modules, so this function can be * This is sometimes inconvenient for field modules, so this function can be
* used to present the data in an alternate format. * used to present the data in an alternate format.
* *
* @param $array * @param $array
* The array to be transposed. It must be at least two-dimensional, and * The array to be transposed. It must be at least two-dimensional, and
* the subarrays must all have the same keys or behavior is undefined. * the subarrays must all have the same keys or behavior is undefined.
* @return * @return
* The transposed array. * The transposed array.
*/ */
function options_transpose_array_rows_cols($array) { function options_transpose_array_rows_cols($array) {
$result = array(); $result = array();
if (is_array($array)) { if (is_array($array)) {
foreach ($array as $key1 => $value1) { foreach ($array as $key1 => $value1) {
if (is_array($value1)) { if (is_array($value1)) {
foreach ($value1 as $key2 => $value2) { foreach ($value1 as $key2 => $value2) {
if (!isset($result[$key2])) { if (!isset($result[$key2])) {
$result[$key2] = array(); $result[$key2] = array();
} }
$result[$key2][$key1] = $value2; $result[$key2][$key1] = $value2;
} }
} }
} }
} }
return $result; return $result;
} }
/** /**
* Helper function for finding the allowed values list for a field. * Helper function for finding the allowed values list for a field.
* *
* See if there is a module hook for the option values. * See if there is a module hook for the option values.
* Otherwise, try list_allowed_values() for an options list. * Otherwise, try list_allowed_values() for an options list.
*/ */
function options_options($field, $instance) { function options_options($field, $instance) {
$function = $field['module'] . '_allowed_values'; $function = $field['module'] . '_allowed_values';
$options = function_exists($function) ? $function($field) : (array) list_allowed_values($field); $options = function_exists($function) ? $function($field) : (array) list_allowed_values($field);
// Add an empty choice for : // Add an empty choice for :
// - non required radios // - non required radios
// - non required selects // - non required selects
if (!$instance['required']) { if (!$instance['required']) {
if ((in_array($instance['widget']['type'], array('options_buttons', 'node_reference_buttons', 'user_reference_buttons')) && !$field['cardinality']) if ((in_array($instance['widget']['type'], array('options_buttons', 'node_reference_buttons', 'user_reference_buttons')) && !$field['cardinality'])
|| (in_array($instance['widget']['type'], array('options_select', 'node_reference_select', 'user_reference_select')))) { || (in_array($instance['widget']['type'], array('options_select', 'node_reference_select', 'user_reference_select')))) {
$options = array('' => theme('options_none', $instance)) + $options; $options = array('' => theme('options_none', $instance)) + $options;
} }
} }
return $options; return $options;
} }
/** /**
* Theme the label for the empty value for options that are not required. * 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. * The default theme will display N/A for a radio list and blank for a select.
*/ */
function theme_options_none($instance) { function theme_options_none($instance) {
switch ($instance['widget']['type']) { switch ($instance['widget']['type']) {
case 'options_buttons': case 'options_buttons':
case 'node_reference_buttons': case 'node_reference_buttons':
case 'user_reference_buttons': case 'user_reference_buttons':
return t('N/A'); return t('N/A');
case 'options_select': case 'options_select':
case 'node_reference_select': case 'node_reference_select':
case 'user_reference_select': case 'user_reference_select':
return t('- None -'); return t('- None -');
default : default :
return ''; return '';
} }
} }
/** /**
* FAPI themes for options. * FAPI themes for options.
* *
* The select, checkboxes or radios are already rendered by the * The select, checkboxes or radios are already rendered by the
* select, checkboxes, or radios themes and the HTML output * select, checkboxes, or radios themes and the HTML output
* lives in $element['#children']. Override this theme to * lives in $element['#children']. Override this theme to
* make custom changes to the output. * make custom changes to the output.
* *
* $element['#field_name'] contains the field name * $element['#field_name'] contains the field name
* $element['#delta] is the position of this element in the group * $element['#delta] is the position of this element in the group
*/ */
function theme_options_select($element) { function theme_options_select($element) {
return $element['#children']; return $element['#children'];
} }
function theme_options_onoff($element) { function theme_options_onoff($element) {
return $element['#children']; return $element['#children'];
} }
function theme_options_buttons($element) { function theme_options_buttons($element) {
return $element['#children']; return $element['#children'];
} }

View File

@ -3,5 +3,4 @@ name = Text
description = Defines simple text field types. description = Defines simple text field types.
package = Core - fields package = Core - fields
core = 7.x core = 7.x
files[]=text.module files[]=text.module

View File

@ -1,400 +1,400 @@
<?php <?php
// $Id$ // $Id$
/** /**
* @file * @file
* Defines simple text field types. * Defines simple text field types.
*/ */
/** /**
* Implementation of hook_theme(). * Implementation of hook_theme().
*/ */
function text_theme() { function text_theme() {
return array( return array(
'text_textarea' => array( 'text_textarea' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
'text_textfield' => array( 'text_textfield' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
'field_formatter_text_default' => array( 'field_formatter_text_default' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
'field_formatter_text_plain' => array( 'field_formatter_text_plain' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
'field_formatter_text_trimmed' => array( 'field_formatter_text_trimmed' => array(
'arguments' => array('element' => NULL), 'arguments' => array('element' => NULL),
), ),
); );
} }
/** /**
* Implementation of hook_field_info(). * Implementation of hook_field_info().
*/ */
function text_field_info() { function text_field_info() {
return array( return array(
'text' => array( 'text' => array(
'label' => t('Text'), 'label' => t('Text'),
'description' => t('This field stores varchar text in the database.'), 'description' => t('This field stores varchar text in the database.'),
'settings' => array('max_length' => 255), 'settings' => array('max_length' => 255),
'instance_settings' => array('text_processing' => 0), 'instance_settings' => array('text_processing' => 0),
'default_widget' => 'text_textfield', 'default_widget' => 'text_textfield',
'default_formatter' => 'text_default', 'default_formatter' => 'text_default',
), ),
'text_long' => array( 'text_long' => array(
'label' => t('Long text'), 'label' => t('Long text'),
'description' => t('This field stores long text in the database.'), 'description' => t('This field stores long text in the database.'),
'instance_settings' => array('text_processing' => 0), 'instance_settings' => array('text_processing' => 0),
'default_widget' => 'text_textarea', 'default_widget' => 'text_textarea',
'default_formatter' => 'text_default', 'default_formatter' => 'text_default',
), ),
); );
} }
/** /**
* Implementation of hook_field_schema(). * Implementation of hook_field_schema().
*/ */
function text_field_columns($field) { function text_field_columns($field) {
if ($field['type'] == 'text_long') { if ($field['type'] == 'text_long') {
$columns = array( $columns = array(
'value' => array( 'value' => array(
'type' => 'text', 'type' => 'text',
'size' => 'big', 'size' => 'big',
'not null' => FALSE, 'not null' => FALSE,
), ),
); );
} }
else { else {
$columns = array( $columns = array(
'value' => array( 'value' => array(
'type' => 'varchar', 'type' => 'varchar',
'length' => $field['settings']['max_length'], 'length' => $field['settings']['max_length'],
'not null' => FALSE, 'not null' => FALSE,
), ),
); );
} }
$columns += array( $columns += array(
'format' => array( 'format' => array(
'type' => 'int', 'type' => 'int',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => FALSE, 'not null' => FALSE,
), ),
); );
return $columns; return $columns;
} }
/** /**
* Implementation of hook_field_validate(). * Implementation of hook_field_validate().
*/ */
function text_field_validate($obj_type, $object, $field, $instance, $items, $form) { function text_field_validate($obj_type, $object, $field, $instance, $items, $form) {
if (is_array($items)) { if (is_array($items)) {
foreach ($items as $delta => $item) { foreach ($items as $delta => $item) {
$error_element = isset($item['_error_element']) ? $item['_error_element'] : ''; $error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']); if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
if (!empty($item['value'])) { if (!empty($item['value'])) {
if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) { if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) {
form_set_error($error_element, t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length']))); form_set_error($error_element, t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length'])));
} }
} }
} }
} }
} }
function text_field_sanitize($obj_type, $object, $field, $instance, &$items) { function text_field_sanitize($obj_type, $object, $field, $instance, &$items) {
global $language; global $language;
foreach ($items as $delta => $item) { foreach ($items as $delta => $item) {
// TODO D7 : this code is really node-related. // TODO D7 : this code is really node-related.
if (!empty($instance['settings']['text_processing'])) { if (!empty($instance['settings']['text_processing'])) {
$check = is_null($object) || (isset($object->build_mode) && $object->build_mode == NODE_BUILD_PREVIEW); $check = is_null($object) || (isset($object->build_mode) && $object->build_mode == NODE_BUILD_PREVIEW);
$text = isset($item['value']) ? check_markup($item['value'], $item['format'], isset($object->language) ? $object->language : $language, $check) : ''; $text = isset($item['value']) ? check_markup($item['value'], $item['format'], isset($object->language) ? $object->language : $language, $check) : '';
} }
else { else {
$text = check_plain($item['value']); $text = check_plain($item['value']);
} }
$items[$delta]['safe'] = $text; $items[$delta]['safe'] = $text;
} }
} }
/** /**
* Implementation of hook_field_is_empty(). * Implementation of hook_field_is_empty().
*/ */
function text_field_is_empty($item, $field) { function text_field_is_empty($item, $field) {
if (empty($item['value']) && (string)$item['value'] !== '0') { if (empty($item['value']) && (string)$item['value'] !== '0') {
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
/** /**
* Implementation of hook_field_formatter_info(). * Implementation of hook_field_formatter_info().
*/ */
function text_field_formatter_info() { function text_field_formatter_info() {
return array( return array(
'text_default' => array( 'text_default' => array(
'label' => t('Default'), 'label' => t('Default'),
'field types' => array('text', 'text_long'), 'field types' => array('text', 'text_long'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'text_plain' => array( 'text_plain' => array(
'label' => t('Plain text'), 'label' => t('Plain text'),
'field types' => array('text', 'text_long'), 'field types' => array('text', 'text_long'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'text_trimmed' => array( 'text_trimmed' => array(
'label' => t('Trimmed'), 'label' => t('Trimmed'),
'field types' => array('text', 'text_long'), 'field types' => array('text', 'text_long'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
); );
} }
/** /**
* Theme function for 'default' text field formatter. * Theme function for 'default' text field formatter.
*/ */
function theme_field_formatter_text_default($element) { function theme_field_formatter_text_default($element) {
return $element['#item']['safe']; return $element['#item']['safe'];
} }
/** /**
* Theme function for 'plain' text field formatter. * Theme function for 'plain' text field formatter.
*/ */
function theme_field_formatter_text_plain($element) { function theme_field_formatter_text_plain($element) {
return strip_tags($element['#item']['safe']); return strip_tags($element['#item']['safe']);
} }
/** /**
* Theme function for 'trimmed' text field formatter. * Theme function for 'trimmed' text field formatter.
*/ */
function theme_field_formatter_text_trimmed($element) { function theme_field_formatter_text_trimmed($element) {
$field = field_info_field($element['#field_name']); $field = field_info_field($element['#field_name']);
$instance = field_info_instance($element['#field_name'], $element['#bundle']); $instance = field_info_instance($element['#field_name'], $element['#bundle']);
return $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL; return $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL;
} }
/** /**
* Implementation of hook_field_widget_info(). * Implementation of hook_field_widget_info().
* *
* Here we indicate that the field module will handle * Here we indicate that the field module will handle
* the default value and multiple values for these widgets. * the default value and multiple values for these widgets.
* *
* Callbacks can be omitted if default handing is used. * Callbacks can be omitted if default handing is used.
* They're included here just so this module can be used * They're included here just so this module can be used
* as an example for custom modules that might do things * as an example for custom modules that might do things
* differently. * differently.
*/ */
function text_field_widget_info() { function text_field_widget_info() {
return array( return array(
'text_textfield' => array( 'text_textfield' => array(
'label' => t('Text field'), 'label' => t('Text field'),
'field types' => array('text'), 'field types' => array('text'),
'settings' => array('size' => 60), 'settings' => array('size' => 60),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
'default value' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'text_textarea' => array( 'text_textarea' => array(
'label' => t('Text area (multiple rows)'), 'label' => t('Text area (multiple rows)'),
'field types' => array('text_long'), 'field types' => array('text_long'),
'settings' => array('rows' => 5), 'settings' => array('rows' => 5),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
'default value' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
); );
} }
/** /**
* Implementation of FAPI hook_elements(). * Implementation of FAPI hook_elements().
* *
* Any FAPI callbacks needed for individual widgets can be declared here, * Any FAPI callbacks needed for individual widgets can be declared here,
* and the element will be passed to those callbacks for processing. * and the element will be passed to those callbacks for processing.
* *
* Drupal will automatically theme the element using a theme with * Drupal will automatically theme the element using a theme with
* the same name as the hook_elements key. * the same name as the hook_elements key.
* *
* Autocomplete_path is not used by text_field_widget but other * Autocomplete_path is not used by text_field_widget but other
* widgets can use it (see nodereference and userreference). * widgets can use it (see nodereference and userreference).
*/ */
function text_elements() { function text_elements() {
return array( return array(
'text_textfield' => array( 'text_textfield' => array(
'#input' => TRUE, '#input' => TRUE,
'#columns' => array('value'), '#delta' => 0, '#columns' => array('value'), '#delta' => 0,
'#process' => array('text_textfield_process'), '#process' => array('text_textfield_process'),
'#autocomplete_path' => FALSE, '#autocomplete_path' => FALSE,
), ),
'text_textarea' => array( 'text_textarea' => array(
'#input' => TRUE, '#input' => TRUE,
'#columns' => array('value', 'format'), '#delta' => 0, '#columns' => array('value', 'format'), '#delta' => 0,
'#process' => array('text_textarea_process'), '#process' => array('text_textarea_process'),
'#filter_value' => FILTER_FORMAT_DEFAULT, '#filter_value' => FILTER_FORMAT_DEFAULT,
), ),
); );
} }
/** /**
* Implementation of hook_field_widget(). * Implementation of hook_field_widget().
* *
* Attach a single form element to the form. It will be built out and * 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 * validated in the callback(s) listed in hook_elements. We build it
* out in the callbacks rather than here in hook_field_widget so it can be * out in the callbacks rather than here in hook_field_widget so it can be
* plugged into any module that can provide it with valid * plugged into any module that can provide it with valid
* $field information. * $field information.
* *
* Field module will set the weight, field name and delta values * Field module will set the weight, field name and delta values
* for each form element. * for each form element.
* *
* If there are multiple values for this field, the field module will * If there are multiple values for this field, the field module will
* call this function as many times as needed. * call this function as many times as needed.
* *
* @param $form * @param $form
* the entire form array, $form['#node'] holds node information * the entire form array, $form['#node'] holds node information
* @param $form_state * @param $form_state
* the form_state, $form_state['values'][$field['field_name']] * the form_state, $form_state['values'][$field['field_name']]
* holds the field's form values. * holds the field's form values.
* @param $field * @param $field
* The field structure. * The field structure.
* @param $instance * @param $instance
* the field instance array * the field instance array
* @param $items * @param $items
* array of default values for this field * array of default values for this field
* @param $delta * @param $delta
* the order of this item in the array of subelements (0, 1, 2, etc) * the order of this item in the array of subelements (0, 1, 2, etc)
* *
* @return * @return
* the form item for a single element for this field * the form item for a single element for this field
*/ */
function text_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { function text_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) {
$element = array( $element = array(
'#type' => $instance['widget']['type'], '#type' => $instance['widget']['type'],
'#default_value' => isset($items[$delta]) ? $items[$delta] : '', '#default_value' => isset($items[$delta]) ? $items[$delta] : '',
); );
return $element; return $element;
} }
/** /**
* Process an individual element. * Process an individual element.
* *
* Build the form element. When creating a form using FAPI #process, * Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set. * note that $element['#value'] is already set.
* *
* The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
* *
* TODO: For widgets to be actual FAPI 'elements', reusable outside of a * TODO: For widgets to be actual FAPI 'elements', reusable outside of a
* 'field' context, they shoudn't rely on $field and $instance. The bits of * 'field' context, they shoudn't rely on $field and $instance. The bits of
* information needed to adjust the behavior of the 'element' should be * information needed to adjust the behavior of the 'element' should be
* extracted in hook_field_widget() above. * extracted in hook_field_widget() above.
*/ */
function text_textfield_process($element, $edit, $form_state, $form) { function text_textfield_process($element, $edit, $form_state, $form) {
$field = $form['#fields'][$element['#field_name']]['field']; $field = $form['#fields'][$element['#field_name']]['field'];
$instance = $form['#fields'][$element['#field_name']]['instance']; $instance = $form['#fields'][$element['#field_name']]['instance'];
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
$delta = $element['#delta']; $delta = $element['#delta'];
$element[$field_key] = array( $element[$field_key] = array(
'#type' => 'textfield', '#type' => 'textfield',
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
'#autocomplete_path' => $element['#autocomplete_path'], '#autocomplete_path' => $element['#autocomplete_path'],
'#size' => $instance['widget']['settings']['size'], '#size' => $instance['widget']['settings']['size'],
'#attributes' => array('class' => 'text'), '#attributes' => array('class' => 'text'),
// The following values were set by the field module and need // The following values were set by the field module and need
// to be passed down to the nested element. // to be passed down to the nested element.
'#title' => $element['#title'], '#title' => $element['#title'],
'#description' => $element['#description'], '#description' => $element['#description'],
'#required' => $element['#required'], '#required' => $element['#required'],
'#field_name' => $element['#field_name'], '#field_name' => $element['#field_name'],
'#bundle' => $element['#bundle'], '#bundle' => $element['#bundle'],
'#delta' => $element['#delta'], '#delta' => $element['#delta'],
'#columns' => $element['#columns'], '#columns' => $element['#columns'],
); );
$element[$field_key]['#maxlength'] = !empty($field['settings']['max_length']) ? $field['settings']['max_length'] : NULL; $element[$field_key]['#maxlength'] = !empty($field['settings']['max_length']) ? $field['settings']['max_length'] : NULL;
if (!empty($instance['settings']['text_processing'])) { if (!empty($instance['settings']['text_processing'])) {
$filter_key = $element['#columns'][1]; $filter_key = $element['#columns'][1];
$format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
$parents = array_merge($element['#parents'] , array($filter_key)); $parents = array_merge($element['#parents'] , array($filter_key));
$element[$filter_key] = filter_form($format, 1, $parents); $element[$filter_key] = filter_form($format, 1, $parents);
} }
// Used so that hook_field('validate') knows where to flag an error. // Used so that hook_field('validate') knows where to flag an error.
// TODO: rework that. See http://groups.drupal.org/node/18019. // TODO: rework that. See http://groups.drupal.org/node/18019.
$element['_error_element'] = array( $element['_error_element'] = array(
'#type' => 'value', '#type' => 'value',
'#value' => implode('][', array_merge($element['#parents'], array($field_key))), '#value' => implode('][', array_merge($element['#parents'], array($field_key))),
); );
return $element; return $element;
} }
/** /**
* Process an individual element. * Process an individual element.
* *
* Build the form element. When creating a form using FAPI #process, * Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set. * note that $element['#value'] is already set.
* *
* The $field and $instance arrays are in $form['#fields'][$element['#field_name']]. * The $field and $instance arrays are in $form['#fields'][$element['#field_name']].
*/ */
function text_textarea_process($element, $edit, $form_state, $form) { function text_textarea_process($element, $edit, $form_state, $form) {
$field = $form['#fields'][$element['#field_name']]['field']; $field = $form['#fields'][$element['#field_name']]['field'];
$instance = $form['#fields'][$element['#field_name']]['instance']; $instance = $form['#fields'][$element['#field_name']]['instance'];
$field_key = $element['#columns'][0]; $field_key = $element['#columns'][0];
$delta = $element['#delta']; $delta = $element['#delta'];
$element[$field_key] = array( $element[$field_key] = array(
'#type' => 'textarea', '#type' => 'textarea',
'#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL, '#default_value' => isset($element['#value'][$field_key]) ? $element['#value'][$field_key] : NULL,
'#rows' => $instance['widget']['settings']['rows'], '#rows' => $instance['widget']['settings']['rows'],
'#weight' => 0, '#weight' => 0,
// The following values were set by the field module and need // The following values were set by the field module and need
// to be passed down to the nested element. // to be passed down to the nested element.
'#title' => $element['#title'], '#title' => $element['#title'],
'#description' => $element['#description'], '#description' => $element['#description'],
'#required' => $element['#required'], '#required' => $element['#required'],
'#field_name' => $element['#field_name'], '#field_name' => $element['#field_name'],
'#bundle' => $element['#bundle'], '#bundle' => $element['#bundle'],
'#delta' => $element['#delta'], '#delta' => $element['#delta'],
'#columns' => $element['#columns'], '#columns' => $element['#columns'],
); );
if (!empty($instance['settings']['text_processing'])) { if (!empty($instance['settings']['text_processing'])) {
$filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format'; $filter_key = (count($element['#columns']) == 2) ? $element['#columns'][1] : 'format';
$format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT; $format = isset($element['#value'][$filter_key]) ? $element['#value'][$filter_key] : FILTER_FORMAT_DEFAULT;
$parents = array_merge($element['#parents'] , array($filter_key)); $parents = array_merge($element['#parents'] , array($filter_key));
$element[$filter_key] = filter_form($format, 1, $parents); $element[$filter_key] = filter_form($format, 1, $parents);
} }
// Used so that hook_field('validate') knows where to flag an error. // Used so that hook_field('validate') knows where to flag an error.
$element['_error_element'] = array( $element['_error_element'] = array(
'#type' => 'value', '#type' => 'value',
'#value' => implode('][', array_merge($element['#parents'], array($field_key))), '#value' => implode('][', array_merge($element['#parents'], array($field_key))),
); );
return $element; return $element;
} }
/** /**
* FAPI theme for an individual text elements. * FAPI theme for an individual text elements.
* *
* The textfield or textarea is already rendered by the * The textfield or textarea is already rendered by the
* textfield or textarea themes and the html output * textfield or textarea themes and the html output
* lives in $element['#children']. Override this theme to * lives in $element['#children']. Override this theme to
* make custom changes to the output. * make custom changes to the output.
* *
* $element['#field_name'] contains the field name * $element['#field_name'] contains the field name
* $element['#delta] is the position of this element in the group * $element['#delta] is the position of this element in the group
*/ */
function theme_text_textfield($element) { function theme_text_textfield($element) {
return $element['#children']; return $element['#children'];
} }
function theme_text_textarea($element) { function theme_text_textarea($element) {
return $element['#children']; return $element['#children'];
} }

View File

@ -1,103 +1,103 @@
<?php <?php
$field = array( $field = array(
'field_name' => 'field_single', 'field_name' => 'field_single',
'type' => 'text', 'type' => 'text',
); );
field_create_field($field); field_create_field($field);
$instance = array( $instance = array(
'field_name' => 'field_single', 'field_name' => 'field_single',
'bundle' => 'article', 'bundle' => 'article',
'label' => 'Single', 'label' => 'Single',
'widget' => array( 'widget' => array(
'type' => 'text_textfield', 'type' => 'text_textfield',
), ),
'display' => array( 'display' => array(
'full' => array( 'full' => array(
'label' => 'above', 'label' => 'above',
'type' => 'text_default', 'type' => 'text_default',
'exclude' => 0, 'exclude' => 0,
), ),
), ),
); );
field_create_instance($instance); field_create_instance($instance);
$instance['bundle'] = 'user'; $instance['bundle'] = 'user';
field_create_instance($instance); field_create_instance($instance);
$field = array( $field = array(
'field_name' => 'field_multiple', 'field_name' => 'field_multiple',
'cardinality' => FIELD_CARDINALITY_UNLIMITED, 'cardinality' => FIELD_CARDINALITY_UNLIMITED,
'type' => 'text', 'type' => 'text',
); );
field_create_field($field); field_create_field($field);
$instance = array( $instance = array(
'field_name' => 'field_multiple', 'field_name' => 'field_multiple',
'bundle' => 'article', 'bundle' => 'article',
'label' => 'Multiple', 'label' => 'Multiple',
'widget' => array( 'widget' => array(
'type' => 'text_textfield', 'type' => 'text_textfield',
), ),
'display' => array( 'display' => array(
'full' => array( 'full' => array(
'label' => 'above', 'label' => 'above',
'type' => 'text_default', 'type' => 'text_default',
'exclude' => 0, 'exclude' => 0,
), ),
), ),
); );
field_create_instance($instance); field_create_instance($instance);
$instance['bundle'] = 'user'; $instance['bundle'] = 'user';
field_create_instance($instance); field_create_instance($instance);
// Number // Number
$field = array( $field = array(
'field_name' => 'field_integer', 'field_name' => 'field_integer',
'type' => 'number_integer', 'type' => 'number_integer',
); );
field_create_field($field); field_create_field($field);
$instance = array( $instance = array(
'field_name' => 'field_integer', 'field_name' => 'field_integer',
'bundle' => 'article', 'bundle' => 'article',
'label' => 'Integer', 'label' => 'Integer',
'widget' => array( 'widget' => array(
'type' => 'number', 'type' => 'number',
), ),
'display' => array( 'display' => array(
'full' => array( 'full' => array(
'label' => 'above', 'label' => 'above',
'type' => 'number_integer', 'type' => 'number_integer',
'exclude' => 0, 'exclude' => 0,
), ),
), ),
); );
field_create_instance($instance); field_create_instance($instance);
$field = array( $field = array(
'field_name' => 'field_decimal', 'field_name' => 'field_decimal',
'type' => 'number_decimal', 'type' => 'number_decimal',
); );
field_create_field($field); field_create_field($field);
$instance = array( $instance = array(
'field_name' => 'field_decimal', 'field_name' => 'field_decimal',
'bundle' => 'article', 'bundle' => 'article',
'label' => 'Decimal', 'label' => 'Decimal',
'widget' => array( 'widget' => array(
'type' => 'number', 'type' => 'number',
), ),
'display' => array( 'display' => array(
'full' => array( 'full' => array(
'label' => 'above', 'label' => 'above',
'type' => 'number_decimal', 'type' => 'number_decimal',
'exclude' => 0, 'exclude' => 0,
), ),
), ),
); );
field_create_instance($instance); field_create_instance($instance);

View File

@ -1,3 +1,5 @@
/* $Id$ */
/* Node display */ /* Node display */
.field .field-label, .field .field-label,
.field .field-label-inline, .field .field-label-inline,
@ -27,4 +29,4 @@
.node-form .number { .node-form .number {
display:inline; display:inline;
width:auto; width:auto;
} }

View File

@ -257,10 +257,10 @@ function node_form(&$form_state, $node) {
); );
} }
$form['#validate'][] = 'node_form_validate'; $form['#validate'][] = 'node_form_validate';
$form['#theme'] = array($node->type . '_node_form', 'node_form'); $form['#theme'] = array($node->type . '_node_form', 'node_form');
$form['#builder_function'] = 'node_form_submit_build_node'; $form['#builder_function'] = 'node_form_submit_build_node';
field_attach_form('node', $node, $form, $form_state); field_attach_form('node', $node, $form, $form_state);
return $form; return $form;
} }
@ -468,10 +468,10 @@ function node_form_submit_build_node($form, &$form_state) {
// Unset any button-level handlers, execute all the form-level submit // Unset any button-level handlers, execute all the form-level submit
// functions to process the form values into an updated node. // functions to process the form values into an updated node.
unset($form_state['submit_handlers']); unset($form_state['submit_handlers']);
form_execute_handlers('submit', $form, $form_state); form_execute_handlers('submit', $form, $form_state);
$node = node_submit($form_state['values']); $node = node_submit($form_state['values']);
field_attach_submit('node', $node, $form, $form_state); field_attach_submit('node', $node, $form, $form_state);
$form_state['node'] = (array)$node; $form_state['node'] = (array)$node;
$form_state['rebuild'] = TRUE; $form_state['rebuild'] = TRUE;

View File

@ -20,7 +20,7 @@
* - $terms: the themed list of taxonomy term links output from theme_links(). * - $terms: the themed list of taxonomy term links output from theme_links().
* - $submitted: themed submission information output from * - $submitted: themed submission information output from
* theme_node_submitted(). * theme_node_submitted().
* TODO D7 : document $FIELD_NAME_rendered variables. * TODO D7 : document $FIELD_NAME_rendered variables.
* *
* Other variables: * Other variables:
* - $node: Full node object. Contains data that may not be safe. * - $node: Full node object. Contains data that may not be safe.

View File

@ -2,59 +2,59 @@
// $Id$ // $Id$
/** /**
* Implementation of hook_schema(). * Implementation of hook_schema().
*/ */
function field_test_schema() { function field_test_schema() {
$schema['test_entity'] = array( $schema['test_entity'] = array(
'description' => 'The base table for test_entities.', 'description' => 'The base table for test_entities.',
'fields' => array( 'fields' => array(
'ftid' => array( 'ftid' => array(
'description' => 'The primary identifier for a test_entity.', 'description' => 'The primary identifier for a test_entity.',
'type' => 'serial', 'type' => 'serial',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => TRUE, 'not null' => TRUE,
), ),
'ftvid' => array( 'ftvid' => array(
'description' => 'The current {test_entity_revision}.ftvid version identifier.', 'description' => 'The current {test_entity_revision}.ftvid version identifier.',
'type' => 'int', 'type' => 'int',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => TRUE, 'not null' => TRUE,
'default' => 0, 'default' => 0,
), ),
'fttype' => array( 'fttype' => array(
'description' => 'The type of this test_entity.', 'description' => 'The type of this test_entity.',
'type' => 'varchar', 'type' => 'varchar',
'length' => 32, 'length' => 32,
'not null' => TRUE, 'not null' => TRUE,
'default' => '', 'default' => '',
), ),
), ),
'unique keys' => array( 'unique keys' => array(
'ftvid' => array('ftvid'), 'ftvid' => array('ftvid'),
), ),
'primary key' => array('ftid'), 'primary key' => array('ftid'),
); );
$schema['test_entity_revision'] = array( $schema['test_entity_revision'] = array(
'description' => 'Stores information about each saved version of a {test_entity}.', 'description' => 'Stores information about each saved version of a {test_entity}.',
'fields' => array( 'fields' => array(
'ftid' => array( 'ftid' => array(
'description' => 'The {test_entity} this version belongs to.', 'description' => 'The {test_entity} this version belongs to.',
'type' => 'int', 'type' => 'int',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => TRUE, 'not null' => TRUE,
'default' => 0, 'default' => 0,
), ),
'ftvid' => array( 'ftvid' => array(
'description' => 'The primary identifier for this version.', 'description' => 'The primary identifier for this version.',
'type' => 'serial', 'type' => 'serial',
'unsigned' => TRUE, 'unsigned' => TRUE,
'not null' => TRUE, 'not null' => TRUE,
), ),
), ),
'indexes' => array( 'indexes' => array(
'nid' => array('ftid'), 'nid' => array('ftid'),
), ),
'primary key' => array('ftvid'), 'primary key' => array('ftvid'),
); );
return $schema; return $schema;

View File

@ -3,299 +3,299 @@
define('FIELD_TEST_ELEMENT_ID', 1); define('FIELD_TEST_ELEMENT_ID', 1);
define('FIELD_TEST_BUNDLE', 'test_bundle'); define('FIELD_TEST_BUNDLE', 'test_bundle');
/** /**
* Implementation of hook_perm(). * Implementation of hook_perm().
*/ */
function field_test_perm() { function field_test_perm() {
$perms = array( $perms = array(
'access field_test content' => array( 'access field_test content' => array(
'title' => t('Access field_test content'), 'title' => t('Access field_test content'),
'description' => t('View published field_test content.'), 'description' => t('View published field_test content.'),
), ),
'administer field_test content' => array( 'administer field_test content' => array(
'title' => t('Administer field_test content'), 'title' => t('Administer field_test content'),
'description' => t('Manage field_test content'), 'description' => t('Manage field_test content'),
), ),
); );
return $perms; return $perms;
} }
/** /**
* Implementation of hook_menu(). * Implementation of hook_menu().
*/ */
function field_test_menu() { function field_test_menu() {
$items = array(); $items = array();
$info = field_test_fieldable_info(); $info = field_test_fieldable_info();
foreach (array_keys($info['test_entity']['bundles']) as $bundle) { foreach (array_keys($info['test_entity']['bundles']) as $bundle) {
$bundle_url_str = str_replace('_', '-', $bundle); $bundle_url_str = str_replace('_', '-', $bundle);
$items['test-entity/add/' . $bundle_url_str] = array( $items['test-entity/add/' . $bundle_url_str] = array(
'title' => "Add $bundle test_entity", 'title' => "Add $bundle test_entity",
'page callback' => 'field_test_entity_add', 'page callback' => 'field_test_entity_add',
'page arguments' => array(2), 'page arguments' => array(2),
'access arguments' => array('administer field_test content'), 'access arguments' => array('administer field_test content'),
'type' => MENU_NORMAL_ITEM, 'type' => MENU_NORMAL_ITEM,
); );
} }
$items['test-entity/%field_test_entity/edit'] = array( $items['test-entity/%field_test_entity/edit'] = array(
'title' => 'Edit test entity', 'title' => 'Edit test entity',
'page callback' => 'field_test_entity_edit', 'page callback' => 'field_test_entity_edit',
'page arguments' => array(1), 'page arguments' => array(1),
'access arguments' => array('administer field_test content'), 'access arguments' => array('administer field_test content'),
'type' => MENU_NORMAL_ITEM, 'type' => MENU_NORMAL_ITEM,
); );
return $items; return $items;
} }
/** /**
* *
* 'Field attach' API. * 'Field attach' API.
* *
*/ */
/** /**
* Define a test fieldable entity. * Define a test fieldable entity.
*/ */
function field_test_fieldable_info() { function field_test_fieldable_info() {
$bundles = variable_get('field_test_bundles', array('test_bundle' => 'Test Bundle')); $bundles = variable_get('field_test_bundles', array('test_bundle' => 'Test Bundle'));
return array( return array(
'test_entity' => array( 'test_entity' => array(
'name' => t('Test Entity'), 'name' => t('Test Entity'),
'id key' => 'ftid', 'id key' => 'ftid',
'revision key' => 'ftvid', 'revision key' => 'ftvid',
'cacheable' => FALSE, 'cacheable' => FALSE,
'bundle key' => 'fttype', 'bundle key' => 'fttype',
'bundles' => $bundles, 'bundles' => $bundles,
), ),
// This entity type doesn't get form handling for now... // This entity type doesn't get form handling for now...
'test_cacheable_entity' => array( 'test_cacheable_entity' => array(
'name' => t('Test Entity, cacheable'), 'name' => t('Test Entity, cacheable'),
'id key' => 'ftid', 'id key' => 'ftid',
'revision key' => 'ftvid', 'revision key' => 'ftvid',
'cacheable' => TRUE, 'cacheable' => TRUE,
'bundle key' => 'fttype', 'bundle key' => 'fttype',
'bundles' => $bundles, 'bundles' => $bundles,
), ),
); );
} }
function field_test_create_bundle($bundle, $text) { function field_test_create_bundle($bundle, $text) {
$bundles = variable_get('field_test_bundles', array('field_text_bundle' => 'Test Bundle')); $bundles = variable_get('field_test_bundles', array('field_text_bundle' => 'Test Bundle'));
$bundles += array($bundle => $text); $bundles += array($bundle => $text);
variable_set('field_test_bundles', $bundles); variable_set('field_test_bundles', $bundles);
field_attach_create_bundle($bundle); field_attach_create_bundle($bundle);
} }
function field_test_rename_bundle($bundle_old, $bundle_new) { function field_test_rename_bundle($bundle_old, $bundle_new) {
$bundles = variable_get('field_test_bundles', array('field_text_bundle' => 'Test Bundle')); $bundles = variable_get('field_test_bundles', array('field_text_bundle' => 'Test Bundle'));
$bundles[$bundle_new] = $bundles[$bundle_old]; $bundles[$bundle_new] = $bundles[$bundle_old];
unset($bundles[$bundle_old]); unset($bundles[$bundle_old]);
variable_set('field_test_bundles', $bundles); variable_set('field_test_bundles', $bundles);
field_attach_rename_bundle($bundle_old, $bundle_new); field_attach_rename_bundle($bundle_old, $bundle_new);
} }
function field_test_delete_bundle($bundle) { function field_test_delete_bundle($bundle) {
$bundles = variable_get('field_test_bundles', array('field_text_bundle' => 'Test Bundle')); $bundles = variable_get('field_test_bundles', array('field_text_bundle' => 'Test Bundle'));
unset($bundles[$bundle]); unset($bundles[$bundle]);
variable_set('field_test_bundles', $bundles); variable_set('field_test_bundles', $bundles);
field_attach_delete_bundle($bundle); field_attach_delete_bundle($bundle);
} }
/** /**
* Implementation of hook_field_build_modes(). * Implementation of hook_field_build_modes().
*/ */
function field_test_field_build_modes($obj_type) { function field_test_field_build_modes($obj_type) {
$modes = array(); $modes = array();
if ($obj_type == 'test_entity' || $obj_type == 'test_cacheable_entity') { if ($obj_type == 'test_entity' || $obj_type == 'test_cacheable_entity') {
$modes = array( $modes = array(
'full' => t('Full node'), 'full' => t('Full node'),
'teaser' => t('Teaser'), 'teaser' => t('Teaser'),
); );
} }
return $modes; return $modes;
} }
/** /**
* Helper function to create a basic 'test entity' structure. * Helper function to create a basic 'test entity' structure.
* *
* TODO : do we stil need this now that we can actualy load and save test_entities ? * TODO : do we stil need this now that we can actualy load and save test_entities ?
*/ */
function field_test_create_stub_entity($id = 1, $vid = 1, $bundle = FIELD_TEST_BUNDLE) { function field_test_create_stub_entity($id = 1, $vid = 1, $bundle = FIELD_TEST_BUNDLE) {
$entity = new stdClass(); $entity = new stdClass();
$entity->ftid = $id; $entity->ftid = $id;
$entity->ftvid = $vid; $entity->ftvid = $vid;
$entity->fttype = $bundle; $entity->fttype = $bundle;
return $entity; return $entity;
} }
function field_test_entity_load($ftid, $ftvid = NULL) { function field_test_entity_load($ftid, $ftvid = NULL) {
// Load basic strucure. // Load basic strucure.
$query = db_select('test_entity', 'fte', array()) $query = db_select('test_entity', 'fte', array())
->fields('fte') ->fields('fte')
->condition('ftid', $ftid); ->condition('ftid', $ftid);
if ($ftvid) { if ($ftvid) {
$query->condition('ftvid', $ftvid); $query->condition('ftvid', $ftvid);
} }
$entities = $query->execute()->fetchAllAssoc('ftid'); $entities = $query->execute()->fetchAllAssoc('ftid');
// Attach fields. // Attach fields.
if ($ftvid) { if ($ftvid) {
field_attach_load_revision('test_entity', $entities); field_attach_load_revision('test_entity', $entities);
} }
else { else {
field_attach_load('test_entity', $entities); field_attach_load('test_entity', $entities);
} }
return $entities[$ftid]; return $entities[$ftid];
} }
function field_test_entity_save(&$entity) { function field_test_entity_save(&$entity) {
field_attach_presave('test_entity', $entity); field_attach_presave('test_entity', $entity);
$entity->is_new = FALSE; $entity->is_new = FALSE;
if (empty($entity->ftid)) { if (empty($entity->ftid)) {
// Insert a new test_entity. // Insert a new test_entity.
$entity->is_new = TRUE; $entity->is_new = TRUE;
} }
elseif (!empty($entity->revision)) { elseif (!empty($entity->revision)) {
$entity->old_ftvid = $entity->ftvid; $entity->old_ftvid = $entity->ftvid;
} }
$update_entity = TRUE; $update_entity = TRUE;
if ($entity->is_new) { if ($entity->is_new) {
drupal_write_record('test_entity', $entity); drupal_write_record('test_entity', $entity);
drupal_write_record('test_entity_revision', $entity); drupal_write_record('test_entity_revision', $entity);
$op = 'insert'; $op = 'insert';
} }
else { else {
drupal_write_record('test_entity', $entity, 'ftid'); drupal_write_record('test_entity', $entity, 'ftid');
if (!empty($entity->revision)) { if (!empty($entity->revision)) {
drupal_write_record('test_entity_revision', $entity); drupal_write_record('test_entity_revision', $entity);
} }
else { else {
drupal_write_record('test_entity_revision', $entity, 'ftvid'); drupal_write_record('test_entity_revision', $entity, 'ftvid');
$update_entity = FALSE; $update_entity = FALSE;
} }
$op = 'update'; $op = 'update';
} }
if ($update_entity) { if ($update_entity) {
db_update('test_entity') db_update('test_entity')
->fields(array('ftvid' => $entity->ftvid)) ->fields(array('ftvid' => $entity->ftvid))
->condition('ftid', $entity->ftid) ->condition('ftid', $entity->ftid)
->execute(); ->execute();
} }
// Save fields. // Save fields.
$function = "field_attach_$op"; $function = "field_attach_$op";
$function('test_entity', $entity); $function('test_entity', $entity);
} }
function field_test_entity_add($fttype) { function field_test_entity_add($fttype) {
$fttype = str_replace('-', '_', $fttype); $fttype = str_replace('-', '_', $fttype);
$entity = (object)array('fttype' => $fttype); $entity = (object)array('fttype' => $fttype);
drupal_set_title(t('Create test_entity @bundle', array('@bundle' => $fttype)), PASS_THROUGH); drupal_set_title(t('Create test_entity @bundle', array('@bundle' => $fttype)), PASS_THROUGH);
return drupal_get_form('field_test_entity_form', $entity); return drupal_get_form('field_test_entity_form', $entity);
} }
function field_test_entity_edit($entity) { function field_test_entity_edit($entity) {
drupal_set_title(t('test_entity @ftid revision @ftvid', array('@ftid' => $entity->ftid, '@ftvid' => $entity->ftvid)), PASS_THROUGH); drupal_set_title(t('test_entity @ftid revision @ftvid', array('@ftid' => $entity->ftid, '@ftvid' => $entity->ftvid)), PASS_THROUGH);
return drupal_get_form('field_test_entity_form', $entity); return drupal_get_form('field_test_entity_form', $entity);
} }
/** /**
* Form to set the value of fields attached to our entity. * Form to set the value of fields attached to our entity.
*/ */
function field_test_entity_form(&$form_state, $entity) { function field_test_entity_form(&$form_state, $entity) {
$form = array(); $form = array();
if (isset($form_state['test_entity'])) { if (isset($form_state['test_entity'])) {
$entity = $form_state['test_entity'] + (array)$entity; $entity = $form_state['test_entity'] + (array)$entity;
} }
$entity = (object)$entity; $entity = (object)$entity;
foreach (array('ftid', 'ftvid', 'fttype') as $key) { foreach (array('ftid', 'ftvid', 'fttype') as $key) {
$form[$key] = array( $form[$key] = array(
'#type' => 'value', '#type' => 'value',
'#value' => isset($entity->$key) ? $entity->$key : NULL, '#value' => isset($entity->$key) ? $entity->$key : NULL,
); );
} }
// Add field widgets. // Add field widgets.
$form['#builder_function'] = 'field_test_entity_form_submit_builder'; $form['#builder_function'] = 'field_test_entity_form_submit_builder';
field_attach_form('test_entity', $entity, $form, $form_state); field_attach_form('test_entity', $entity, $form, $form_state);
$form['revision'] = array( $form['revision'] = array(
'#access' => user_access('administer field_test content'), '#access' => user_access('administer field_test content'),
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => t('Create new revision'), '#title' => t('Create new revision'),
'#default_value' => FALSE, '#default_value' => FALSE,
'#weight' => 100, '#weight' => 100,
); );
$form['submit'] = array( $form['submit'] = array(
'#type' => 'submit', '#type' => 'submit',
'#value' => t('Save'), '#value' => t('Save'),
'#weight' => 101, '#weight' => 101,
); );
return $form; return $form;
} }
/** /**
* Validate handler for field_test_set_field_values(). * Validate handler for field_test_set_field_values().
*/ */
function field_test_entity_form_validate($form, &$form_state) { function field_test_entity_form_validate($form, &$form_state) {
$entity = (object)$form_state['values']; $entity = (object)$form_state['values'];
field_attach_validate('test_entity', $entity, $form); field_attach_validate('test_entity', $entity, $form);
} }
/** /**
* Submit handler for field_test_set_field_values(). * Submit handler for field_test_set_field_values().
*/ */
function field_test_entity_form_submit($form, &$form_state) { function field_test_entity_form_submit($form, &$form_state) {
$entity = field_test_entity_form_submit_builder($form, $form_state); $entity = field_test_entity_form_submit_builder($form, $form_state);
$insert = empty($entity->ftid); $insert = empty($entity->ftid);
field_test_entity_save($entity); field_test_entity_save($entity);
$message = $insert ? t('test_entity @id has been created.', array('@id' => $entity->ftid)) : t('test_entity @id has been updated.', array('@id' => $entity->ftid)); $message = $insert ? t('test_entity @id has been created.', array('@id' => $entity->ftid)) : t('test_entity @id has been updated.', array('@id' => $entity->ftid));
drupal_set_message($message); drupal_set_message($message);
if ($entity->ftid) { if ($entity->ftid) {
unset($form_state['rebuild']); unset($form_state['rebuild']);
$form_state['redirect'] = 'test-entity/' . $entity->ftid . '/edit'; $form_state['redirect'] = 'test-entity/' . $entity->ftid . '/edit';
} }
else { else {
// Error on save. // Error on save.
drupal_set_message(t('The entity could not be saved.'), 'error'); drupal_set_message(t('The entity could not be saved.'), 'error');
} }
} }
/** /**
* Build a test_entity by processing submitted form values and prepare for a form rebuild. * Build a test_entity by processing submitted form values and prepare for a form rebuild.
*/ */
function field_test_entity_form_submit_builder($form, &$form_state) { function field_test_entity_form_submit_builder($form, &$form_state) {
$entity = field_test_create_stub_entity($form_state['values']['ftid'], $form_state['values']['ftvid'], $form_state['values']['fttype']); $entity = field_test_create_stub_entity($form_state['values']['ftid'], $form_state['values']['ftvid'], $form_state['values']['fttype']);
field_attach_submit('test_entity', $entity, $form, $form_state); field_attach_submit('test_entity', $entity, $form, $form_state);
$form_state['test_entity'] = (array)$entity; $form_state['test_entity'] = (array)$entity;
$form_state['rebuild'] = TRUE; $form_state['rebuild'] = TRUE;
return $entity; return $entity;
} }
/** /**
* *
* 'Field type' API. * 'Field type' API.
* *
*/ */
/** /**
* Implementation of hook_field_info(). * Implementation of hook_field_info().
@ -327,11 +327,11 @@ function field_test_field_columns($field) {
return $columns; return $columns;
} }
/** /**
* Implementation of hook_instance_settings(). * Implementation of hook_instance_settings().
*/ */
function field_test_field_instance_settings($field_type) { function field_test_field_instance_settings($field_type) {
return array('test_instance_setting' => 'dummy test string'); return array('test_instance_setting' => 'dummy test string');
} }
/** /**
@ -395,8 +395,8 @@ function field_test_field_widget_info() {
'field types' => array('test_field'), 'field types' => array('test_field'),
'settings' => array('test_widget_setting_multiple' => 'dummy test string'), 'settings' => array('test_widget_setting_multiple' => 'dummy test string'),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM, 'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'default value' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
); );
@ -436,31 +436,31 @@ function field_test_field_widget_info() {
* the form item for a single element for this field * the form item for a single element for this field
*/ */
function field_test_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) { function field_test_field_widget(&$form, &$form_state, $field, $instance, $items, $delta = 0) {
$element = array( $element = array(
'value' => array( 'value' => array(
'#title' => $instance['label'], '#title' => $instance['label'],
'#type' => 'textfield', '#type' => 'textfield',
'#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '', '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : '',
'#required' => $instance['required'], '#required' => $instance['required'],
), ),
); );
return $element; return $element;
} }
/** /**
* Implementation of hook_field_formatter_info(). * Implementation of hook_field_formatter_info().
*/ */
function field_test_field_formatter_info() { function field_test_field_formatter_info() {
return array( return array(
'field_test_default' => array( 'field_test_default' => array(
'label' => t('Default'), 'label' => t('Default'),
'field types' => array('test_field'), 'field types' => array('test_field'),
'settings' => array( 'settings' => array(
'test_formatter_setting' => 'dummy test string', 'test_formatter_setting' => 'dummy test string',
), ),
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
), ),
), ),
'field_test_multiple' => array( 'field_test_multiple' => array(
'label' => t('Default'), 'label' => t('Default'),
@ -471,32 +471,32 @@ function field_test_field_formatter_info() {
'behaviors' => array( 'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM, 'multiple values' => FIELD_BEHAVIOR_CUSTOM,
), ),
), ),
); );
} }
/**
* Implementation of hook_theme().
*/
function field_test_theme() {
return array(
'field_formatter_field_test_default' => array(
'arguments' => array('element' => NULL),
),
'field_formatter_field_test_multiple' => array(
'arguments' => array('element' => NULL),
),
);
}
/** /**
* Theme function for 'field_test_default' formatter. * Implementation of hook_theme().
*/ */
function field_test_theme() {
return array(
'field_formatter_field_test_default' => array(
'arguments' => array('element' => NULL),
),
'field_formatter_field_test_multiple' => array(
'arguments' => array('element' => NULL),
),
);
}
/**
* Theme function for 'field_test_default' formatter.
*/
function theme_field_formatter_field_test_default($element) { function theme_field_formatter_field_test_default($element) {
$value = $element['#item']['value']; $value = $element['#item']['value'];
$settings = $element['#settings']; $settings = $element['#settings'];
return $settings['test_formatter_setting'] . '|' . $value; return $settings['test_formatter_setting'] . '|' . $value;
} }
/** /**

View File

@ -38,7 +38,7 @@
* Available variables: * Available variables:
* - $user_profile: All user profile data. Ready for print. * - $user_profile: All user profile data. Ready for print.
* - $profile: Keyed array of profile categories and their items or other data * - $profile: Keyed array of profile categories and their items or other data
* provided by modules. * provided by modules.
* - TODO D7 : document $FIELD_NAME_rendered variables. * - TODO D7 : document $FIELD_NAME_rendered variables.
* *
* @see template_preprocess_user_profile() * @see template_preprocess_user_profile()