Index: modules/comment/comment.module =================================================================== RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v retrieving revision 1.616 diff -u -r1.616 comment.module --- modules/comment/comment.module 10 Jan 2008 15:03:53 -0000 1.616 +++ modules/comment/comment.module 14 Jan 2008 11:03:23 -0000 @@ -607,8 +607,7 @@ break; case 'delete': - db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid); - db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid); + comment_delete_node_comments($node); break; case 'update index': @@ -634,6 +633,99 @@ } /** + * Delete the comments of the given node. + * + * NOTE: use batch processing to prevent timeout when deleting + * a large number of comments. + * + * @param $node + * The node to delete comments from. + */ +function comment_delete_node_comments($node) { + // We use batch processing to prevent timeout when deleting a large number of comments. + $total = comment_num_all($node->nid); + if ($total > 10) { + $batch = array( + 'operations' => array( + // In this first batch operation the comments are proccesed and the hook_comment is invoked. + array('_comment_delete_node_comments_batch_process', array($node)), + // In this other operation the records are removed from the database. + array('_comment_remove_comments', array($node)) + ), + 'finished' => '_comment_delete_node_comments_batch_finished', + 'title' => t('Deleting node comments'), + // We use a single multi-pass operation, so the default + // 'Remaining x of y operations' message will be confusing here. + 'progress_message' => '', + 'error_message' => t('Errors deleting comments belonging to this post.'), + ); + batch_set($batch); + } + else { + $comments = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.nid = %d ORDER BY c.cid DESC', $node->nid); + while ($comment = db_fetch_object($comments)) { + $comment->name = $comment->uid ? $comment->registered_name : $comment->name; + comment_invoke_comment($comment, 'delete'); + } + _comment_remove_comments($node); + drupal_set_message(t('Comments belonging to this post have been deleted.')); + } +} + +/** + * Helper function to remove the comments from the database + * + * @param $node + * The node to delete comments from. + */ +function _comment_remove_comments($node) { + db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid); + db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid); +} + +/** + * Batch delete comments associated with a node. + */ +function _comment_delete_node_comments_batch_process($node, &$context) { + if (!isset($context['sandbox']['progress'])) { + $context['sandbox']['progress'] = 0; + $context['sandbox']['max'] = comment_num_all($node->nid); + $context['sandbox']['node'] = $node; + } + $node = $context['sandbox']['node']; + + // Process comments by groups of 10. + $limit = 10; + $comments = db_query_range('SELECT c.*, u.name AS registered_name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.nid = %d ORDER BY c.cid DESC', $node->nid, $context['sandbox']['progress'], $limit); + while ($comment = db_fetch_object($comments)) { + $comment->name = $comment->uid ? $comment->registered_name : $comment->name; + comment_invoke_comment($comment, 'delete'); + $context['sandbox']['progress']++; + } + + // Inform the batch engine that we are not finished, + // and provide a completion estimate. + if ($context['sandbox']['progress'] != $context['sandbox']['max']) { + $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max']; + } +} + +/** + * Node comments deletion Batch 'finished' callback. + */ +function _comment_delete_node_comments_batch_finished($success, $results, $operations) { + if ($success) { + drupal_set_message(t('The comments belonging to this post have been deleted.')); + } + else { + drupal_set_message(t('An error occurred and processing did not complete.'), 'error'); + $message = format_plural(count($results), '1 item successfully processed:', '@count items successfully processed:'); + $message .= theme('item_list', $results); + drupal_set_message($message); + } +} + +/** * Implementation of hook_user(). */ function comment_user($type, $edit, &$user, $category = NULL) {