ted serbinski – entrepreneur & web architect
  • thoughts
  • about
  • contact



Popular content

  • Tracking External Links and "In-Network" Links with Google Analytics and jQuery
  • New external links filter for Drupal
  • How to make theming in Drupal easier
  • Speeding up CSS and JS in Drupal
  • Blueprint Drupal Theme Released
  • My latest patch: fixing links and breaking modules
  • Drupal on Inside the Net
  • MTV.co.uk
  • How often do you change your oil? Maybe too often...
  • "Black & Blue" Drupal Theme Released
more

Recent comments

  • really interesting and well
    5 days 14 hours ago
  • cloning the
    3 weeks 5 days ago
  • vacabindex module (drupal
    4 weeks 1 day ago
  • I seem not to know where to
    4 weeks 2 days ago
  • Hi guys, Here a module
    5 weeks 6 days ago
more

Preventing duplicate posts: part 2

In a previous article, I wrote about how to use jQuery to remove submit form buttons and replacing it with some “Saving…” text to prevent duplicate form submissions.

While this works well, it only works about 90-95% of the time—rest of the time the user either reloads the page and resubmits or has JavaScript off.

Then what do you do?

Well I originally helped write a patch to prevent duplicate form submissions in Drupal 5 and it lived for a bit but was recently removed because of the complexity and breakage it introduced. And it didn’t work all the time either I discovered :-)

And now, as MothersClick is growing quite fast, we’re hitting this duplicate issue a couple times, which is greatly exacerbated by our integration with groups and email notifications—a duplicate post is now a duplicate email, eek!

So here’s how I solved it for our site. Create a new module for your site, and use hook_nodeapi and hook_comment to catch duplicates before they are saved into the database.

Here’s the code for hook_nodeapi:

  1. /**
  2.  * Implementation of hook_nodeapi().
  3.  */
  4. function YOUR-MODULE_nodeapi(&$node, $op, $teaser, $page) {
  5.   switch ($op) {  
  6.     case 'validate':
  7.       // find a duplicate node of the same type with the same title
  8.       // compare the created time of the duplicate node to now, if it is within the past 6 minutes this is very likely a duplicate
  9.       $duplicate = db_result(db_query("<span class="caps">SELECT</span> nid <span class="caps">FROM</span> {node} <span class="caps">WHERE</span> type = '%s' <span class="caps">AND</span> title = '%s' <span class="caps">AND</span> (created >= %d – 360) <span class="caps">LIMIT</span> 1", $node->type, $node->title, time()));
  10.  
  11.       if ($duplicate > 0) {
  12.         // since is most likely a duplicate, set an error so a duplicate isn't created
  13.         form_set_error('title', t('<a href="!url">A duplicate entry has been found</a>. This usually results from clicking the submit button more than once. If you are having trouble, please <a href="!contact">contact us</a>.', array('!url' => url('node/'. $duplicate), '!contact' => url('contact'))));
  14.       }
  15.  
  16.       break;    
  17.   }
  18. }

And the code for hook_comment:

  1. /**
  2.  * Implementation of hook_comment().
  3.  */
  4. function YOUR-MODULE_comment($a1, $op) {
  5.   switch ($op) {
  6.     case 'validate':
  7.       // find a duplicate comment with the same body, since the subject is not required
  8.       // compare the timestamp of the duplicate comment to now, if it is within the past 6 minutes this is very likely a duplicate
  9.       $duplicate = db_result(db_query("<span class="caps">SELECT</span> cid <span class="caps">FROM</span> {comments} <span class="caps">WHERE</span> nid = %d <span class="caps">AND</span> comment = '%s' <span class="caps">AND</span> (timestamp >= %d – 360) <span class="caps">LIMIT</span> 1", $a1['nid'], $a1['comment'], time()));
  10.  
  11.       if ($duplicate > 0) {
  12.         // since is most likely a duplicate, set an error so a duplicate isn't created
  13.         form_set_error('comment', t('<a href="!url">A duplicate entry has been found</a>. This usually results from clicking the submit button more than once. If you are having trouble, please <a href="!contact">contact us</a>.', array('!url' => url('node/'. $a1['nid'], <span class="caps">NULL</span>, 'comment-'. $duplicate), '!contact' => url('contact'))));
  14.       }
  15.  
  16.       break;
  17.   }
  18. }

While this isn’t a 100% guarantee to stop duplicate content, it is now stopping all duplicate content we have seen—and, what makes a better usability test case than your mom? :-)

And while you’re at it, why not add a nice performance boost to your site? Remove comment modules duplicate SQL check since it actually doesn’t do anything but produce a watchdog warning, which isn’t helpful.

Should this go into Drupal 6? Well yes, but this might not be most optimal generic solution for everyone, but for MothersClick and my related projects, it’s good enough for me :-)

posted 4 Jun 2007
  • drupal
  • MothersClick

1 comment

#1
martijn wrote 1 year 24 weeks ago

Hi,

I was wondering if you also have a solution for duplicate links in the site?

greetings,
Martijn

Add your comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <p> <img> <pre>
  • Web page addresses and e-mail addresses turn into links automatically.
  • You can use Textile markup to format text.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>. Beside the tag style "<foo>" it is also possible to use "[foo]". PHP source code can also be enclosed in <?php ... ?> or <% ... %>.

More information about formatting options


Code examples and downloadable zip files of code are licensed under a Creative Commons License.
All other content, unless where noted, ©2009 Theodore Serbinski. All Rights Reserved.