Recently I came across a requirement from a client who wishes to allow authenticated users to change their email, password and profile picture in another form. On top of that, he didn't want to see more than one submit button for the form so I cannot separate them in two sections. After some Googling I came up with the following steps which might serve as a handy reference for Drupal newbies like me in the future. There are better ways to do this but it is still nice to know how to call hook_form_alter to modify more than just textfields ;) I will not go into too much detail regarding each function call's syntax. There are already some very good examples online that cover all these functions. What I am sharing with you today are the steps of doing this task.
1) Modify the form using hook_form_alter()
Email can be fetched easily with "$user->email" to display on the form. Password and the profile picture can be blank on the form so you don't need to display any detail. We will use the regular 'textfield' type to display the email while passwords will be using the 'password confirm' type. You can also add a checkbox to trigger delete picture. Finally the upload picture field will be using the 'file' type. Note: do not use #maxlength in the password_confirm field for it might give you a "warning: mb_strlen() expects parameter 1 to be string, array given" message every time you submit the form.
Make sure your form_alter has "form['#validate']" and "form['#submit']" at the end to call your customized validation and submit function. By using the 'password_confirm' type form submit will automatically check if the passwords are identical. The main things you need to check are empty passwords, valid email syntax and the upload picture file name. If you need to overwrite the user's profile name(like rename it to the match the user id) then you can consider using the following code: $_FILES['file']['name'][_UPLOAD_VARIABLE_NAME_] = $user->uid.$file_extension;
3) Modifying hook_node_form_submit()
The final part is to submit the changes you added in hook_form_alter(). Since you are modifying the user information you will need to first call a 'user_load()' function by passing the current user id. Next you will need to create a new user info array to hold the update information. Later on you will need to pass the new user info array back in 'user_save()': $thisUser = user_load($user->uid); //this is the user array $newArray = array(); //just a name Next, you will need to update the submitted user information. Update the new user info array by adding changes to $newArray['mail'], $newArray['pass'] from the $form_state['values']fields. For the picture upload changes you also need to call the 'file_save_upload()' function. Basically by calling this 'file_save_upload()' function you will be able to save the uploaded profile picture. You will also need to update the $newArray['picture'] to the $file->filepath in order to save the profile image path to the user's data. Without that, even you saved the picture file Drupal will not be able to load the profile picture properly. Finally, if you are trying to delete the profile picture then simply set $newArray['picture'] to blank if the delete profile picture checkbox is checked.
4) Save the user node and update the rest of the form.
You can now call the 'user_save()' function to update the user data: user_save($thisUser, $newArray); Remember the rest of the form? You will still need to call the following; otherwise you will only be saving just the email, password and profile picture fields. $node = node_form_submit_build_node($form, $form_state); node_save($node); That's it! Now you have a regular form that allows you to update user's email, password and profile picture. You apply this concept to add other fields or merge two forms together etc.