Drupal admin: deleting many nodes

Submitted by Frederic Marand on

Ofttimes, when developing a site, you can be led to create or import a large number of custom nodes, for instance flexinodes, only to have to delete them later on. Doing it by hand in admin/content is inconvenient when the number of nodes is large, and for custom nodes like flexinodes, the exact entries to delete in the various Drupal tables may not be obvious. Time for a workaround.

The basic idea is to leverage the capabilites of the module defining the custom nodes: it will hopefully always include an implementation of hook_delete, which means Drupal will be able to delete these nodes cleanly using node_delete once the nid of each node to be deleted is known.

Using this, it's just a matter of selecting the nodes, typically based on their type, and invoking node_delete() in a loop. But there's a catch: on most shared hosting plans, the execution of a script is host-limited and cannot be raised by the webmaster (in other words set_time_limit() is unavailable on these plans). So any code will have to be executed several times. To optimize these recurring executions, we can check the time elapsed while looping on the deletions and stop a few seconds before the bell rings and the script is killed. Here is a possible code example for this:

WARNING: this code runs with absolutely no protection when executed as described below and can totally ruin your site. Be sure you have a backup before using it and understand what you're doing with it.

<?php
// First choose the type of nodes to be deleted
$type = 'flexinode-1';

// Then the script duration, supposing the host allows 20 seconds.
// Always leave some margin.
$seconds = 15;

// Now select the nodes
$sq = "select n.nid from {node} n where n.type = '%s'";
$ts0 = time();
$q = db_query($sq, $type);
$n = 0 ;

// Then delete as many as possible within the time allowed
echo "<pre>Deleting:\r\n ";
while (
$o = db_fetch_object($q))
  {
  echo
"$o->nid " ;
 
node_delete($o->nid);
 
$n++;
  if (
$n % 10 == 0)
    echo
"\r\n";
 
$ts1 = time();
  if (
$ts1 > $ts0 + $seconds)
    break;
  }

// Show the results
$sq = "select count(n.nid) cnt from {node} n where n.type = '%s'";
$q = db_query($sq, $type);
$o = db_fetch_object($q);
echo
"<pre>Deleted $n nodes in "
 
. ($ts1 - $ts0) . " seconds, "
 
. "$o->cnt nodes remaining.</pre>" ;

// Done
?>

Now this leaves a question opened: where should this code go ? There is in fact a very simple, although not very visible, way to execute arbitrary PHP code on a drupal server: this is the Drupal devel.module, usually not listed amongst the available modules for download on drupal.org, because it is only intendend for use by developers, and not just basic sysadmins. Once installed, it enables a menu choice leading to a page from which to run a PHP piece of code, in which the code above can be pasted and tweaked to one's needs.

Dekbed overtre… (not verified)

Tue, 2009-08-11 13:14

Hi, just what I need :). Looking at article date this will not apply on current Drupal versions. Is this compatible with Drupal 6?
Thanks!

That's the whole point: since it is using the Drupal node API to delete the node, it should work with CCK nodes on D6 too, if that's what your considering.

For D7, you'll likely need to convert to the new DBTNG API instead of traditional db_query(), but the deletion mechanism is the same.

Evgeny (not verified)

Thu, 2009-09-03 14:39

Thanks for solution! For Drupal 4.6, string
node_delete($o->nid);
should be replaced with
$edit=array();
$edit['nid'] = $o->nid;
$edit['confirm'] = 1;
node_delete($edit);