diff options
author | Dries Buytaert <dries@buytaert.net> | 2010-06-17 13:44:45 +0000 |
---|---|---|
committer | Dries Buytaert <dries@buytaert.net> | 2010-06-17 13:44:45 +0000 |
commit | cb043e8c489f033f7435e7fd5d18325155465c77 (patch) | |
tree | 716cdfe743aa99a01a1dce97cc800c00119af896 /modules | |
parent | 3620310d7c8a5d487f7b6826a89f8a4816149333 (diff) | |
download | brdo-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')
-rw-r--r-- | modules/book/book.module | 26 | ||||
-rw-r--r-- | modules/comment/comment.module | 105 | ||||
-rw-r--r-- | modules/field/field.attach.inc | 3 | ||||
-rw-r--r-- | modules/field/field.default.inc | 23 | ||||
-rw-r--r-- | modules/field/field.form.inc | 15 | ||||
-rw-r--r-- | modules/field/tests/field_test.entity.inc | 29 | ||||
-rw-r--r-- | modules/menu/menu.module | 9 | ||||
-rw-r--r-- | modules/node/node.api.php | 28 | ||||
-rw-r--r-- | modules/node/node.pages.inc | 77 | ||||
-rw-r--r-- | modules/poll/poll.module | 11 | ||||
-rw-r--r-- | modules/simpletest/tests/form_test.module | 2 | ||||
-rw-r--r-- | modules/taxonomy/taxonomy.admin.inc | 152 | ||||
-rw-r--r-- | modules/user/user.pages.inc | 25 |
13 files changed, 299 insertions, 206 deletions
diff --git a/modules/book/book.module b/modules/book/book.module index bea4a077f..9d3284bc8 100644 --- a/modules/book/book.module +++ b/modules/book/book.module @@ -416,15 +416,13 @@ function book_form_alter(&$form, &$form_state, $form_id) { if ($access) { _book_add_form_elements($form, $form_state, $node); + // Since the "Book" dropdown can't trigger a form submission when + // JavaScript is disabled, add a submit button to do that. book.css hides + // this button when JavaScript is enabled. $form['book']['pick-book'] = array( '#type' => 'submit', '#value' => t('Change book (update list of parents)'), - // Submit the node form so the parent select options get updated. - // This is typically only used when JS is disabled. Since the parent options - // 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_pick_book_nojs_submit'), '#weight' => 20, ); } @@ -432,6 +430,22 @@ function book_form_alter(&$form, &$form_state, $form_id) { } /** + * Submit handler to change a node's book. + * + * This handler is run when JavaScript is disabled. It triggers the form to + * rebuild so that the "Parent item" options are changed to reflect the newly + * selected book. When JavaScript is enabled, the submit button that triggers + * this handler is hidden, and the "Book" dropdown directly triggers the + * book_form_update() AJAX callback instead. + * + * @see book_form_update() + */ +function book_pick_book_nojs_submit($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. * * This function is also called when generating a new set of options during the diff --git a/modules/comment/comment.module b/modules/comment/comment.module index 03cbb5460..d54a33a9c 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -1762,6 +1762,32 @@ function comment_edit_page($comment) { function comment_form($form, &$form_state, $comment) { global $user; + // During initial form build, add the comment 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['comment'])) { + $defaults = array( + 'name' => '', + 'mail' => '', + 'homepage' => '', + 'subject' => '', + 'comment' => '', + 'cid' => NULL, + 'pid' => NULL, + 'language' => LANGUAGE_NONE, + 'uid' => 0, + ); + foreach ($defaults as $key => $value) { + if (!isset($comment->$key)) { + $comment->$key = $value; + } + } + $form_state['comment'] = $comment; + } + else { + $comment = $form_state['comment']; + } + $node = node_load($comment->nid); $form['#node'] = $node; @@ -1773,24 +1799,6 @@ function comment_form($form, &$form_state, $comment) { $form['#attributes']['class'][] = 'user-info-from-cookie'; } - $comment = (array) $comment; - // Take into account multi-step rebuilding. - if (isset($form_state['comment'])) { - $comment = $form_state['comment'] + (array) $comment; - } - $comment += array( - 'name' => '', - 'mail' => '', - 'homepage' => '', - 'subject' => '', - 'comment' => '', - 'cid' => NULL, - 'pid' => NULL, - 'language' => LANGUAGE_NONE, - 'uid' => 0, - ); - $comment = (object) $comment; - // If not replying to a comment, use our dedicated page callback for new // comments on nodes. if (empty($comment->cid) && empty($comment->pid)) { @@ -1966,8 +1974,9 @@ function comment_form($form, &$form_state, $comment) { * Build a preview from submitted form values. */ function comment_form_build_preview($form, &$form_state) { - $comment = comment_form_submit_build_comment($form, $form_state); + $comment = $form['#builder_function']($form, $form_state); $form_state['comment_preview'] = comment_preview($comment); + $form_state['rebuild'] = TRUE; } /** @@ -2033,8 +2042,8 @@ function comment_preview($comment) { */ function comment_form_validate($form, &$form_state) { global $user; - $comment = (object) $form_state['values']; - field_attach_form_validate('comment', $comment, $form, $form_state); + + entity_form_field_validate('comment', $form, $form_state); if (!empty($form_state['values']['cid'])) { if ($form_state['values']['date'] && strtotime($form_state['values']['date']) === FALSE) { @@ -2085,49 +2094,56 @@ function comment_form_validate($form, &$form_state) { /** * Prepare a comment for submission. - * - * @param $comment - * An associative array containing the comment data. */ function comment_submit($comment) { - $comment += array('subject' => ''); - if (empty($comment['date'])) { - $comment['date'] = 'now'; + // @todo Legacy support. Remove in Drupal 8. + if (is_array($comment)) { + $comment += array('subject' => ''); + $comment = (object) $comment; + } + + if (empty($comment->date)) { + $comment->date = 'now'; } - $comment['created'] = strtotime($comment['date']); - $comment['changed'] = REQUEST_TIME; + $comment->created = strtotime($comment->date); + $comment->changed = REQUEST_TIME; - if (!empty($comment['name']) && ($account = user_load_by_name($comment['name']))) { - $comment['uid'] = $account->uid; + if (!empty($comment->name) && ($account = user_load_by_name($comment->name))) { + $comment->uid = $account->uid; } // Validate the comment's subject. If not specified, extract from comment body. - if (trim($comment['subject']) == '') { + if (trim($comment->subject) == '') { // The body may be in any format, so: // 1) Filter it into HTML // 2) Strip out all HTML tags // 3) Convert entities back to plain-text. - $comment['subject'] = truncate_utf8(trim(decode_entities(strip_tags(check_markup($comment['comment_body'][LANGUAGE_NONE][0]['value'], $comment['comment_body'][LANGUAGE_NONE][0]['format'])))), 29, TRUE); + $comment->subject = truncate_utf8(trim(decode_entities(strip_tags(check_markup($comment->comment_body[LANGUAGE_NONE][0]['value'], $comment->comment_body[LANGUAGE_NONE][0]['format'])))), 29, TRUE); // Edge cases where the comment body is populated only by HTML tags will // require a default subject. - if ($comment['subject'] == '') { - $comment['subject'] = t('(No subject)'); + if ($comment->subject == '') { + $comment->subject = t('(No subject)'); } } - return (object) $comment; + return $comment; } /** - * Build a comment by processing form values and prepare for a form rebuild. + * Updates the form state's comment entity by processing this submission's values. + * + * This is the default #builder_function for the comment 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 comment_form() */ function comment_form_submit_build_comment($form, &$form_state) { - $comment = comment_submit($form_state['values']); - - field_attach_submit('comment', $comment, $form, $form_state); - - $form_state['comment'] = (array) $comment; - $form_state['rebuild'] = TRUE; + $comment = $form_state['comment']; + entity_form_submit_build_entity('comment', $comment, $form, $form_state); + comment_submit($comment); return $comment; } @@ -2136,7 +2152,7 @@ function comment_form_submit_build_comment($form, &$form_state) { */ function comment_form_submit($form, &$form_state) { $node = node_load($form_state['values']['nid']); - $comment = comment_form_submit_build_comment($form, $form_state); + $comment = $form['#builder_function']($form, $form_state); if (user_access('post comments') && (user_access('administer comments') || $node->comment == COMMENT_NODE_OPEN)) { // Save the anonymous user information to a cookie for reuse. if (!$comment->uid) { @@ -2173,7 +2189,6 @@ function comment_form_submit($form, &$form_state) { // Redirect the user to the node they are commenting on. $redirect = 'node/' . $node->nid; } - unset($form_state['rebuild']); $form_state['redirect'] = $redirect; // Clear the block and page caches so that anonymous users see the comment // they have posted. diff --git a/modules/field/field.attach.inc b/modules/field/field.attach.inc index d461eca46..3f4a641b3 100644 --- a/modules/field/field.attach.inc +++ b/modules/field/field.attach.inc @@ -547,9 +547,6 @@ function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcod $form['#entity_type'] = $entity_type; $form['#bundle'] = $bundle; - // Save the original entity to allow later re-use. - $form_state['entity'] = $entity; - // Let other modules make changes to the form. // Avoid module_invoke_all() to let parameters be taken by reference. foreach (module_implements('field_attach_form') as $module) { diff --git a/modules/field/field.default.inc b/modules/field/field.default.inc index 4cd512392..060ad990e 100644 --- a/modules/field/field.default.inc +++ b/modules/field/field.default.inc @@ -65,25 +65,12 @@ function field_default_validate($entity_type, $entity, $field, $instance, $langc } function field_default_submit($entity_type, $entity, $field, $instance, $langcode, &$items, $form, &$form_state) { - $field_name = $field['field_name']; - - if (isset($form_state['values'][$field_name][$langcode])) { - // Reorder items to account for drag-n-drop reordering. - if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) { - $items = _field_sort_items($field, $items); - } - // Filter out empty values. - $items = _field_filter_items($field, $items); - } - elseif (!empty($entity->revision) && isset($form_state['entity']->{$field_name}[$langcode])) { - // To ensure new revisions are created with all field values in all - // languages, populate values not included in the form with the ones from - // the original object. This covers: - // - partial forms including only a subset of the fields, - // - fields for which the user has no edit access, - // - languages not involved in the form. - $items = $form_state['entity']->{$field_name}[$langcode]; + // Reorder items to account for drag-n-drop reordering. + if (field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT) { + $items = _field_sort_items($field, $items); } + // Filter out empty values. + $items = _field_filter_items($field, $items); } /** diff --git a/modules/field/field.form.inc b/modules/field/field.form.inc index 32c4d3a9a..e042fd728 100644 --- a/modules/field/field.form.inc +++ b/modules/field/field.form.inc @@ -359,17 +359,12 @@ 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 (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]); - } + $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_state['rebuild'] = TRUE; } /** diff --git a/modules/field/tests/field_test.entity.inc b/modules/field/tests/field_test.entity.inc index b078714b9..b7887c812 100644 --- a/modules/field/tests/field_test.entity.inc +++ b/modules/field/tests/field_test.entity.inc @@ -289,10 +289,15 @@ function field_test_entity_edit($entity) { * Test_entity form. */ function field_test_entity_form($form, &$form_state, $entity, $add = FALSE) { - if (isset($form_state['test_entity'])) { - $entity = $form_state['test_entity'] + (array) $entity; + // During initial form build, add the 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['test_entity'])) { + $form_state['test_entity'] = $entity; + } + else { + $entity = $form_state['test_entity']; } - $entity = (object) $entity; foreach (array('ftid', 'ftvid', 'fttype') as $key) { $form[$key] = array( @@ -327,15 +332,14 @@ function field_test_entity_form($form, &$form_state, $entity, $add = FALSE) { * Validate handler for field_test_entity_form(). */ function field_test_entity_form_validate($form, &$form_state) { - $entity = field_test_create_stub_entity($form_state['values']['ftid'], $form_state['values']['ftvid'], $form_state['values']['fttype']); - field_attach_form_validate('test_entity', $entity, $form, $form_state); + entity_form_field_validate('test_entity', $form, $form_state); } /** * Submit handler for field_test_entity_form(). */ function field_test_entity_form_submit($form, &$form_state) { - $entity = field_test_entity_form_submit_builder($form, $form_state); + $entity = $form['#builder_function']($form, $form_state); $insert = empty($entity->ftid); field_test_entity_save($entity); @@ -343,25 +347,20 @@ function field_test_entity_form_submit($form, &$form_state) { drupal_set_message($message); if ($entity->ftid) { - unset($form_state['rebuild']); $form_state['redirect'] = 'test-entity/' . $entity->ftid . '/edit'; } else { // Error on save. drupal_set_message(t('The entity could not be saved.'), 'error'); + $form_state['rebuild'] = TRUE; } } /** - * Builds a test_entity from submitted form values. + * Updates the form state's entity by processing this submission's values. */ function field_test_entity_form_submit_builder($form, &$form_state) { - $entity = field_test_create_stub_entity($form_state['values']['ftid'], $form_state['values']['ftvid'], $form_state['values']['fttype']); - $entity->revision = !empty($form_state['values']['revision']); - field_attach_submit('test_entity', $entity, $form, $form_state); - - $form_state['test_entity'] = (array) $entity; - $form_state['rebuild'] = TRUE; - + $entity = $form_state['test_entity']; + entity_form_submit_build_entity('test_entity', $entity, $form, $form_state); return $entity; } diff --git a/modules/menu/menu.module b/modules/menu/menu.module index 12381543c..9686a57bf 100644 --- a/modules/menu/menu.module +++ b/modules/menu/menu.module @@ -596,7 +596,6 @@ function menu_form_alter(&$form, $form_state, $form_id) { return; } $link = $form['#node']->menu; - $form['#submit'][] = 'menu_node_form_submit'; $form['menu'] = array( '#type' => 'fieldset', @@ -661,15 +660,13 @@ function menu_form_alter(&$form, $form_state, $form_id) { } /** - * Submit handler for node form. - * - * @see menu_form_alter() + * Implements hook_node_submit(). */ -function menu_node_form_submit($form, &$form_state) { +function menu_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($form_state['values']['menu']['menu_name'], $form_state['values']['menu']['plid']) = explode(':', $form_state['values']['menu']['parent']); + list($node->menu['menu_name'], $node->menu['plid']) = explode(':', $form_state['values']['menu']['parent']); } } 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; } diff --git a/modules/poll/poll.module b/modules/poll/poll.module index f273953a4..d698e0301 100644 --- a/modules/poll/poll.module +++ b/modules/poll/poll.module @@ -366,15 +366,18 @@ 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; } + // Renumber the choices. This invalidates the corresponding key/value + // associations in $form_state['input'], so clear that out. This requires + // poll_form() to rebuild the choices with the values in + // $form_state['node']->choice, which it does. + $form_state['node']->choice = array_values($form_state['values']['choice']); + unset($form_state['input']['choice']); + $form_state['rebuild'] = TRUE; } function _poll_choice_form($key, $chid = NULL, $value = '', $votes = 0, $weight = 0, $size = 10) { diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module index 6a1cb3258..0b9284adb 100644 --- a/modules/simpletest/tests/form_test.module +++ b/modules/simpletest/tests/form_test.module @@ -1143,8 +1143,6 @@ function form_test_form_user_register_form_alter(&$form, &$form_state) { if (!empty($_REQUEST['field'])) { $node = (object)array('type' => 'page'); field_attach_form('node', $node, $form, $form_state); - // The form API requires the builder function to set rebuilding, so do so. - $form['#builder_function'] = 'form_test_user_register_form_rebuild'; } } diff --git a/modules/taxonomy/taxonomy.admin.inc b/modules/taxonomy/taxonomy.admin.inc index 59defe82c..1080e3818 100644 --- a/modules/taxonomy/taxonomy.admin.inc +++ b/modules/taxonomy/taxonomy.admin.inc @@ -100,17 +100,33 @@ function theme_taxonomy_overview_vocabularies($variables) { * @see taxonomy_form_vocabulary_submit() */ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) { - if (!is_array($edit)) { - $edit = (array) $edit; - } - $edit += array( - 'name' => '', - 'machine_name' => '', - 'description' => '', - 'hierarchy' => 0, - 'weight' => 0, - ); - $form['#vocabulary'] = (object) $edit; + // During initial form build, add the 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['vocabulary'])) { + $vocabulary = is_object($edit) ? $edit : (object) $edit; + $defaults = array( + 'name' => '', + 'machine_name' => '', + 'description' => '', + 'hierarchy' => 0, + 'weight' => 0, + ); + foreach ($defaults as $key => $value) { + if (!isset($vocabulary->$key)) { + $vocabulary->$key = $value; + } + } + $form_state['vocabulary'] = $vocabulary; + } + else { + $vocabulary = $form_state['vocabulary']; + } + + // @todo Legacy support. Modules are encouraged to access the entity using + // $form_state. Remove in Drupal 8. + $form['#vocabulary'] = $form_state['vocabulary']; + // Check whether we need a deletion confirmation form. if (isset($form_state['confirm_delete']) && isset($form_state['values']['vid'])) { return taxonomy_vocabulary_confirm_delete($form, $form_state, $form_state['values']['vid']); @@ -118,7 +134,7 @@ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) { $form['name'] = array( '#type' => 'textfield', '#title' => t('Name'), - '#default_value' => $edit['name'], + '#default_value' => $vocabulary->name, '#maxlength' => 255, '#required' => TRUE, '#field_suffix' => ' <small id="edit-name-suffix"> </small>', @@ -139,7 +155,7 @@ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) { $form['machine_name'] = array( '#type' => 'textfield', '#title' => t('Machine-readable name'), - '#default_value' => $edit['machine_name'], + '#default_value' => $vocabulary->machine_name, '#maxlength' => 255, '#description' => t('The unique machine-readable name for this vocabulary, used for theme templates. Can only contain lowercase letters, numbers, and underscores.'), '#required' => TRUE, @@ -150,7 +166,7 @@ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) { $form['description'] = array( '#type' => 'textfield', '#title' => t('Description'), - '#default_value' => $edit['description'], + '#default_value' => $vocabulary->description, ); // Set the hierarchy to "multiple parents" by default. This simplifies the // vocabulary form and standardizes the term form. @@ -161,10 +177,10 @@ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) { $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save')); - if (isset($edit['vid'])) { + if (isset($vocabulary->vid)) { $form['actions']['delete'] = array('#type' => 'submit', '#value' => t('Delete')); - $form['vid'] = array('#type' => 'value', '#value' => $edit['vid']); - $form['module'] = array('#type' => 'value', '#value' => $edit['module']); + $form['vid'] = array('#type' => 'value', '#value' => $vocabulary->vid); + $form['module'] = array('#type' => 'value', '#value' => $vocabulary->module); } return $form; } @@ -201,16 +217,17 @@ function taxonomy_form_vocabulary_validate($form, &$form_state) { * Accept the form submission for a vocabulary and save the results. */ function taxonomy_form_vocabulary_submit($form, &$form_state) { - $old_vocabulary = $form['#vocabulary']; if ($form_state['clicked_button']['#value'] == t('Delete')) { // Rebuild the form to confirm vocabulary deletion. $form_state['rebuild'] = TRUE; $form_state['confirm_delete'] = TRUE; return; } - $vocabulary = (object) $form_state['values']; - if ($vocabulary->machine_name != $old_vocabulary->machine_name) { - field_attach_rename_bundle('taxonomy_term', $old_vocabulary->machine_name, $vocabulary->machine_name); + $old_machine_name = $form_state['vocabulary']->machine_name; + $vocabulary = $form_state['vocabulary']; + entity_form_submit_build_entity('taxonomy_vocabulary', $vocabulary, $form, $form_state); + if ($vocabulary->machine_name != $old_machine_name) { + field_attach_rename_bundle('taxonomy_term', $old_machine_name, $vocabulary->machine_name); } switch (taxonomy_vocabulary_save($vocabulary)) { case SAVED_NEW: @@ -617,33 +634,45 @@ function theme_taxonomy_overview_terms($variables) { * @see taxonomy_form_term_submit() */ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary = NULL) { - if (!isset($vocabulary) && is_object($edit)) { - $vocabulary = taxonomy_vocabulary_load($edit->vid); - $edit = (array) $edit; - } - $edit += array( - 'name' => '', - 'description' => '', - 'format' => filter_default_format(), - 'vocabulary_machine_name' => $vocabulary->machine_name, - 'tid' => NULL, - 'weight' => 0, - ); - - // Take into account multi-step rebuilding. - if (isset($form_state['term'])) { - $edit = $form_state['term'] + $edit; + // During initial form build, add the term 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['term'])) { + $term = is_object($edit) ? $edit : (object) $edit; + if (!isset($vocabulary) && isset($term->vid)) { + $vocabulary = taxonomy_vocabulary_load($term->vid); + } + $defaults = array( + 'name' => '', + 'description' => '', + 'format' => filter_default_format(), + 'vocabulary_machine_name' => isset($vocabulary) ? $vocabulary->machine_name : NULL, + 'tid' => NULL, + 'weight' => 0, + ); + foreach ($defaults as $key => $value) { + if (!isset($term->$key)) { + $term->$key = $value; + } + } + $form_state['term'] = $term; + } + else { + $term = $form_state['term']; + if (!isset($vocabulary) && isset($term->vid)) { + $vocabulary = taxonomy_vocabulary_load($term->vid); + } } - $parent = array_keys(taxonomy_get_parents($edit['tid'])); - $form['#term'] = $edit; + $parent = array_keys(taxonomy_get_parents($term->tid)); + $form['#term'] = (array) $term; $form['#term']['parent'] = $parent; $form['#vocabulary'] = $vocabulary; $form['#builder_function'] = 'taxonomy_form_term_submit_builder'; // Check for confirmation forms. if (isset($form_state['confirm_delete'])) { - return array_merge($form, taxonomy_term_confirm_delete($form, $form_state, $edit['tid'])); + return array_merge($form, taxonomy_term_confirm_delete($form, $form_state, $term->tid)); } elseif (isset($form_state['confirm_parents'])) { return array_merge($form, taxonomy_term_confirm_parents($form, $form_state, $vocabulary)); @@ -652,7 +681,7 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary = $form['name'] = array( '#type' => 'textfield', '#title' => t('Name'), - '#default_value' => $edit['name'], + '#default_value' => $term->name, '#maxlength' => 255, '#required' => TRUE, '#weight' => -5, @@ -660,18 +689,18 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary = $form['description'] = array( '#type' => 'text_format', '#title' => t('Description'), - '#default_value' => $edit['description'], - '#format' => $edit['format'], + '#default_value' => $term->description, + '#format' => $term->format, '#weight' => 0, ); $form['vocabulary_machine_name'] = array( '#type' => 'textfield', '#access' => FALSE, - '#value' => isset($edit['vocabulary_machine_name']) ? $edit['vocabulary_machine_name'] : $vocabulary->name, + '#value' => isset($term->vocabulary_machine_name) ? $term->vocabulary_machine_name : $vocabulary->name, ); - field_attach_form('taxonomy_term', (object) $edit, $form, $form_state); + field_attach_form('taxonomy_term', $term, $form, $form_state); $form['relations'] = array( '#type' => 'fieldset', @@ -686,23 +715,23 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary = // full vocabulary. Contrib modules can then intercept before // hook_form_alter to provide scalable alternatives. if (!variable_get('taxonomy_override_selector', FALSE)) { - $parent = array_keys(taxonomy_get_parents($edit['tid'])); - $children = taxonomy_get_tree($vocabulary->vid, $edit['tid']); + $parent = array_keys(taxonomy_get_parents($term->tid)); + $children = taxonomy_get_tree($vocabulary->vid, $term->tid); // A term can't be the child of itself, nor of its children. foreach ($children as $child) { $exclude[] = $child->tid; } - $exclude[] = $edit['tid']; + $exclude[] = $term->tid; $tree = taxonomy_get_tree($vocabulary->vid); $options = array('<' . t('root') . '>'); if (empty($parent)) { $parent = array(0); } - foreach ($tree as $term) { - if (!in_array($term->tid, $exclude)) { - $options[$term->tid] = str_repeat('-', $term->depth) . $term->name; + foreach ($tree as $item) { + if (!in_array($item->tid, $exclude)) { + $options[$item->tid] = str_repeat('-', $item->depth) . $item->name; } } $form['relations']['parent'] = array( @@ -718,7 +747,7 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary = '#type' => 'textfield', '#title' => t('Weight'), '#size' => 6, - '#default_value' => $edit['weight'], + '#default_value' => $term->weight, '#description' => t('Terms are displayed in ascending order by weight.'), '#required' => TRUE, ); @@ -728,7 +757,7 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary = ); $form['tid'] = array( '#type' => 'value', - '#value' => $edit['tid'], + '#value' => $term->tid, ); $form['actions'] = array('#type' => 'actions'); @@ -738,7 +767,7 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary = '#weight' => 5, ); - if ($edit['tid']) { + if ($term->tid) { $form['actions']['delete'] = array( '#type' => 'submit', '#value' => t('Delete'), @@ -759,7 +788,7 @@ function taxonomy_form_term($form, &$form_state, $edit = array(), $vocabulary = * @see taxonomy_form_term() */ function taxonomy_form_term_validate($form, &$form_state) { - field_attach_form_validate('taxonomy_term', (object) $form_state['values'], $form, $form_state); + entity_form_field_validate('taxonomy_term', $form, $form_state); // Ensure numeric values. if (isset($form_state['values']['weight']) && !is_numeric($form_state['values']['weight'])) { @@ -790,7 +819,7 @@ function taxonomy_form_term_submit($form, &$form_state) { return; } - $term = taxonomy_form_term_submit_builder($form, $form_state); + $term = $form['#builder_function']($form, $form_state); $status = taxonomy_term_save($term); switch ($status) { @@ -833,21 +862,16 @@ function taxonomy_form_term_submit($form, &$form_state) { } /** - * Build a term by processing form values and prepare for a form rebuild. + * Updates the form state's term entity by processing this submission's values. */ function taxonomy_form_term_submit_builder($form, &$form_state) { - $term = (object) $form_state['values']; + $term = $form_state['term']; + entity_form_submit_build_entity('taxonomy_term', $term, $form, $form_state); // Convert text_format field into values expected by taxonomy_term_save(). $description = $form_state['values']['description']; $term->description = $description['value']; $term->format = $description['format']; - - field_attach_submit('taxonomy_term', $term, $form, $form_state); - - $form_state['term'] = (array) $term; - $form_state['rebuild'] = TRUE; - return $term; } diff --git a/modules/user/user.pages.inc b/modules/user/user.pages.inc index 32c20a4d7..24b9a2b72 100644 --- a/modules/user/user.pages.inc +++ b/modules/user/user.pages.inc @@ -243,6 +243,18 @@ function template_preprocess_user_profile_category(&$variables) { function user_profile_form($form, &$form_state, $account, $category = 'account') { global $user; + // During initial form build, add the 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['user'])) { + $form_state['user'] = $account; + } + else { + $account = $form_state['user']; + } + + // @todo Legacy support. Modules are encouraged to access the entity using + // $form_state. Remove in Drupal 8. $form['#user'] = $account; $form['#user_category'] = $category; @@ -278,22 +290,23 @@ function user_profile_form($form, &$form_state, $account, $category = 'account') * Validation function for the user account and profile editing form. */ function user_profile_form_validate($form, &$form_state) { - $edit = (object) $form_state['values']; - field_attach_form_validate('user', $edit, $form, $form_state); + entity_form_field_validate('user', $form, $form_state); } /** * Submit function for the user account and profile editing form. */ function user_profile_form_submit($form, &$form_state) { - $account = $form['#user']; + $account = $form_state['user']; $category = $form['#user_category']; // Remove unneeded values. form_state_values_clean($form_state); - $edit = (object) $form_state['values']; - field_attach_submit('user', $edit, $form, $form_state); - $edit = (array) $edit; + entity_form_submit_build_entity('user', $account, $form, $form_state); + + // Populate $edit with the properties of $account, which have been edited on + // this form by taking over all values, which appear in the form values too. + $edit = array_intersect_key((array) $account, $form_state['values']); user_save($account, $edit, $category); $form_state['values']['uid'] = $account->uid; |