background image

Content tagged with: form_alter

Eric's picture

For my blog, I thought it would be great if I was notified when a comment was submitted. Like most of my articles, I try to explain how to accomplish something by implementing your own module hooks. In this article, I'll explain how I modified the comment form using a form_alter hook, and added an additional submit handler to send an email using drupal_mail.

First, I defined a form_alter hook to modify the comment form submit handlers

<?php
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
 
// test for comment form
 
if ($form_id == 'comment_form') {
   
// add an additional submit handler
   
$form['#submit'][] = '_MYMODULE_comment_form_submit';
  }
}
?>

Next, I created the submit handler function

<?php
function _MYMODULE_comment_form_submit($form, &$form_state) {

 
// create an array of parameters
 
$params = array(
   
// NOTE: I tried using l() here,
    // but links don't work very well in text emails
       
    // this link will send me back to the node with an anchor to the comment
   
'commentLink' => 'http://' . $_SERVER['HTTP_HOST'] . base_path() .
     
$form_state['redirect'][0] . '#' . $form_state['redirect'][2]
  );
   
 
// call mail function and send email
 
drupal_mail('MYMODULE', 'comment_submitted',
   
variable_get('site_mail','MYDEFAULTEMAIL'), language_default(), $params);

}
?>

Lastly, I defined the mail hook

<?php
function MYMODULE_mail($key, &$message, $params) {
 
$language = $message['language'];
  switch(
$key) {
    case
'comment_submitted':
           
     
// create an array of variables from the parameters argument
     
$variables = array(
       
'!commentLink' => $params['commentLink'],
      );
           
     
// define subject and body
     
$message['subject'] = t("A comment has been submitted");
     
$message['body'] = t("!commentLink", $variables, $language->language);
           
      break;
  }
}
?>

Now when a comment is posted, my submit handler is called which notifies me of the new comment.

Eric's picture

This code snippet shows you how you can modify a preexisting form and insert an anchor, which will allow you to link to a specific form element from your content. This could be useful if you'd like a user to update their profile details or fill out a certain section of a form. In this example, I add an anchor to the user profile form picture fieldset.

<?php
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
 
// check for the user profile form
 
if ($form_id == 'user_profile_form') {
   
// add a new anchor form element
   
$form['picture']['anchor'] = array(
     
'#value' => '<a name="MYMODULE_picture"></a>',
    );
  }
}
?>

Then in my content, I added a link with an anchor.

<?php
$html
.= l('Upload profile picture', 'user/' . $GLOBALS['user']->uid . '/edit',
  array(
'fragment' => 'MYMODULE_picture')
);
?>

Eric's picture

Unfortunately, the stock Drupal contact module does not satisfy everyone's functional requirements. I decided to weigh alternative solutions, but since all I wanted to do was add an additional field to the form and email, I decided to add a few lines of module code instead. This solution consists of adding a form_alter hook to modify the contact form and submit handler, and an additional submit handler function:

<?php
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
 
// check for contact form
 
if ($form_id == 'contact_mail_page') {
       
   
// prefix another submit handler
   
array_unshift($form['#submit'], '_MYMODULE_mail_page_submit');
       
   
// NOTE: since I want to insert the form element at a certain point,
    // I have to create a new $form object
   
$newForm = array();
       
   
// define insertion point
   
$ip = 'message';
       
   
// lop through $form object and duplicate the values
   
foreach ($form as $k => $v) {
           
     
// check for insertion point and add new form element
     
if ($k == $ip) {
       
// add phone number
       
$newForm['phone'] = array(
         
'#type' => 'textfield',
         
'#required' => true,
         
'#title' => 'Phone',
        );
      }
           
     
$newForm[$k] = $v;
    }
       
   
// replace $form object with new form
   
$form = $newForm;

  }
}

function
_MYMODULE_mail_page_submit($form, &$form_state) {   

 
// Since message is required by default,
  // I can concatenate the new form field onto the message variable
 
if (!empty($form_state['values']['phone'])) {
   
$form_state['values']['message'] .= "\n\nPhone: " . $form_state['values']['phone'];
  }
   
}
?>

Now, if I browse to the contact form, there is a new field (phone number in this example) inserted right above the message textarea. When I submit the form, the email sent contains the phone number as well.

Eric's picture

At some point you might want add validation to the user edit form to ensure username is a valid email address. You can accomplish this by adding a form_alter hook, testing for the user profile form, and adding a validation handler to the $form object.

<?php
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
 
// test for the user profile edit form
 
if ($form_id == 'user_profile_form') {
   
// add another validation function to the list
   
$form['#validate'][] = '_MYMODULE_form_alter_user_profile_validate';
  }
}

// define the validation function
function _MYMODULE_form_alter_user_profile_validate($form, &$form_state) {
 
// validate the username and set a form error as necessary
 
if (!valid_email_address($form_state['values']['name']))
   
form_set_error('name', 'Username must be a valid email address.');
}
?>

Eric's picture

In a recent project I used the content profile module to improve flexibility in creating user profiles. This module replaces the regular profile creation with a CCK node type. One of the requested profile fields was job title, which is confusing since title is already a required field of a node. In most cases, I would use first and last name as the title, but in this case those fields were required to be separate. Since the node title did not fit into the list of requested fields, I decided to remove it from the form and dynamically generate a node title from the user's first and last name. Here's how this can be accomplished:

<?php
// create a form_alter hook to remove the field from the form:
function MYMODULE_form_alter(&$form, $form_state, $form_id) {

  if (
$form_id == 'profile_node_form') {
   
// remove title from view
   
$form['title']['#access'] = false;
  }
   
}

// create a nodeapi function to create the node title when the node is created
function MYMODULE_nodeapi(&$node, $op, $a3=NULL, $a4=NULL) {
  if (
$node->type =='profile' && $op=='insert') {
   
$node->title = $node->field_profile_name_first[0]['value'] . " " . $node->field_profile_name_last[0]['value'];
   
node_save($node);      
  }
}
?>