background image

Content tagged with: form_alter

Eric's picture

This code snippet will should you how to add additional functionality to a system form when it's submitted. You can do this in Drupal 5.x using a form_alter hook to modify the submit handlers on the form object. In my example, I'll show you how to add your own function that will executed when the contact form is submitted.

<?php
function MYMODULE_form_alter($form_id, &$form) {
 
// check for the form ID you'd like to alter
 
if ($form_id == 'contact_mail_page') {
   
// modify the "#submit" form property by prepending another submit handler array
   
$form['#submit'] = array_merge(
      array(
'_MYMODULE_contant_mail_page_submit' => array()),
     
$form['#submit']
    );
  }
}
?>

Now, when the contact form is submitted, you're submit handler will be processed as well. You'll need to define a function with the same name.

<?php
function _MYMODULE_contant_mail_page_submit($form_id, $form_values) {
 
// do whatever you'd like here and it will be executed when the contact form is submitted
}
?>

Eric's picture

Drupal 6 comes with greatly improved usability, such as the ability to reposition node form elements by dragging and dropping (unlike Drupal 5, which made you assign a numeric weight to each item). But what about the form elements that Drupal does not let you adjust, like the revision information? You can implement a form_alter hook to solve this one...

<?php
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
 
// node add/edit form
 
if (substr($form_id, -10)=='_node_form') {
   
// manually set a weight on the revision fieldset
   
$form['revision_information']['#weight'] = -100;
  }
}
?>

Eric's picture

Here are some tips on how to create a node programmatically in a Drupal module. The safest way to create a node is to use the drupal_execute() function which simulates the submission of a form [see API documentation]. This function accepts a variable number of arguments: 1) $form_id; 2) $form_state; and 3) any additional arguments. When creating a new node, the 3rd argument should be a $node object.

The $form_id should be formatted: NODETYPE_node_form. To confirm this, you could use hook_form_alter to show the form IDs for the current page (NOTE: you'll have to be on node/add/NODETYPE to display the node form ID).

<?php
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
  echo
$form_id . "<BR>";
}
?>

For the second argument, you'll have to create an array that contains $form_state values (the data submitted from the node/add/NODETYPE form). Here is a basic $form_state array:

<?php
$form_state
= array();
$form_state['values'] = array(
 
'title' => t('MYTITLE'),
 
'body' => t('MYBODY'),
 
'name' => $GLOBALS['user']->name,
 
'op' => t('Save'),
);
?>

If you are creating a more complex node type, you'll want to include more information in in the $form_state['values'] array. I find it helpful to view the submitted node form data using the following code:

<?php
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
 
// ensure we are modifying the right node type
 
if ($form_id == 'NODETYPE_node_form') {
   
// add an additional validation handler
   
$form['#validate'][] = '_MYMODULE_node_form_validate';
  }
}

function
_MYMODULE_node_form_validate($form, &$form_state) {
 
// display the submitted data and then die
 
echo "<pre>";
 
print_r($form_state['values']);
  echo
"</pre>";
  die;
}
?>

Now, if you create a test node (node/add/NODETYPE), you'll see the data that's being submitted from the form. NOTE: be sure to remove these two functions when you are familiar with the structure of the $form_state variable.

The 3rd argument will be a (mostly) empty $node object containing the node type:

<?php
$node
= (object) NULL;
$node->type = 'NODETYPE';
?>

Here's a code snippet that shows all the pieces together:

<?php
// create $form_state
$form_state = array();
$form_state['values'] = array(
 
'title' => t('MYTITLE'),
 
'body' => t('MYBODY'),
 
'name' => $GLOBALS['user']->name,
 
'op' => t('Save'),
);

// create $node
$node = (object) NULL;
$node->type = 'NODETYPE';

// include node file, necessary for node generation
module_load_include('inc', 'node', 'node.pages');

// create node using drupal_execute
drupal_execute('NODETYPE_node_form', $form_state, $node);
?>

Eric's picture

A recent task that came my way way to create the functionality to capture email addresses using a simple subscription form. Since email is not a reliable means of capturing data, I used CCK to create nodes to capture the data and a view to show the results. First, I create a CCK node type called "email_subscription" which did not have a body or any custom fields, just the title for email address. I then created a view that shows the nodes in a table. Here's the module I created that generates a block module that contains the CCK node form. The block uses the CCK node form to capture the data. When the node is created, it uses the nodeapi hook to send a conformation email. There is also a function to validate the user's email address.

<?php
function MYMODULE_subscribe_block($op='list', $delta=0) {
 
// listing of blocks, such as on the admin/block page
 
if ($op == "list") {
   
$block[0]["info"] = t('Subscribe Block');
    return
$block;
  } else if (
$op == 'view') {
   
$block['subject'] = 'Subscribe';
   
$block['content'] = _MYMODULE_subscribe_block_main();
    return
$block;
  }
}

function
_MYMODULE_subscribe_block_main() {
 
// show the cck node form
 
return drupal_get_form('email_subscription_node_form',
    array(
     
'type' => 'email_subscription',
     
'uid' => $GLOBALS['user']->uid,
     
'name' => $GLOBALS['user']->name,
    )
  );
}

function
MYMODULE_subscribe_form_alter($form_id, &$form) {
  if (
$form_id == 'email_subscription_node_form') {
   
// remove preview button
   
unset($form['preview']);

   
// add custom validation
   
$form['#validate'] = array_merge(array('_MYMODULE_subscribe_node_form_validate' => array()), $form['#validate']);
  }
}

function
_MYMODULE_subscribe_node_form_validate($form_id, $form_values, $form) {
 
// validate title as email address
 
if (!valid_email_address($form_values['title'])) form_set_error('title', 'Email is not valid.');

 
// get list of already submitted emails
 
$sql = "select title from {node} where type = 'email_subscription'";

 
// if editing an existing node:
 
if ($form_values['nid']) $sql .= " and title!='" . db_escape_string($form_values['title']) . "'";

 
$resource = db_query($sql);
 
$results = array();
  while (
$row = db_fetch_array($resource)) $results[] = $row['title'];

 
// ensure email address has not already been subscribed
 
if (in_array($form_values['title'],$results)) form_set_error('title', 'Email has already been subscribed.');

}

function
MYMODULE_subscribe_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  if (
$node->type == 'email_subscription' && $op=='insert') {
   
// send email to user
   
mail($node->title, variable_get('site_name') . ' Subscription', 'Thank you for subscribing!', "From: " . variable_get('site_mail'));
  }
}
?>

Eric's picture

I recently decided to use taxonomy to set the status of my nodes as they moved through phases of the application. A created a category called status and added the terms: incomplete, complete, and submitted. I needed the ability to restrict who can set the taxonomy, so I wrote this module which allows you to set which roles can modify taxonomy...

<?php
function tpr_perm() {
  return array(
'modify node taxonomy');   
}

function
tpr_form_alter(&$form, $form_state, $form_id) {

 
// ensure this is a node form
 
if (substr($form_id,-10)!='_node_form') return;
   
 
// ensure taxonomy exists for this node type
 
if (!isset($form['taxonomy'])) return;
   
 
// if the user does not have permission to modify node taxonomy:
 
if (!user_access('modify node taxonomy')) {

   
// node already exists
   
if (isset($form['#node']->nid)) {
           
     
// loop through taxonomy form elements
     
foreach ($form['taxonomy'] as $k => $v) {

       
// set each form element to disabled
       
if (is_int($k) && is_array($v)) {
         
$form['taxonomy'][$k]['#disabled'] = true;   
        }

      }
           
    } else {
     
// new node, remove taxonomy from elements
              
      // loop through taxonomy from elements
     
foreach ($form['taxonomy'] as $k => $v) {

        if (
is_int($k) && is_array($v)) {

         
// get first termID
         
$termID = array_shift(array_keys($v['#options'][0]->option));
                   
          if (
is_int($termID)) {
           
// set default option
           
$form['taxonomy'][$k]['#default_value'] = $termID;   
          }
                   
         
// set element as disabled
         
$form['taxonomy'][$k]['#disabled'] = true;   
        }

      }
           
    }

  }
   
}
?>