This is part three of a series. If you haven't already, you might be interested in reading previous articles.
- Part 3: Catching Duplicates With hook_form_alter()
- Part 2: How To Create a Bookmarklet
- Part 1: How To Build A Personal Nodetracker
In this tutorial, we are going to implement the hook_form_alter() function to test for duplicate entries based on a form field.
I'll be using the nodetracker content type that we built in previous tutorials for demonstration purposes, but the general method is applicable to any form or content type within Drupal.
Now that we have our nodetracker built, we have a small problem. What if we stumble across an interesting looking node, but can't remember if we've already added it to our tracker?
It would be great if upon submission, we could code our nodetracker to reject any entries that have the same node id as a previously submitted entry. There are a number of ways that we could accomplish this. We could implement hook_submit and check to see that the node being submitted doesn't already exist in the database when the node is being saved, or we could implement hook_validate to make the same check when the form contents are being validated.
But both of those solutions require us to have all the necessary form fields filled out and the submit button clicked before they come into effect.
What I want is some sort of immediately visible indication that I am trying to submit a drupal.org node that I have already added to my nodetracker in the past.
The solution? hook_form_alter
hook_form_alter() allows us to modify form contents at the time of rendering. It is the perfect solution for our problem.
We are going to put our code into a custom module. If that sounds scary, it shouldn't. Having your own module space to plug in individualized code for your website is generally a good idea. Sure, you can hack most stuff in at the template level, but that is a bit of a kludge and often a pain to maintain.
Create a file in your modules directory, and give it a recognizable name. The name of your website - or an abbreviation of that name - is a good idea. I've called mine wwdd.module.
<?php
function wwdd_form_alter($form_id, &$form) {
if ($form_id == 'content_nodetrack_node_form') {
if (isset($form['field_nodetrack___nodeid'])) {
$nodeid =
$form['field_nodetrack___nodeid']
['0']
['value']
['#default_value'];
$query = "SELECT n.field_nodetrack___nodeid_value FROM
{node_content_nodetrack} n WHERE
field_nodetrack___nodeid_value=" . $nodeid;
$result = db_fetch_object(db_query($query));
if ($result) {
$form['field_nodetrack___nodeid']
['0']
['value']
['#default_value'] = 'DUPE!';
unset($form['submit']);
unset($form['preview']);
}
}
}
}
?>Ok. So what does this do, exactly?
function wwdd_form_alter($form_id, &$form) {
First we declare that any time Drupal is serving up a form, it should call our function in order to let us modify it if necessary.
if ($form_id == 'content_nodetrack_node_form') {Here we check to make sure that the form Drupal is serving up is, in fact, the form that we are interested in altering.
if (isset($form['field_nodetrack___nodeid'])) {And here we check to make sure that the nodeid field has actually been set to some value.
If you aren't sure exactly what the form id or the field id are for the particular form you might be working with, all you need to do is pull up the form (ie. through the "create content" page) and viewing the source. You will find all the forms and form fields labeled.
$nodeid =
$form['field_nodetrack___nodeid']
['0']
['value']
['#default_value'];
$query = "SELECT n.field_nodetrack___nodeid_value FROM
{node_content_nodetrack} n WHERE
field_nodetrack___nodeid_value=" . $nodeid;In the first section, we assign the value of the nodeid form field to the variable $nodeid. Because we've been using the prepopulate module to fill in these fields through the URL, when we are using our bookmarklet the #default_value of this field will already be set to the node number of the drupal.org node that we want to track.
In the second section, we are building a database query to pull up any nodes of the type "nodetrack - nodeid" where the node id value is the same as the node id number that we've passed in trhough the URL. Remember, we are checking for duplicate entries here.
$result = db_fetch_object(db_query($query));
if ($result) {
$form['field_nodetrack___nodeid']
['0']
['value']
['#default_value'] = 'DUPE!';
unset($form['submit']);
unset($form['preview']);
}If the database returns any results, then we know we have a duplicate entry. For immediate visual feedback, I've decided that such cases should change the form entry textfield to "DUPE!" (Duplicate!), and just in case I'm not paying attention, also remove the submit and preview buttons from the form entirely.
So, let's see what happens when I try to add a new (unique) node to my nodetracker ...

Great. Just as it should be.
And if I try to add duplicate content?
In the last tutorial, I added node #260 (Installing Drupal) to my nodetracker. What happens if I try to add it again?

And if somehow I miss that glaring "DUPE!" yelling at me, I don't even have a submit button to click on. Perfect.
As I said, this isn't limited to the nodetracker by any means. These techniques can work just as well with any node type, or any form. The hook_form_alter function is a powerful beast. In fact, the entire Drupal hook system is incredibly well conceived and extremely robust.






map