diff --git modules/book/book.module modules/book/book.module index d60ab18..318b483 100644 --- modules/book/book.module +++ modules/book/book.module @@ -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_state, $form_id) { // 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. * diff --git modules/field/field.form.inc modules/field/field.form.inc index 8802c8e..2eb548a 100644 --- modules/field/field.form.inc +++ modules/field/field.form.inc @@ -363,17 +363,19 @@ function field_default_form_errors($entity_type, $entity, $field, $instance, $la * 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; } /** diff --git modules/node/node.pages.inc modules/node/node.pages.inc index da52f45..2aab5b5 100644 --- modules/node/node.pages.inc +++ modules/node/node.pages.inc @@ -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, &$form_state) { */ 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, $node) { $form['title']['#weight'] = -5; } + // @todo Drop this for D8 so only $form_state[$entity_type] is used. $form['#node'] = $node; $form['additional_settings'] = array( @@ -269,7 +268,6 @@ function node_form($form, &$form_state, $node) { $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; @@ -292,6 +290,7 @@ function node_form_delete_submit($form, &$form_state) { 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; } /** @@ -387,7 +386,6 @@ function node_form_submit($form, &$form_state) { 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; @@ -396,23 +394,30 @@ function node_form_submit($form, &$form_state) { // 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; } } /** - * 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'])); + // Invoke the node submit hook. + foreach (module_implements('node_submit') as $module) { + $function = $module . '_node_submit'; + $function($node, $form, $form_state); + } field_attach_submit('node', $node, $form, $form_state); + $form_state['node'] = $node; - $form_state['node'] = (array)$node; - $form_state['rebuild'] = TRUE; return $node; } diff --git modules/poll/poll.module modules/poll/poll.module index 41ac9e2..b51b9ec 100644 --- modules/poll/poll.module +++ modules/poll/poll.module @@ -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, &$form_state) { // 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']); } /**