diff --git modules/book/book.module modules/book/book.module
index d60ab18..60cb46f 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,20 @@ 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) {
+ // @todo: Fix to not use that but rely on the form values for rebuilding.
+ // Then we can also use limited validation.
+ node_form_submit_build_node($form, $form_state);
+ $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 63b9a84..89e60e6 100644
--- modules/field/field.form.inc
+++ modules/field/field.form.inc
@@ -131,11 +131,6 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
* - drag-n-drop value reordering
*/
function field_multiple_value_form($field, $instance, $langcode, $items, &$form, &$form_state) {
- // This form has its own multistep persistance.
- if ($form_state['rebuild']) {
- $form_state['input'] = array();
- }
-
$field_name = $field['field_name'];
// Determine the number of widgets to display.
@@ -368,16 +363,16 @@ 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]);
}
}
diff --git modules/field/tests/field.test modules/field/tests/field.test
index 29a9e33..5205fec 100644
--- modules/field/tests/field.test
+++ modules/field/tests/field.test
@@ -1562,18 +1562,17 @@ class FieldFormTestCase extends FieldTestCase {
$edit["$this->field_name[$langcode][$delta][value]"] = $value;
$edit["$this->field_name[$langcode][$delta][_weight]"] = $weight;
// We'll need three slightly different formats to check the values.
- $values[$weight] = $value;
+ $values[$delta] = $value;
+ $weights[$delta] = $weight;
$field_values[$weight]['value'] = (string)$value;
$pattern[$weight] = "]*value=\"$value\" [^>]*";
}
// Press 'add more' button -> 4 widgets
$this->drupalPost(NULL, $edit, t('Add another item'));
- ksort($values);
- $values = array_values($values);
for ($delta = 0; $delta <= $delta_range; $delta++) {
$this->assertFieldByName("$this->field_name[$langcode][$delta][value]", $values[$delta], "Widget $delta is displayed and has the right value");
- $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $delta, "Widget $delta has the right weight");
+ $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $weights[$delta], "Widget $delta has the right weight");
}
ksort($pattern);
$pattern = implode('.*', array_values($pattern));
@@ -1632,7 +1631,8 @@ class FieldFormTestCase extends FieldTestCase {
$edit["$this->field_name[$langcode][$delta][value]"] = $value;
$edit["$this->field_name[$langcode][$delta][_weight]"] = $weight;
// We'll need three slightly different formats to check the values.
- $values[$weight] = $value;
+ $values[$delta] = $value;
+ $weights[$delta] = $weight;
$field_values[$weight]['value'] = (string)$value;
$pattern[$weight] = "]*value=\"$value\" [^>]*";
}
@@ -1641,11 +1641,9 @@ class FieldFormTestCase extends FieldTestCase {
$commands = $this->drupalPostAJAX(NULL, $edit, $this->field_name . '_add_more');
$this->content = $commands[1]['data'];
- ksort($values);
- $values = array_values($values);
for ($delta = 0; $delta <= $delta_range; $delta++) {
$this->assertFieldByName("$this->field_name[$langcode][$delta][value]", $values[$delta], "Widget $delta is displayed and has the right value");
- $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $delta, "Widget $delta has the right weight");
+ $this->assertFieldByName("$this->field_name[$langcode][$delta][_weight]", $weights[$delta], "Widget $delta has the right weight");
}
ksort($pattern);
$pattern = implode('.*', array_values($pattern));
diff --git modules/node/node.pages.inc modules/node/node.pages.inc
index fce7bfd..7f2d131 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,7 @@ 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);
- }
if (isset($form_state['node_preview'])) {
$form['#prefix'] = $form_state['node_preview'];
}
@@ -134,6 +128,8 @@ function node_form($form, &$form_state, $node) {
$form['title']['#weight'] = -5;
}
+ $form_state += array('node' => $node);
+ // @todo Drop this for D8 as we use $form_state[$entity_type] now.
$form['#node'] = $node;
$form['additional_settings'] = array(
@@ -266,7 +262,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;
@@ -289,6 +284,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;
}
/**
@@ -403,7 +399,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;
@@ -412,23 +407,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..e854c16 100644
--- modules/poll/poll.module
+++ modules/poll/poll.module
@@ -355,15 +355,12 @@ 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['rebuild'] = TRUE;
}
function _poll_choice_form($key, $chid = NULL, $value = '', $votes = 0, $weight = 0, $size = 10) {