=== modified file 'includes/form.inc' --- includes/form.inc +++ includes/form.inc @@ -113,7 +113,6 @@ function drupal_get_form($form_id) { return drupal_render_form($args[0], $form); } - /** * Retrieves a form using a form_id, populates it with $form_values, * processes it, and returns any validation errors encountered. This @@ -200,16 +199,15 @@ function drupal_retrieve_form($form_id) * The path to redirect the user to upon completion. */ function drupal_process_form($form_id, &$form) { - global $form_values, $form_submitted, $user, $form_button_counter; + global $form_values, $submit_callback, $user; static $saved_globals = array(); // In some scenerios, this function can be called recursively. Pushing any pre-existing // $form_values and form submission data lets us start fresh without clobbering work done // in earlier recursive calls. - array_push($saved_globals, array($form_values, $form_submitted, $form_button_counter)); + array_push($saved_globals, array($form_values, $submit_callback)); $form_values = array(); - $form_submitted = FALSE; - $form_button_counter = array(0, 0); + $submit_callback = array(); drupal_prepare_form($form_id, $form); if (($form['#programmed']) || (!empty($_POST) && (($_POST['form_id'] == $form_id) || ($_POST['form_id'] == $form['#base'])))) { @@ -217,8 +215,8 @@ function drupal_process_form($form_id, & // IE does not send a button value when there is only one submit button (and no non-submit buttons) // and you submit by pressing enter. // In that case we accept a submission without button values. - if ((($form['#programmed']) || $form_submitted || (!$form_button_counter[0] && $form_button_counter[1])) && !form_get_errors()) { - $redirect = drupal_submit_form($form_id, $form); + if ((($form['#programmed']) || $submit_callback) && !form_get_errors()) { + $redirect = drupal_submit_form($form_id, $form, $submit_callback); if (!$form['#programmed']) { drupal_redirect_form($form, $redirect); } @@ -227,7 +225,7 @@ function drupal_process_form($form_id, & // We've finished calling functions that alter the global values, so we can // restore the ones that were there before this function was called. - list($form_values, $form_submitted, $form_button_counter) = array_pop($saved_globals); + list($form_values, $submit_callback) = array_pop($saved_globals); return $redirect; } @@ -306,17 +304,6 @@ function drupal_prepare_form($form_id, & } } - if (!isset($form['#submit'])) { - if (function_exists($form_id .'_submit')) { - // we set submit here so that it can be altered but use reference for - // $form_values because it will change later - $form['#submit'] = array($form_id .'_submit' => array()); - } - elseif (function_exists($base .'_submit')) { - $form['#submit'] = array($base .'_submit' => array()); - } - } - foreach (module_implements('form_alter') as $module) { $function = $module .'_form_alter'; $function($form_id, $form); @@ -367,24 +354,37 @@ function drupal_validate_form($form_id, * theming, and hook_form_alter functions. * @param $form * An associative array containing the structure of the form. + * @param $submit_callback + * An array of callback functions. The name can contain %base which will be + * changed to $form_id / #base accordingly. * @return * A string containing the path of the page to display when processing * is complete. * */ -function drupal_submit_form($form_id, $form) { +function drupal_submit_form($form_id, $form, $submit_callback) { global $form_values; $default_args = array($form_id, &$form_values); - if (isset($form['#submit'])) { - foreach ($form['#submit'] as $function => $args) { - if (function_exists($function)) { - $args = array_merge($default_args, (array) $args); - // Since we can only redirect to one page, only the last redirect will work - $redirect = call_user_func_array($function, $args); - if (isset($redirect)) { - $goto = $redirect; - } + // Loop through the callbacks for a given submit operation, and execute + // each one if it exists. If we encounter a %base, we replace that with + // $form_id / #base + foreach ($submit_callback as $function => $args) { + if (strpos($function, '%base') !== FALSE) { + if (function_exists(str_replace('%base', $form_id, $function))) { + $function = str_replace('%base', $form_id, $function); + } + elseif (function_exists(str_replace('%base', $form['#base'], $function))) { + $function = str_replace('%base', $form['#base'], $function); + } + } + + if (function_exists($function)) { + $args = array_merge($default_args, (array) $args); + // Since we can only redirect to one page, only the last redirect will work + $redirect = call_user_func_array($function, $args); + if (isset($redirect)) { + $goto = $redirect; } } } @@ -581,7 +581,7 @@ function form_error(&$element, $message * An associative array containing the structure of the form. */ function form_builder($form_id, $form) { - global $form_values, $form_submitted, $form_button_counter; + global $form_values, $submit_callback; // Initialize as unprocessed. $form['#processed'] = FALSE; @@ -670,13 +670,13 @@ function form_builder($form_id, $form) { } } } - if (isset($form['#executes_submit_callback'])) { - // Count submit and non-submit buttons - $form_button_counter[$form['#executes_submit_callback']]++; - // See if a submit button was pressed + if (isset($form['#button_type'])) { + // This is an element capable of initiating a form submit. See if it was clicked. if (isset($form['#post'][$form['#name']]) && $form['#post'][$form['#name']] == $form['#value']) { $form_submitted = $form_submitted || $form['#executes_submit_callback']; - + if (isset($form['#callback'])) { + $submit_callback = $form['#callback']; + } // In most cases, we want to use form_set_value() to manipulate the global variables. // In this special case, we want to make sure that the value of this element is listed // in $form_variables under 'op'. @@ -698,8 +698,10 @@ function form_builder($form_id, $form) { // Set the $form_values key that gets passed to validate and submit. // We call this after #process gets called so that #process has a - // chance to update #value if desired. - if (isset($form['#input']) && $form['#input']) { + // chance to update #value if desired. Button type input fields should + // only show up if they're used to submit the form, so we will ignore + // them here. + if (isset($form['#input']) && $form['#input'] && !isset($form['#button_type'])) { form_set_value($form, $form['#value']); } === modified file 'modules/node/node.module' --- modules/node/node.module +++ modules/node/node.module @@ -1936,7 +1936,17 @@ function node_form($node, $form_values = // Add the buttons. $form['preview'] = array('#type' => 'button', '#value' => t('Preview'), '#weight' => 40); - $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'), '#weight' => 45); + $form['submit'] = array( + '#type' => 'submit', + '#value' => t('Submit'), + '#weight' => 45, + '#callback' => array( + $node->type .'_node_submit_early' => array(), + 'node_form_submit' => array(), + $node->type .'_node_submit' => array(), + ), + ); + if ($node->nid && node_access('delete', $node)) { $form['delete'] = array('#type' => 'button', '#value' => t('Delete'), '#weight' => 50); } @@ -1949,7 +1959,7 @@ function node_form_add_preview($form) { global $form_values; $op = isset($form_values['op']) ? $form_values['op'] : ''; - if ($op == $form_values['preview']) { + if ($op == t('Preview')) { drupal_validate_form($form['form_id']['#value'], $form); if (!form_get_errors()) { // We pass the global $form_values here to preserve changes made during form validation === modified file 'modules/system/system.module' --- modules/system/system.module +++ modules/system/system.module @@ -66,8 +66,8 @@ function system_elements() { // Inputs $type['checkbox'] = array('#input' => TRUE, '#return_value' => 1); - $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => TRUE); - $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#executes_submit_callback' => FALSE); + $type['submit'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit', '#callback' => array('%base_submit' => array())); + $type['button'] = array('#input' => TRUE, '#name' => 'op', '#button_type' => 'submit'); $type['textfield'] = array('#input' => TRUE, '#size' => 60, '#maxlength' => 128, '#autocomplete_path' => FALSE); $type['password'] = array('#input' => TRUE, '#size' => 30); $type['password_confirm'] = array('#input' => TRUE, '#process' => array('expand_password_confirm' => array())); @@ -409,12 +409,13 @@ function system_admin_theme_settings() { '#default_value' => variable_get('admin_theme', 'bluemarine'), ); + $form = system_settings_form($form); // In order to give it our own submit, we have to give it the default submit - // too because the presence of a #submit will prevent the default #submit + // too because the presence of a #callback will prevent the default submit // from being used. Also we want ours first. - $form['#submit']['system_admin_theme_submit'] = array(); - $form['#submit']['system_settings_form_submit'] = array(); - return system_settings_form($form); + $form['buttons']['submit']['#callback']['system_admin_theme_submit'] = array(); + $form['buttons']['submit']['#callback']['system_settings_form_submit'] = array(); + return $form; }