Index: modules/field/field.attach.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.attach.inc,v retrieving revision 1.97 diff -u -p -r1.97 field.attach.inc --- modules/field/field.attach.inc 20 Nov 2010 19:57:01 -0000 1.97 +++ modules/field/field.attach.inc 27 Nov 2010 21:09:04 -0000 @@ -188,8 +188,14 @@ function _field_invoke($op, $entity_type foreach ($instances as $instance) { $field_name = $instance['field_name']; $field = field_info_field($field_name); - $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op; - if (function_exists($function)) { + $function = FALSE; + if ($options['default']) { + $function = 'field_default_' . $op; + } + elseif (module_hook($field['module'], 'field_' . $op)) { + $function = $field['module'] . '_field_' . $op; + } + if ($function) { // Determine the list of languages to iterate on. $available_languages = field_available_languages($entity_type, $field); $languages = _field_language_suggestion($available_languages, $options['language'], $field_name); @@ -298,8 +304,14 @@ function _field_invoke_multiple($op, $en $field_id = $instance['field_id']; $field_name = $instance['field_name']; $field = $field_info[$field_id]; - $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op; - if (function_exists($function)) { + $function = FALSE; + if ($options['default']) { + $function = 'field_default_' . $op; + } + elseif (module_hook($field['module'], 'field_' . $op)) { + $function = $field['module'] . '_field_' . $op; + } + if ($function) { // Add the field to the list of fields to invoke the hook on. if (!isset($fields[$field_id])) { $fields[$field_id] = $field; @@ -325,7 +337,13 @@ function _field_invoke_multiple($op, $en // For each field, invoke the field hook and collect results. foreach ($fields as $field_id => $field) { $field_name = $field['field_name']; - $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op; + $function = FALSE; + if ($options['default']) { + $function = 'field_default_' . $op; + } + elseif (module_hook($field['module'], 'field_' . $op)) { + $function = $field['module'] . '_field_' . $op; + } // Iterate over all the field translations. foreach ($grouped_items[$field_id] as $langcode => $items) { $results = $function($entity_type, $grouped_entities[$field_id], $field, $grouped_instances[$field_id], $langcode, $grouped_items[$field_id][$langcode], $a, $b); Index: modules/field/field.default.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.default.inc,v retrieving revision 1.41 diff -u -p -r1.41 field.default.inc --- modules/field/field.default.inc 21 Nov 2010 19:09:18 -0000 1.41 +++ modules/field/field.default.inc 27 Nov 2010 21:09:04 -0000 @@ -157,8 +157,8 @@ function field_default_prepare_view($ent foreach ($modules as $module) { // Invoke hook_field_formatter_prepare_view(). - $function = $module . '_field_formatter_prepare_view'; - if (function_exists($function)) { + if (module_hook($module, 'field_formatter_prepare_view')) { + $function = $module . '_field_formatter_prepare_view'; $function($entity_type, $grouped_entities[$module], $field, $grouped_instances[$module], $langcode, $grouped_items[$module], $grouped_displays[$module]); } } @@ -203,8 +203,8 @@ function field_default_view($entity_type if ($display['type'] !== 'hidden') { // Calling the formatter function through module_invoke() can have a // performance impact on pages with many fields and values. - $function = $display['module'] . '_field_formatter_view'; - if (function_exists($function)) { + if (module_hook($display['module'], 'field_formatter_view')) { + $function = $display['module'] . '_field_formatter_view'; $elements = $function($entity_type, $entity, $field, $instance, $langcode, $items, $display); if ($elements) { Index: modules/field/field.form.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.form.inc,v retrieving revision 1.54 diff -u -p -r1.54 field.form.inc --- modules/field/field.form.inc 20 Nov 2010 19:57:01 -0000 1.54 +++ modules/field/field.form.inc 27 Nov 2010 21:09:04 -0000 @@ -61,8 +61,8 @@ function field_default_form($entity_type // make it the $delta value. else { $delta = isset($get_delta) ? $get_delta : 0; - $function = $instance['widget']['module'] . '_field_widget_form'; - if (function_exists($function)) { + if (module_hook($instance['widget']['module'], 'field_widget_form')) { + $function = $instance['widget']['module'] . '_field_widget_form'; $element = array( '#entity_type' => $instance['entity_type'], '#bundle' => $instance['bundle'], @@ -160,8 +160,8 @@ function field_multiple_value_form($fiel $field_elements = array(); - $function = $instance['widget']['module'] . '_field_widget_form'; - if (function_exists($function)) { + if (module_hook($instance['widget']['module'], 'field_widget_form')) { + $function = $instance['widget']['module'] . '_field_widget_form'; for ($delta = 0; $delta <= $max; $delta++) { $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED; $element = array( @@ -337,7 +337,7 @@ function field_default_form_errors($enti if (!empty($field_state['errors'])) { $function = $instance['widget']['module'] . '_field_widget_error'; - $function_exists = function_exists($function); + $function_exists = module_hook($instance['widget']['module'], 'field_widget_error'); // Locate the correct element in the the form. $element = drupal_array_get_nested_value($form_state['complete form'], $field_state['array_parents']); Index: modules/field/field.module =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.module,v retrieving revision 1.90 diff -u -p -r1.90 field.module --- modules/field/field.module 21 Nov 2010 19:09:18 -0000 1.90 +++ modules/field/field.module 27 Nov 2010 21:09:04 -0000 @@ -110,6 +110,102 @@ define('FIELD_LOAD_REVISION', 'FIELD_LOA class FieldUpdateForbiddenException extends FieldException {} /** + * Implements hook_hook_info(). + */ +function field_hook_info() { + $field_hooks = array( + 'field_access', + 'field_attach_create_bundle', + 'field_attach_delete', + 'field_attach_delete_bundle', + 'field_attach_delete_revision', + 'field_attach_form', + 'field_attach_insert', + 'field_attach_load', + 'field_attach_prepare_translation_alter', + 'field_attach_preprocess_alter', + 'field_attach_presave', + 'field_attach_purge', + 'field_attach_rename_bundle', + 'field_attach_submit', + 'field_attach_update', + 'field_attach_validate', + 'field_attach_view_alter', + 'field_available_languages_alter', + 'field_create_field', + 'field_create_instance', + 'field_delete', + 'field_delete_field', + 'field_delete_instance', + 'field_delete_revision', + 'field_display_alter', + // @todo http://drupal.org/node/968264 + 'field_display_ENTITY_TYPE_alter', + 'field_extra_fields', + 'field_extra_fields_alter', + 'field_extra_fields_display_alter', + 'field_formatter_info', + 'field_formatter_info_alter', + 'field_formatter_prepare_view', + 'field_formatter_settings_form', + 'field_formatter_settings_summary', + 'field_formatter_view', + 'field_info', + 'field_info_alter', + 'field_info_max_weight', + 'field_insert', + 'field_instance_settings_form', + 'field_is_empty', + 'field_language_alter', + 'field_load', + 'field_prepare_translation', + 'field_prepare_view', + 'field_presave', + 'field_purge_field', + 'field_purge_field_instance', + 'field_read_field', + 'field_read_instance', + 'field_settings_form', + 'field_storage_create_field', + 'field_storage_delete', + 'field_storage_delete_field', + 'field_storage_delete_instance', + 'field_storage_delete_revision', + 'field_storage_details', + 'field_storage_details_alter', + 'field_storage_info', + 'field_storage_info_alter', + 'field_storage_load', + 'field_storage_pre_insert', + 'field_storage_pre_load', + 'field_storage_pre_update', + 'field_storage_purge', + 'field_storage_purge_field', + 'field_storage_purge_field_instance', + 'field_storage_query', + 'field_storage_update_field', + 'field_storage_write', + 'field_update', + 'field_update_field', + 'field_update_forbid', + 'field_update_instance', + 'field_validate', + 'field_widget_error', + 'field_widget_form', + 'field_widget_info', + 'field_widget_info_alter', + 'field_widget_properties_alter', + // @todo http://drupal.org/node/968264 + 'field_widget_properties_ENTITY_TYPE_alter', + 'field_widget_settings_form', + ); + $hooks = array_fill_keys($field_hooks, array( + 'group' => 'field', + )); + return $hooks; +} + +/** * Implements hook_flush_caches(). */ function field_flush_caches() { @@ -286,8 +382,8 @@ function field_get_default_value($entity * the array keys to ensure sequential deltas. */ function _field_filter_items($field, $items) { + module_hook($field['module'], 'field_is_empty'); $function = $field['module'] . '_field_is_empty'; - function_exists($function); foreach ((array) $items as $delta => $item) { // Explicitly break if the function is undefined. if ($function($item, $field)) { Index: modules/field_ui/field_ui.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.admin.inc,v retrieving revision 1.86 diff -u -p -r1.86 field_ui.admin.inc --- modules/field_ui/field_ui.admin.inc 21 Nov 2010 07:28:39 -0000 1.86 +++ modules/field_ui/field_ui.admin.inc 27 Nov 2010 21:09:04 -0000 @@ -1538,9 +1538,9 @@ function field_ui_field_settings_form($f // responsible for not returning settings that cannot be changed if // the field already has data. $form['field']['settings'] = array(); - $additions = module_invoke($field['module'], 'field_settings_form', $field, $instance, $has_data); - if (is_array($additions)) { - $form['field']['settings'] = $additions; + if (module_hook($field['module'], 'field_settings_form')) { + $function = $field['module'] . '_field_settings_form'; + $form['field']['settings'] = $function($field, $instance, $has_data, $form, $form_state); } if (empty($form['field']['settings'])) { $form['field']['settings'] = array( @@ -1814,15 +1814,17 @@ function field_ui_field_edit_form($form, ); // Add additional field instance settings from the field module. - $additions = module_invoke($field['module'], 'field_instance_settings_form', $field, $instance); - if (is_array($additions)) { - $form['instance']['settings'] = $additions; + $form['instance']['settings'] = array(); + if (module_hook($field['module'], 'field_instance_settings_form')) { + $function = $field['module'] . '_field_instance_settings_form'; + $form['instance']['settings'] = $function($field, $instance, $form, $form_state); } // Add additional widget settings from the widget module. - $additions = module_invoke($widget_type['module'], 'field_widget_settings_form', $field, $instance); - if (is_array($additions)) { - $form['instance']['widget']['settings'] = $additions; + $form['instance']['widget']['settings'] = array(); + if (module_hook($widget_type['module'], 'field_widget_settings_form')) { + $function = $widget_type['module'] . '_field_widget_settings_form'; + $form['instance']['widget']['settings'] = $function($field, $instance, $form, $form_state); $form['instance']['widget']['active']['#value'] = 1; } @@ -1863,9 +1865,10 @@ function field_ui_field_edit_form($form, // Add additional field type settings. The field type module is // responsible for not returning settings that cannot be changed if // the field already has data. - $additions = module_invoke($field['module'], 'field_settings_form', $field, $instance, $has_data); - if (is_array($additions)) { - $form['field']['settings'] = $additions; + $form['field']['settings'] = array(); + if (module_hook($field['module'], 'field_settings_form')) { + $function = $field['module'] . '_field_settings_form'; + $form['field']['settings'] = $function($field, $instance, $has_data, $form, $form_state); } $form['actions'] = array('#type' => 'actions'); Index: modules/field_ui/field_ui.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.api.php,v retrieving revision 1.10 diff -u -p -r1.10 field_ui.api.php --- modules/field_ui/field_ui.api.php 12 Nov 2010 03:10:38 -0000 1.10 +++ modules/field_ui/field_ui.api.php 27 Nov 2010 21:09:04 -0000 @@ -32,11 +32,15 @@ * The instance structure being configured. * @param $has_data * TRUE if the field already has data, FALSE if not. + * @param $complete_form + * The form structure of field_ui_field_edit_form(). + * @param $form_state + * The current state of the form. * * @return * The form definition for the field settings. */ -function hook_field_settings_form($field, $instance, $has_data) { +function hook_field_settings_form($field, $instance, $has_data, $complete_form, &$form_state) { $settings = $field['settings']; $form['max_length'] = array( '#type' => 'textfield', @@ -59,11 +63,15 @@ function hook_field_settings_form($field * The field structure being configured. * @param $instance * The instance structure being configured. + * @param $complete_form + * The form structure of field_ui_field_edit_form(). + * @param $form_state + * The current state of the form. * * @return * The form definition for the field instance settings. */ -function hook_field_instance_settings_form($field, $instance) { +function hook_field_instance_settings_form($field, $instance, $complete_form, &$form_state) { $settings = $instance['settings']; $form['text_processing'] = array( @@ -101,11 +109,15 @@ function hook_field_instance_settings_fo * The field structure being configured. * @param $instance * The instance structure being configured. + * @param $complete_form + * The form structure of field_ui_field_edit_form(). + * @param $form_state + * The current state of the form. * * @return * The form definition for the widget settings. */ -function hook_field_widget_settings_form($field, $instance) { +function hook_field_widget_settings_form($field, $instance, $complete_form, &$form_state) { $widget = $instance['widget']; $settings = $widget['settings']; Index: modules/file/file.field.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/file/file.field.inc,v retrieving revision 1.41 diff -u -p -r1.41 file.field.inc --- modules/file/file.field.inc 22 Nov 2010 04:42:09 -0000 1.41 +++ modules/file/file.field.inc 27 Nov 2010 21:11:12 -0000 @@ -72,9 +75,13 @@ function file_field_settings_form($field /** * Implements hook_field_instance_settings_form(). */ -function file_field_instance_settings_form($field, $instance) { +function file_field_instance_settings_form($field, $instance, $complete_form, &$form_state) { $settings = $instance['settings']; + // #element_validate handlers are defined in this file, so ensure that it is + // loaded when the form is processed from cache. + form_load_include($form_state, 'inc', 'file', 'file.field'); + $form['file_directory'] = array( '#type' => 'textfield', '#title' => t('File directory'), @@ -486,6 +493,9 @@ function file_field_widget_form(&$form, // Allows this field to return an array instead of a single value. '#extended' => TRUE, ); + // file_field_widget_process() is defined in this file, so ensure that it is + // loaded when the form is processed. + form_load_include($form_state, 'inc', 'file', 'file.field'); if ($field['cardinality'] == 1) { // If there's only one field, return it as delta 0. Index: modules/file/file.module =================================================================== RCS file: /cvs/drupal/drupal/modules/file/file.module,v retrieving revision 1.47 diff -u -p -r1.47 file.module --- modules/file/file.module 23 Nov 2010 05:51:16 -0000 1.47 +++ modules/file/file.module 27 Nov 2010 21:09:04 -0000 @@ -6,9 +6,6 @@ * Defines a "managed_file" Form API field and a "file" field for Field module. */ -// Load all Field module hooks for File. -require_once DRUPAL_ROOT . '/modules/file/file.field.inc'; - /** * Implements hook_help(). */ Index: modules/image/image.field.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/image/image.field.inc,v retrieving revision 1.34 diff -u -p -r1.34 image.field.inc --- modules/image/image.field.inc 31 Oct 2010 12:12:00 -0000 1.34 +++ modules/image/image.field.inc 27 Nov 2010 21:11:44 -0000 @@ -6,6 +6,10 @@ * Implement an image field, based on the file module's file field. */ +// Image field depends on file field, so all field hook implementations of File +// module need to be loaded. +require_once DRUPAL_ROOT . '/modules/file/file.field.inc'; + /** * Implements hook_field_info(). */ @@ -67,11 +71,15 @@ function image_field_settings_form($fiel /** * Implements hook_field_instance_settings_form(). */ -function image_field_instance_settings_form($field, $instance) { +function image_field_instance_settings_form($field, $instance, $complete_form, &$form_state) { $settings = $instance['settings']; // Use the file field instance settings form as a basis. - $form = file_field_instance_settings_form($field, $instance); + $form = file_field_instance_settings_form($field, $instance, $complete_form, $form_state); + + // #element_validate handlers are defined in this file, so ensure that it is + // loaded when the form is processed from cache. + form_load_include($form_state, 'inc', 'image', 'image.field'); // Add maximum and minimum resolution settings. $max_resolution = explode('x', $settings['max_resolution']) + array('', ''); @@ -267,12 +275,12 @@ function image_field_widget_info() { /** * Implements hook_field_widget_settings_form(). */ -function image_field_widget_settings_form($field, $instance) { +function image_field_widget_settings_form($field, $instance, $complete_form, &$form_state) { $widget = $instance['widget']; $settings = $widget['settings']; // Use the file widget settings form. - $form = file_field_widget_settings_form($field, $instance); + $form = file_field_widget_settings_form($field, $instance, $complete_form, $form_state); $form['preview_image_style'] = array( '#title' => t('Preview image style'), @@ -313,6 +321,9 @@ function image_field_widget_form(&$form, // Add all extra functionality provided by the image widget. $elements[$delta]['#process'][] = 'image_field_widget_process'; } + // image_field_widget_process() is defined in this file, so ensure that it is + // loaded when the form is processed. + form_load_include($form_state, 'inc', 'image', 'image.field'); if ($field['cardinality'] == 1) { // If there's only one field, return it as delta 0. Index: modules/image/image.module =================================================================== RCS file: /cvs/drupal/drupal/modules/image/image.module,v retrieving revision 1.54 diff -u -p -r1.54 image.module --- modules/image/image.module 18 Nov 2010 05:36:27 -0000 1.54 +++ modules/image/image.module 27 Nov 2010 21:09:04 -0000 @@ -31,9 +31,6 @@ define('IMAGE_STORAGE_EDITABLE', IMAGE_S */ define('IMAGE_STORAGE_MODULE', IMAGE_STORAGE_OVERRIDE | IMAGE_STORAGE_DEFAULT); -// Load all Field module hooks for Image. -require_once DRUPAL_ROOT . '/modules/image/image.field.inc'; - /** * Implement of hook_help(). */