Drupal Form submit - drupal

How could i sent the $first_name and $last_name variable values without attaching them in the url in the below example
function my_module_my_form_submit($form, &$form_state) {
$first_name = $form_state['values']['first'];
$last_name = $form_state['values']['last'];
drupal_goto("/my_view/".$first_name."/".$last_name);
}

First, you should not call drupal_goto() in a form submit handler. drupal_goto() will send the location header immediately and exit the process, thus preventing the rest of the submit function from being executed.
If you want to process your form, do it in the submit handler. Drupal form API uses the same URL to render the form and as the target URL.
If you need to redirect user after the form submit, do as follows.
function my_module_my_form_submit($form, &$form_state) { // $form_state is passed by reference! {
// .. Do submit handling here.
$form_state['redirect'] = 'my_view/'."$first_name/$last_name";
}
If you want to access them in in a latter step, store them in SESSION; See Raniel's answer.

You can use a $_SESSION variable:
$_SESSION['first_name'] = $first_name;
$_SESSION['last_name'] = $last_name;
then get this values from other page.

Related

Drupal custom form twice on same page, i need the errors displayed in the one submitted and not on both

I've a custom module that builds a form with a couple of fields, so far so good.
In one of my pages, i print this form twice (different blocks), the form gets the same "form_id", so when i submit one of them and get an error, both of them get the error highlighted, and the fields populated.
I want that only the form i submit gets the errors, is there a way to do this?
Thanks!!
For anyone interested, to do this you need to use the hook_forms.
This hook only gets called when the form_id passed to a drupal_get_form doesn't exist, this is important, if you want to use this, make sure your calls use a non existing form_id, for example:
//Defining the form:
function mx_wtransnet_form_contacto($form, &$form_state, $block = null, $formType = null) {
}
I want to use this form multiple times and get different error handlers, instead of loading my form (mx_transnet_form_contacto), i'll call a non existing one:
$form = drupal_get_form("mx_wtransnet_form_contacto_invalid", "contacto-mini");
Then i create my hook:
function mx_wtransnet_forms($form_id, $args) {
$forms = array();
if (strpos($form_id, '_contacto_') !==false) {
$forms[$form_id] = array(
'callback' => 'mx_wtransnet_form_contacto',
);
}
return $forms;
}
This function will catch all my druapl_get_form calls that don't exist, so i can process/direct them, in my example, what i do is simply check that the form_id contains contacto and then set the callback for this form to the original function.
In this case better to create another form with different "form_id" but with the same submit handler.
Another case: when you output same form twice on the page it also may get JS errors because ID of form elements are the same.
In case you don't repeat the form code and its submit handler(DRY principle), I would recommend create a custom function that has the form array
function form_my_custom($form_id){
$form['my_first_field'] = array();
$form['my_second_field'] = array();
$form['#attributes']['id'] = $form_id;
$form['my_submit_button'] = array(
'#submit' => array('my_custom_form_submit')
);
return $form;
}
function my_block1_form(){
return my_custom_form('my_form_id_1');
}
function my_block2_form(){
return my_custom_form('my_form_id_2');
}
function my_custom_form_submit(&$form, &$form_state){
// your submit handler.
}

Drupal login error message displayed without using form_set_error()

I created a module that adds a field to the user login block form to display errors. I want to display the error in the new field instead of using form_set_error(). I am able to see the warning field in the login block. But when I submit with an error it does not display the error.
Code is as follows. I do not understand how to refresh the value of form once it gets an error.
function usermoved_form_user_login_block_alter(&$form, &$form_state) {
$form['warning'] = array(
'#value' => t('oops'),
'#weight' => 11
);
$form['#submit'][] = 'usermoved_form_submit_code';
}
function usermoved_form_submit_code($form, &$form_state) {
global $user;
if (!$user->uid) {
$form['warning']['value']= "changed to someting";
}
}
Your code is wrong: Instead of using $form['warning']['value'], it should use $form['warning']['#value']. Even doing so, the message (which should be passed to t()) is not shown to the users because $form is not passed by reference, and it is not the value returned from the form submission handler, which is not expected to return any value.
Form submission handlers are then never called, when a form validation handler raises an error. If you are checking the user ID to see if the user has not been logged-in, then you cannot do it in a form submission handler, as the user not being logged-in means there have been errors during the validation phase, and the form submission handlers are not invoked.
What you can use is a form validation handler.
function usermoved_form_user_login_block_alter(&$form, &$form_state) {
$message = (empty($_SESSION['usermoved_form_user_login_block_alter']) ? t('Initial message') : $_SESSION['usermoved_form_user_login_block_alter']);
$form['warning'] = array(
'#value' => $message,
'#weight' => 11
);
$form['#validate'][] = 'usermoved_form_validate_code';
}
function usermoved_form_validate_code($form, &$form_state) {
if (empty($form_state['uid'])) {
$_SESSION['usermoved_form_user_login_block_alter'] = t('The error message');
}
else {
unset($_SESSION['usermoved_form_user_login_block_alter']);
}
}
$form_state['uid'] is a value set from user_login_authenticate_validate(), the second validation handler invoked by Drupal. When it is not set, it means there have been some errors before Drupal tried to authenticate the user, or the user didn't authenticate. The first case can happen when the user is blocked (user_login_name_validate() verifies that), or the user tried too much times to authenticate (see user_login_authenticate_validate() which uses flood_is_allowed() to verify the user didn't try too much times to authenticate); the latter case can happen when the user didn't enter the right password. (See user_login_final_validate().)
As side notes:
I used t('Initial message') as default message, but that could be replaced with '', if you don't have any message to show to the users before they log in.
The user login block is not shown to already logged-in users. $user->uid (where $user is the global variable) is always 0, when the login block is shown, and when logging-in failed; checking the value of $user->uid while showing the login block doesn't make sense.

Override user_login_submit in Drupal 6 to redirect an authenticated user

I would like to redirect a user that logged in over the user login block. What I have is a module that contains the following code:
Appendix, 3.9.2011, 15:30h: Changed code according to the advice of kiamlaluno.
Appendix, 3.9.2011, 17:08h: Small Fix: Changed node/admin to admin.
Appendix, 3.9.2011, 17:24h: removed []
-> code is working like this now, but do not forget to change the module priority in DB.
function _MYMODULE_user_login_submit($form, &$form_state) {
global $user;
if ($user->uid == 1) {
$form_state['redirect'] = 'admin';
} elseif ($user->uid) {
$form_state['redirect'] = 'node/add/image';
return;
}
}
/**
* Modifies the outfit and behaviour of the user login block.
*/
function MYMODULE_form_user_login_block_alter(&$form, $form_state) {
unset($form['#action']);
// removes the forgot password and register links
$form['links'] = array();
// Redirects the user to the image upload page after login
// This cannot be done by a rule, the rule based redirect is only
// working for the login page not the user login block.
$form['#submit'] = array('_MYMODULE_user_login_submit');
}
It doesn't redirect users; it seems like _MYMODULE_user_login_submit() is simply ignored.
What I know already:
I cannot use Rules/Triggers, because I do not login over the login page but the user login block
It is always said: "use logintoboggan" on posts, but there I only have redirection options for "on registration" and "on confirmation", but I need "on authentication" or "after login".
Anyway, I do not want to use more modules, I prefer a few lines of PHP.
Your code doesn't work because user_block_login() sets the "#action" property for the form; in that case, redirecting the form after submission doesn't work.
$form = array(
'#action' => url($_GET['q'], array('query' => drupal_get_destination())),
'#id' => 'user-login-form',
'#validate' => user_login_default_validators(),
'#submit' => array('user_login_submit'),
);
To make it work, you should first unset $form[#action], and then executing the code you already execute in your hook_form_alter() implementation.
As side notes, I will add:
If you want to be sure your code effectively redirect the user where you want, be sure your module is executed for last; if any other module that implements hook_form_alter() adds a form submission handler to redirect the user to a different page, and that module is executed after yours, then your module would not have any effect. To make sure your module is executed after the others, you should use code similar to the following during the installation of the module, or in an update hook. (Replace "MYMODULE" with the short name of the module.)
db_query("UPDATE {system} SET weight = 100 WHERE name = 'MYMODULE');
Instead of using MYMODULE_form_alter(), you can use `MYMODULE_form_user_login_block_alter(), which would not require to check the form ID.
You should append new form submission handlers, instead of replacing the existing ones. This means you should use $form['#submit'][] = 'user_login_submit_redirected';.
Functions implemented in a module should be prefixed with the short name of the module, which means "MYMODULE_" or "_MYMODULE_" (the latter is for private functions). Not using such prefix could create a compatibility issue with other module, such as the User module, as the function you are using has a name starting with "user_."
can u try this please
function user_login_submit_redirected($form, &$form_state) {
global $user;
if ($user->uid == 0) {
$form_state['redirect'] = 'node/admin';
drupal_goto('node/admin') ;
} elseif ($user->uid) {
$form_state['redirect'] = 'node/add/image';
drupal_goto('node/add/image') ;
return;
}
}

Form submit handlers with additional arguments

For some requirement I need to pass additional information to form submit handler. In form api, while defining custom submit handler as
$additional_args = array();
$form['#submit'][] = 'my_submit_handler'
I expect to submit handler as
function my_submit_handler($form, &$form_state, $additional_args){
The submit handler is called by the drupal fapi, so you can't do something like that. Instead what you can do, is to add what you need, either to the $form, or to the $form_state. The usual approaches is to:
Added a field to the form, type value to store the value. Don't do this if you have the value in the form definition.
$form['store'] = array(
'#type' => 'value',
'#value' => $value
);
This will be available in $form_state['values']['store'].
Add the value to $form_state['storage'], done if you variables in your validation handle you want to transfer to your submit handler:
// Validation.
$form_state['storage']['value'] = $value;
...
// Submit
$value = $form_state['storage']['value'];
// Need to unset stored values when not used anymore.
unset($form_state['storage']['value']);
Drupal 7: Custom arguments are automatically propagated troug $form_state['build_info']['args']
This is said in http://api.drupal.org/api/drupal/includes!form.inc/function/drupal_get_form/7
Ex:
hook_form($form, &$form_state, $myAdditionnalArg) {...}
Then in
hook_form_submit($form, &$form_state) {
...
//$form_state['build_info']['args'] is an array containing at index 0 the value of argument $myAdditionnalArg
...
As reported in $form['#submit'] and $form['#validate'] and $form['#process'] no longer support custom parameters, the suggested way to pass parameters to a submission handler set as in the shown code is to use code similar to the following:
$form['#first_paramater'] = $value;
$form['#submit'][] = 'my_submit_handler';
The handler would retrieve the value as $form['#first_paramater'].
To notice that, instead of #first_paramater, the code can use a different string, but it must start with #.
Normally it's not necessary to set a submission handler like the code does, but there are some cases where it is necessary, like to alter a form created by another module, or to set a different submission handler for each of the submission buttons present in a form.
drupal_retrieve_form() saves the parameters passed to the form build handler in $form['#parameters'] which contains:
$form_id
$form_state
parameters passed to the form builder

Preventing form_token from rendering in Drupal "GET" forms

Drupal inserts a form_token as a hidden field when it renders forms. The form_token is then checked on form submission to prevent cross-site request forgery attacks. The form data that is submitted is guaranteed to have come from the original form rendered by Drupal.
However, forms using the "GET" method shouldn't need this token. All it does is lengthen and uglify the resulting URL.
Is there any way of suppressing it?
Yes, there is a way, but use it consciously (see warning below):
If you create the form yourself, adding
$form['#token'] = FALSE;
to the form definition array should prevent a token from being generated in the first place.
If you are dealing with an existing form, you can bypass the token validation process by unsetting the '#token' element on hook_form_alter:
// Example for removal of token validation from login (NOTE: BAD IDEA!)
function yourmodule_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'user_login_block') {
unset($form['#token']);
}
}
Warning: Given your question, I think there is a slight misconception concerning the difference (better, the lack of a difference) between GET and POST requests.
... on forms using the "GET" method
shouldn't need this token. All it does
is lengthen and uglify the resulting
URL.
This is wrong! GET and POST are just two different, but mostly equivalent methods of transmitting data from the client to the server. Since POST is better suited to transfer large amounts of data (or difficult formatted data), it is the established standard for submitting forms, but it is in no way safer/unsafer or more/less secure than GET requests. Both type of requests can be tampered with by malicious users in the same ways, hence both types should use the same protection mechanisms.
With a GET request, the token does exactly the same as with a POST request - it proves to the server that the submitted data comes from the same Browser on the same machine as the request he build the form for! So you should only remove it if you are sure that the request can not be misused via XSRF.
This worked for me. I had to unset all the form api elements and set the #token property to false. Notice the after_build function for unsetting the other properties.
function mymodule_form(&$form_state){
$form['name'] = array(
'#type' => 'textfield',
'#title' => 'name',
'#value' => 'name',
);
$form['#method'] = 'get';
$form['#action'] = url('someurl');
$form['submit'] = array('#type' => 'submit', '#value' => 'go');
$form['#token'] = false;
$form['#after_build'] = array('mymodule_unset_default_form_elements');
return $form;
}
function mymodule_unset_default_form_elements($form){
unset($form['#build_id'], $form['form_build_id'], $form['form_id']);
return $form;
}
The site I work on uses the Drupal 6 form API for custom search forms, so by removing the token and build id we were able to cache the results in memcache. Now we've moved to Acquia hosting, it's cached using Varnish.
To remove the form_token and form_build_id from your form and submit it as a GET request, use the following method:
<?php
function module_example_form($form_state, $form_id = NULL) {
// Form root settings.
$form = array();
// Set the submission callback for this form.
$form['#submit'][] = __FUNCTION__ . '_submit';
// Set the request method for this form to GET instead of the default
// of POST.
$form['#method'] = 'get';
// Remove unique form token so request can be cached. This is accompanied by
// code in hook_form_alter to ignore the token and remove the build_id.
$form['#token'] = FALSE;
// Submit button.
$form['go'] = array(
'#type' => 'submit',
'#value' => t('Go!'),
);
return $form;
}
/**
* Implements hook_form_alter().
*/
function module_form_alter(&$form, $form_state, $form_id) {
// Changes to the 'module_example_form' form.
if ($form_id == 'module_example_form') {
// Unset the hidden token field and form_build_id field.
unset($form['#token'], $form['form_build_id'], $form['#build_id']);
}
}
?>
I find that simply throwing away the CSRF token is not an option. We solved it using hook_theme_registry_alter() to overwrite the Drupal core theme_hidden() function so that the hidden form element 'form_token' is rendered as an <esi /> tag. The tag will cause Varnish to make a call to a PHP file which we allow to pass through the cache. This file will calculate the proper form token for the current user and will then output the HTML code for the hidden field. You can calculate this token without a Drupal bootstrap, but you will need a single DB query to fetch the *drupal_private_key* for your site, which is stored in the variable table.

Resources