summaryrefslogtreecommitdiff
path: root/modules/node
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-06-17 13:44:45 +0000
committerDries Buytaert <dries@buytaert.net>2010-06-17 13:44:45 +0000
commitcb043e8c489f033f7435e7fd5d18325155465c77 (patch)
tree716cdfe743aa99a01a1dce97cc800c00119af896 /modules/node
parent3620310d7c8a5d487f7b6826a89f8a4816149333 (diff)
downloadbrdo-cb043e8c489f033f7435e7fd5d18325155465c77.tar.gz
brdo-cb043e8c489f033f7435e7fd5d18325155465c77.tar.bz2
- Patch #735800 by effulgentsia, fago, Frando: node form triggers form level submit functions on button level submits, without validation. Oh yeah.
Diffstat (limited to 'modules/node')
-rw-r--r--modules/node/node.api.php28
-rw-r--r--modules/node/node.pages.inc77
2 files changed, 78 insertions, 27 deletions
diff --git a/modules/node/node.api.php b/modules/node/node.api.php
index 95dc3b2b1..690fb9e39 100644
--- a/modules/node/node.api.php
+++ b/modules/node/node.api.php
@@ -665,6 +665,34 @@ function hook_node_validate($node, $form) {
}
/**
+ * Act on a node after validated form values have been copied to it.
+ *
+ * This hook is invoked when a node form is submitted with either the "Save" or
+ * "Preview" button, after form values have been copied to the form state's node
+ * object, but before the node is saved or previewed. It is a chance for modules
+ * to adjust the node's properties from what they are simply after a copy from
+ * $form_state['values']. This hook is intended for adjusting non-field-related
+ * properties. See hook_field_attach_submit() for customizing field-related
+ * properties.
+ *
+ * @param $node
+ * The node being updated in response to a form submission.
+ * @param $form
+ * The form being used to edit the node.
+ * @param $form_state
+ * The form state array.
+ *
+ * @ingroup node_api_hooks
+ */
+function hook_node_submit($node, $form, &$form_state) {
+ // Decompose the selected menu parent option into 'menu_name' and 'plid', if
+ // the form used the default parent selection widget.
+ if (!empty($form_state['values']['menu']['parent'])) {
+ list($node->menu['menu_name'], $node->menu['plid']) = explode(':', $form_state['values']['menu']['parent']);
+ }
+}
+
+/**
* Act on a node that is being assembled before rendering.
*
* The module may add elements to $node->content prior to rendering. This hook
diff --git a/modules/node/node.pages.inc b/modules/node/node.pages.inc
index 6b9544f17..96a4ebfcb 100644
--- a/modules/node/node.pages.inc
+++ b/modules/node/node.pages.inc
@@ -76,12 +76,15 @@ function node_add($type) {
}
function node_form_validate($form, &$form_state) {
+ // $form_state['node'] contains the actual entity being edited, but we must
+ // not update it with form values that have not yet been validated, so we
+ // create a pseudo-entity to use during validation.
$node = (object) $form_state['values'];
node_validate($node, $form);
// Field validation. Requires access to $form_state, so this cannot be
// done in node_validate() as it currently exists.
- field_attach_form_validate('node', $node, $form, $form_state);
+ entity_form_field_validate('node', $form, $form_state);
}
/**
@@ -89,28 +92,29 @@ 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'];
- }
- foreach (array('title') as $key) {
- if (!isset($node->$key)) {
- $node->$key = NULL;
+ // During initial form build, add the node entity to the form state for use
+ // during form building and processing. During a rebuild, use what is in the
+ // form state.
+ if (!isset($form_state['node'])) {
+ if (!isset($node->title)) {
+ $node->title = NULL;
}
- }
- if (!isset($form_state['node_preview'])) {
node_object_prepare($node);
+ $form_state['node'] = $node;
}
else {
+ $node = $form_state['node'];
+ }
+
+ // Some special stuff when previewing a node.
+ if (isset($form_state['node_preview'])) {
+ $form['#prefix'] = $form_state['node_preview'];
$node->in_preview = TRUE;
}
+ else {
+ unset($node->in_preview);
+ }
// Identify this as a node edit form.
$form['#node_edit_form'] = TRUE;
@@ -140,7 +144,9 @@ function node_form($form, &$form_state, $node) {
if (!isset($form['title']['#weight'])) {
$form['title']['#weight'] = -5;
}
-
+ // @todo Legacy support. Modules adding form building and processing functions
+ // to the node form are encouraged to access the node using
+ // $form_state['node']. Remove in Drupal 8.
$form['#node'] = $node;
$form['additional_settings'] = array(
@@ -299,8 +305,9 @@ 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);
+ $node = $form['#builder_function']($form, $form_state);
$form_state['node_preview'] = node_preview($node);
+ $form_state['rebuild'] = TRUE;
}
/**
@@ -382,7 +389,7 @@ function theme_node_preview($variables) {
}
function node_form_submit($form, &$form_state) {
- $node = node_form_submit_build_node($form, $form_state);
+ $node = $form['#builder_function']($form, $form_state);
$insert = empty($node->nid);
node_save($node);
$node_link = l(t('view'), 'node/' . $node->nid);
@@ -398,7 +405,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;
@@ -407,25 +413,42 @@ 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;
}
// Clear the page and block caches.
cache_clear_all();
}
/**
- * Build a node by processing submitted form values and prepare for a form rebuild.
+ * Updates the form state's node entity by processing this submission's values.
+ *
+ * This is the default #builder_function for the node form. It is called
+ * during the "Save" and "Preview" submit handlers to retrieve the entity to
+ * save or preview. This function can also be called by a "Next" button of a
+ * wizard to update the form state's entity with the current step's values
+ * before proceeding to the next step.
+ *
+ * @see node_form()
*/
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.
+ // @todo Legacy support for modules that extend the node form with form-level
+ // submit handlers that adjust $form_state['values'] prior to those values
+ // being used to update the entity. Module authors are encouraged to instead
+ // adjust the node directly within a hook_node_submit() implementation. For
+ // Drupal 8, evaluate whether the pattern of triggering form-level submit
+ // handlers during button-level submit processing is worth supporting
+ // properly, and if so, add a Form API function for doing so.
unset($form_state['submit_handlers']);
form_execute_handlers('submit', $form, $form_state);
- $node = node_submit((object) $form_state['values']);
- field_attach_submit('node', $node, $form, $form_state);
+ $node = $form_state['node'];
+ entity_form_submit_build_entity('node', $node, $form, $form_state);
- $form_state['node'] = (array) $node;
- $form_state['rebuild'] = TRUE;
+ node_submit($node);
+ foreach (module_implements('node_submit') as $module) {
+ $function = $module . '_node_submit';
+ $function($node, $form, $form_state);
+ }
return $node;
}