diff options
author | Dries Buytaert <dries@buytaert.net> | 2009-10-13 16:38:43 +0000 |
---|---|---|
committer | Dries Buytaert <dries@buytaert.net> | 2009-10-13 16:38:43 +0000 |
commit | fbfa7a4150a40d6df9347692bb6681f45f804c7d (patch) | |
tree | 425db0f6cc7b72b8a9350c5a462fe718e0ed2877 /includes | |
parent | f67e438b4196a6bc79c0da576da0a9e09fedb612 (diff) | |
download | brdo-fbfa7a4150a40d6df9347692bb6681f45f804c7d.tar.gz brdo-fbfa7a4150a40d6df9347692bb6681f45f804c7d.tar.bz2 |
- Patch #593522 by sun: a better and faster drupal_alter().
Diffstat (limited to 'includes')
-rw-r--r-- | includes/common.inc | 83 | ||||
-rw-r--r-- | includes/form.inc | 19 |
2 files changed, 46 insertions, 56 deletions
diff --git a/includes/common.inc b/includes/common.inc index 118953c53..8993047c6 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -4250,52 +4250,51 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1) } /** - * Hands off structured Drupal arrays to type-specific *_alter implementations. + * Hands off alterable variables to type-specific *_alter implementations. * - * This dispatch function hands off structured Drupal arrays to type-specific - * *_alter implementations. It ensures a consistent interface for all altering - * operations. + * This dispatch function hands off the passed in variables to type-specific + * hook_TYPE_alter() implementations in modules. It ensures a consistent + * interface for all altering operations. + * + * A maximum of 2 alterable arguments is supported. In case more arguments need + * to be passed and alterable, modules provide additional variables assigned by + * reference in the last $context argument: + * @code + * $context = array( + * 'alterable' => &$alterable, + * 'unalterable' => $unalterable, + * 'foo' => 'bar', + * ); + * drupal_alter('mymodule_data', $alterable1, $alterable2, $context); + * @endcode + * + * Note that objects are always passed by reference in PHP5. If it is absolutely + * required that no implementation alters a passed object in $context, then an + * object needs to be cloned: + * @code + * $context = array( + * 'unalterable_object' => clone $object, + * ); + * drupal_alter('mymodule_data', $data, $context); + * @endcode * * @param $type - * The data type of the structured array. 'form', 'links', + * A string describing the data type of the alterable $data. 'form', 'links', * 'node_content', and so on are several examples. - * @param $data - * The structured array to be altered. - * @param ... - * Any additional params will be passed on to the called - * hook_$type_alter functions. - */ -function drupal_alter($type, &$data) { - // PHP's func_get_args() always returns copies of params, not references, so - // drupal_alter() can only manipulate data that comes in via the required first - // param. For the edge case functions that must pass in an arbitrary number of - // alterable parameters (hook_form_alter() being the best example), an array of - // those params can be placed in the __drupal_alter_by_ref key of the $data - // array. This is somewhat ugly, but is an unavoidable consequence of a flexible - // drupal_alter() function, and the limitations of func_get_args(). - // @todo: Remove this in Drupal 7. - if (is_array($data) && isset($data['__drupal_alter_by_ref'])) { - $by_ref_parameters = $data['__drupal_alter_by_ref']; - unset($data['__drupal_alter_by_ref']); - } - - // Hang onto a reference to the data array so that it isn't blown away later. - // Also, merge in any parameters that need to be passed by reference. - $args = array(&$data); - if (isset($by_ref_parameters)) { - $args = array_merge($args, $by_ref_parameters); - } - - // Now, use func_get_args() to pull in any additional parameters passed into - // the drupal_alter() call. - $additional_args = func_get_args(); - array_shift($additional_args); - array_shift($additional_args); - $args = array_merge($args, $additional_args); - - foreach (module_implements($type . '_alter') as $module) { - $function = $module . '_' . $type . '_alter'; - call_user_func_array($function, $args); + * @param &$data + * The primary data to be altered. + * @param &$context1 + * (optional) An additional variable that is passed by reference. + * @param &$context2 + * (optional) An additional variable that is passed by reference. If more + * context needs to be provided to implementations, then this should be an + * keyed array as described above. + */ +function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL) { + $hook = $type . '_alter'; + foreach (module_implements($hook) as $module) { + $function = $module . '_' . $hook; + $function($data, $context1, $context2); } } diff --git a/includes/form.inc b/includes/form.inc index 282f3a1b1..96a182f64 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -670,20 +670,11 @@ function drupal_prepare_form($form_id, &$form, &$form_state) { } } - // Normally, we would call drupal_alter($form_id, $form, $form_state). - // However, drupal_alter() normally supports just one byref parameter. Using - // the __drupal_alter_by_ref key, we can store any additional parameters - // that need to be altered, and they'll be split out into additional params - // for the hook_form_alter() implementations. - // @todo: Remove this in Drupal 7. - $data = &$form; - $data['__drupal_alter_by_ref'] = array(&$form_state); - drupal_alter('form_' . $form_id, $data); - - // __drupal_alter_by_ref is unset in the drupal_alter() function, we need - // to repopulate it to ensure both calls get the data. - $data['__drupal_alter_by_ref'] = array(&$form_state); - drupal_alter('form', $data, $form_id); + // Invoke hook_form_FORM_ID_alter() implementations. + drupal_alter('form_' . $form_id, $form, $form_state); + + // Invoke hook_form_alter() implementations. + drupal_alter('form', $form, $form_state, $form_id); } |