Index: modules/book/book.module =================================================================== RCS file: /cvs/drupal/drupal/modules/book/book.module,v retrieving revision 1.537 diff -u -p -r1.537 book.module --- modules/book/book.module 30 Jan 2010 04:23:46 -0000 1.537 +++ modules/book/book.module 6 Apr 2010 04:38:16 -0000 @@ -399,7 +399,7 @@ function book_get_books() { function book_form_alter(&$form, &$form_state, $form_id) { if (!empty($form['#node_edit_form'])) { // Add elements to the node form. - $node = $form['#node']; + $node = $form_state['node']; $access = user_access('administer book outlines'); if (!$access) { @@ -419,13 +419,18 @@ function book_form_alter(&$form, &$form_ // won't be changed via AJAX, a button is provided in the node form to submit // the form and generate options in the parent select corresponding to the // selected book. This is similar to what happens during a node preview. - '#submit' => array('node_form_submit_build_node'), + '#submit' => array('book_node_form_rebuild'), '#weight' => 20, ); } } } +function book_node_form_rebuild($form, &$form_state) { + $form_state['node']->book = $form_state['values']['book']; + $form_state['rebuild'] = TRUE; +} + /** * Build the parent selection form element for the node form or outline tab. * Index: modules/field/field.form.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/field/field.form.inc,v retrieving revision 1.45 diff -u -p -r1.45 field.form.inc --- modules/field/field.form.inc 27 Mar 2010 05:52:49 -0000 1.45 +++ modules/field/field.form.inc 6 Apr 2010 04:38:17 -0000 @@ -363,17 +363,19 @@ function field_default_form_errors($enti * to return just the changed part of the form. */ function field_add_more_submit($form, &$form_state) { - // Set the form to rebuild and run submit handlers. + // If a builder function has been specified, execute it. Entity forms can + // use it to implement their own form persistence mode. if (isset($form['#builder_function']) && function_exists($form['#builder_function'])) { - $entity = $form['#builder_function']($form, $form_state); - - // Make the changes we want to the form state. - $field_name = $form_state['clicked_button']['#field_name']; - $langcode = $form_state['clicked_button']['#language']; - if ($form_state['values'][$field_name . '_add_more']) { - $form_state['field_item_count'][$field_name] = count($form_state['values'][$field_name][$langcode]); - } + $form['#builder_function']($form, $form_state); + } + // Make the changes we want to the form state. + $field_name = $form_state['clicked_button']['#field_name']; + $langcode = $form_state['clicked_button']['#language']; + if ($form_state['values'][$field_name . '_add_more']) { + $form_state['field_item_count'][$field_name] = count($form_state['values'][$field_name][$langcode]); } + // Make sure the form rebuilds regardless whether we submit with JS. + $form_state['rebuild'] = TRUE; } /** Index: modules/node/node.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v retrieving revision 1.120 diff -u -p -r1.120 node.pages.inc --- modules/node/node.pages.inc 31 Mar 2010 13:55:25 -0000 1.120 +++ modules/node/node.pages.inc 6 Apr 2010 04:38:18 -0000 @@ -72,6 +72,7 @@ function node_add($type) { } function node_form_validate($form, &$form_state) { + // @todo for D8: Fix to don't pass that half baken $node object around. $node = (object)$form_state['values']; node_validate($node, $form); @@ -85,14 +86,11 @@ function node_form_validate($form, &$for */ function node_form($form, &$form_state, $node) { global $user; - // This form has its own multistep persistence. - if ($form_state['rebuild']) { - $form_state['input'] = array(); - } - if (isset($form_state['node'])) { - $node = (object)($form_state['node'] + (array)$node); - } + // Submit handlers may have updated $form_state['node'] so keep this changes. + $form_state += array('node' => $node); + $node = $form_state['node']; + if (isset($form_state['node_preview'])) { $form['#prefix'] = $form_state['node_preview']; } @@ -137,6 +135,7 @@ function node_form($form, &$form_state, $form['title']['#weight'] = -5; } + // @todo Drop this for D8 so only $form_state[$entity_type] is used. $form['#node'] = $node; $form['additional_settings'] = array( @@ -273,7 +272,6 @@ function node_form($form, &$form_state, $form['#validate'][] = 'node_form_validate'; $form['#theme'] = array($node->type . '_node_form', 'node_form'); - $form['#builder_function'] = 'node_form_submit_build_node'; field_attach_form('node', $node, $form, $form_state, $node->language); return $form; @@ -296,6 +294,7 @@ function node_form_delete_submit($form, function node_form_build_preview($form, &$form_state) { $node = node_form_submit_build_node($form, $form_state); $form_state['node_preview'] = node_preview($node); + $form_state['rebuild'] = TRUE; } /** @@ -391,7 +390,6 @@ function node_form_submit($form, &$form_ drupal_set_message(t('@type %title has been updated.', $t_args)); } if ($node->nid) { - unset($form_state['rebuild']); $form_state['values']['nid'] = $node->nid; $form_state['nid'] = $node->nid; $form_state['redirect'] = 'node/' . $node->nid; @@ -400,25 +398,33 @@ function node_form_submit($form, &$form_ // In the unlikely case something went wrong on save, the node will be // rebuilt and node form redisplayed the same way as in preview. drupal_set_message(t('The post could not be saved.'), 'error'); + $form_state['rebuild'] = TRUE; } // Clear the page and block caches. cache_clear_all(); } /** - * Build a node by processing submitted form values and prepare for a form rebuild. + * Build a node by processing submitted form values and prepare for a form + * rebuild. As this function invokes form level submit handlers only call it + * if the form has already been fully validated. */ function node_form_submit_build_node($form, &$form_state) { // Unset any button-level handlers, execute all the form-level submit // functions to process the form values into an updated node. unset($form_state['submit_handlers']); form_execute_handlers('submit', $form, $form_state); - $node = node_submit((object)$form_state['values']); + $node = node_submit((object)($form_state['values'] + (array)$form_state['node'])); field_attach_submit('node', $node, $form, $form_state); - $form_state['node'] = (array)$node; - $form_state['rebuild'] = TRUE; + // Invoke the node submit hook. + foreach (module_implements('node_submit') as $module) { + $function = $module . '_node_submit'; + $function($node, $form, $form_state); + } + + $form_state['node'] = $node; return $node; } Index: modules/poll/poll.module =================================================================== RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v retrieving revision 1.339 diff -u -p -r1.339 poll.module --- modules/poll/poll.module 12 Mar 2010 15:56:29 -0000 1.339 +++ modules/poll/poll.module 6 Apr 2010 04:38:18 -0000 @@ -355,15 +355,15 @@ function poll_form($node, &$form_state) * return just the changed part of the form. */ function poll_more_choices_submit($form, &$form_state) { - include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'node') . '/node.pages.inc'; - // Set the form to rebuild and run submit handlers. - node_form_submit_build_node($form, $form_state); - // Make the changes we want to the form state. if ($form_state['values']['poll_more']) { $n = $_GET['q'] == 'system/ajax' ? 1 : 5; $form_state['choice_count'] = count($form_state['values']['choice']) + $n; } + $form_state['node']->choice = array_values($form_state['values']['choice']); + // Disable the form API persistence for the choice form elements. + unset($form_state['input']['choice']); + $form_state['rebuild'] = TRUE; } function _poll_choice_form($key, $chid = NULL, $value = '', $votes = 0, $weight = 0, $size = 10) { @@ -425,6 +425,8 @@ function poll_node_form_submit(&$form, & // Renumber fields $form_state['values']['choice'] = array_values($form_state['values']['choice']); $form_state['values']['teaser'] = poll_teaser((object)$form_state['values']); + // Disable the form API persistence for the choice form elements. + unset($form_state['input']['choice']); } /**