From e7fc2383df8922eef9edd7406370e57bc0808a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Hojtsy?= Date: Tue, 18 Dec 2007 16:24:01 +0000 Subject: #192767 by fago, Eaton, chx: taking form_state per reference in form constructor function. Will be replaced with a nicer PHP 5 solution in Drupal 7. --- includes/common.inc | 17 +++++++++++++++++ includes/form.inc | 22 +++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) (limited to 'includes') diff --git a/includes/common.inc b/includes/common.inc index 8c47f0036..353010634 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -2832,8 +2832,25 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1) * 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 (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. diff --git a/includes/form.inc b/includes/form.inc index 088893b74..6155a3584 100644 --- a/includes/form.inc +++ b/includes/form.inc @@ -78,7 +78,7 @@ function drupal_get_form($form_id) { // Use a copy of the function's arguments for manipulation $args_temp = $args; array_shift($args_temp); - array_unshift($args_temp, $form_state); + array_unshift($args_temp, &$form_state); array_unshift($args_temp, $form_id); $form = call_user_func_array('drupal_retrieve_form', $args_temp); @@ -173,7 +173,7 @@ function drupal_rebuild_form($form_id, &$form_state, $args, $form_build_id = NUL // callback. Neither is needed. array_shift($args); // Put in the current state. - array_unshift($args, $form_state); + array_unshift($args, &$form_state); // And the form_id. array_unshift($args, $form_id); $form = call_user_func_array('drupal_retrieve_form', $args); @@ -333,7 +333,7 @@ function drupal_retrieve_form($form_id, &$form_state) { } } - array_unshift($args, $form_state); + array_unshift($args, &$form_state); // If $callback was returned by a hook_forms() implementation, call it. // Otherwise, call the function named after the form id. @@ -497,8 +497,20 @@ function drupal_prepare_form($form_id, &$form, &$form_state) { } } - drupal_alter('form_'. $form_id, $form, $form_state); - drupal_alter('form', $form, $form_state, $form_id); + // 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); } -- cgit v1.2.3