summaryrefslogtreecommitdiff
path: root/includes
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2009-10-13 16:38:43 +0000
committerDries Buytaert <dries@buytaert.net>2009-10-13 16:38:43 +0000
commitfbfa7a4150a40d6df9347692bb6681f45f804c7d (patch)
tree425db0f6cc7b72b8a9350c5a462fe718e0ed2877 /includes
parentf67e438b4196a6bc79c0da576da0a9e09fedb612 (diff)
downloadbrdo-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.inc83
-rw-r--r--includes/form.inc19
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);
}