Permit the administrator to delete a single comment, without
also deleting all of its descendents.
http://drupal.org/node/11877
I still can't believe Drupal thinks it's a good idea to force an editor,
who wants to remove one little piece of content, to also remove other
content, sight unseen. This is Drupal's biggest flaw -- it's should be a
content-MANAGEMENT system, not a content-ARBITRARILY-DISCARDING system.
--- /Users/kevin/doc/dl/drupal-4.6.0/modules/comment.module Fri Apr 8 10:00:02 2005
+++ comment.module Thu Apr 14 11:57:37 2005
@@ -557,76 +557,7 @@ function comment_post($edit) {
// Here we are building the thread field. See the comment
// in comment_render().
- if ($edit['pid'] == 0) {
- // This is a comment with no parent comment (depth 0): we start
- // by retrieving the maximum thread level.
- $max = db_result(db_query('SELECT MAX(thread) FROM {comments} WHERE nid = %d', $edit['nid']));
-
- // Strip the "/" from the end of the thread.
- $max = rtrim($max, '/');
-
- // Next, we increase this value by one. Note that we can't
- // use 1, 2, 3, ... 9, 10, 11 because we order by string and
- // 10 would be right after 1. We use 1, 2, 3, ..., 9, 91,
- // 92, 93, ... instead. Ugly but fast.
- $decimals = (string) substr($max, 0, strlen($max) - 1);
- $units = substr($max, -1, 1);
- if ($units) {
- $units++;
- }
- else {
- $units = 1;
- }
-
- if ($units == 10) {
- $units = '90';
- }
-
- // Finally, build the thread field for this new comment.
- $thread = $decimals . $units .'/';
- }
- else {
- // This is comment with a parent comment: we increase
- // the part of the thread value at the proper depth.
-
- // Get the parent comment:
- $parent = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $edit['pid']));
-
- // Strip the "/" from the end of the parent thread.
- $parent->thread = (string) rtrim((string) $parent->thread, '/');
-
- // Get the max value in _this_ thread.
- $max = db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $edit['nid']));
-
- if ($max == '') {
- // First child of this parent.
- $thread = $parent->thread .'.1/';
- }
- else {
- // Strip the "/" at the end of the thread.
- $max = rtrim($max, '/');
-
- // We need to get the value at the correct depth.
- $parts = explode('.', $max);
- $parent_depth = count(explode('.', $parent->thread));
- $last = $parts[$parent_depth];
-
- // Next, we increase this value by one. Note that we can't
- // use 1, 2, 3, ... 9, 10, 11 because we order by string and
- // 10 would be right after 1. We use 1, 2, 3, ..., 9, 91,
- // 92, 93, ... instead. Ugly but fast.
- $decimals = (string)substr($last, 0, strlen($last) - 1);
- $units = substr($last, -1, 1);
- $units++;
- if ($units == 10) {
- $units = '90';
- }
-
- // Finally, build the thread field for this new comment.
- $thread = $parent->thread .'.'. $decimals . $units .'/';
- }
- }
-
+ $thread = comment_thread($edit['nid'], $edit['pid']);
$edit['cid'] = db_next_id('{comments}_cid');
$edit['timestamp'] = time();
@@ -669,6 +600,96 @@ function comment_post($edit) {
}
}
+function comment_thread($nid, $pid) {
+ if ($pid == 0) {
+ /*
+ ** This is a comment with no parent comment (depth 0): we start
+ ** by retrieving the maximum thread level.
+ */
+
+ $max = db_result(db_query('SELECT MAX(thread) FROM {comments} WHERE nid = %d', $nid));
+
+ // Strip the "/" from the end of the thread.
+ $max = rtrim($max, '/');
+ if (($dot = strpos($max, '.')) !== FALSE) {
+ $max = substr($max, 0, $dot);
+ }
+
+ /*
+ ** Next, we increase this value by one. Note that we can't
+ ** use 1, 2, 3, ... 9, 10, 11 because we order by string and
+ ** 10 would be right after 1. We use 1, 2, 3, ..., 9, 91,
+ ** 92, 93, ... instead. Ugly but fast.
+ */
+
+ $decimals = (string)substr($max, 0, strlen($max) - 1);
+ $units = substr($max, -1, 1);
+ if ($units) {
+ $units++;
+ }
+ else {
+ $units = 1;
+ }
+
+ if ($units == 10) {
+ $units = '90';
+ }
+
+ // Finally, build the thread field for this new comment.
+ $thread = "$decimals$units/";
+ }
+ else {
+ /*
+ ** This is comment with a parent comment: we increase
+ ** the part of the thread value at the proper depth.
+ */
+
+ // Get the parent comment:
+ $parent = db_fetch_object(db_query('SELECT * FROM {comments} WHERE cid = %d', $pid));
+
+ // Strip the "/" from the end of the parent thread.
+ $parent->thread = (string)rtrim((string)$parent->thread, '/');
+
+ // Get the max value in _this_ thread.
+ $max = db_result(db_query("SELECT MAX(thread) FROM {comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $nid));
+
+ if ($max == '') {
+ // First child of this parent.
+ $thread = "$parent->thread.1/";
+ }
+ else {
+ // Strip the "/" at the end of the thread.
+ $max = rtrim($max, '/');
+ // We need to get the value at the correct depth.
+ $parts = explode('.', $max);
+ $parent_depth = count(explode('.', $parent->thread));
+ $last = $parts[$parent_depth];
+ // We need to get the value at the correct depth.
+ $parts = explode('.', $max);
+ $parent_depth = count(explode('.', $parent->thread));
+ $last = $parts[$parent_depth];
+
+ /*
+ ** Next, we increase this value by one. Note that we can't
+ ** use 1, 2, 3, ... 9, 10, 11 because we order by string and
+ ** 10 would be right after 1. We use 1, 2, 3, ..., 9, 91,
+ ** 92, 93, ... instead. Ugly but fast.
+ */
+
+ $decimals = (string)substr($last, 0, strlen($last) - 1);
+ $units = substr($last, -1, 1);
+ $units++;
+ if ($units == 10) {
+ $units = '90';
+ }
+
+ // Finally, build the thread field for this new comment.
+ $thread = "$parent->thread.". $decimals.$units .'/';
+ }
+ }
+ return $thread;
+}
+
function comment_links($comment, $return = 1) {
global $user;
@@ -961,10 +982,18 @@ function comment_delete($cid) {
// We'll only delete if the user has confirmed the
// deletion using the form in our else clause below.
if ($comment->cid && $_POST['edit']['confirm']) {
- drupal_set_message(t('The comment and all its replies have been deleted.'));
+ if ($_POST['edit']['thread']) {
+ drupal_set_message(t('The comment and all its replies have been deleted.'));
- // Delete comment and its replies.
- _comment_delete_thread($comment);
+ // Delete comment and its replies.
+ _comment_delete_thread($comment);
+ }
+ else {
+ drupal_set_message(t('The comment has been deleted.'));
+
+ // Delete comment.
+ _comment_delete_single($comment);
+ }
_comment_update_node_statistics($comment->nid);
@@ -975,11 +1004,21 @@ function comment_delete($cid) {
}
else if ($comment->cid) {
+ $children = db_result(db_query('SELECT COUNT(cid) FROM {comments} WHERE pid = %d', $comment->cid));
+ if ($children) {
+ $extra = form_checkbox(t('Delete thread'), 'thread', 1, FALSE,
+ t('If selected, any replies to this comment will be lost.'));
+ }
+ else {
+ $extra = form_hidden('thread', 0);
+ }
$output = theme('confirm',
- t('Are you sure you want to delete the comment %title?', array('%title' => theme('placeholder', $comment->subject))),
+ t('Are you sure you want to delete the comment %title?', array('%title' => ''. $comment->subject .'')),
'node/'. $comment->nid,
- t('Any replies to this comment will be lost. This action cannot be undone.'),
- t('Delete'));
+ NULL,
+ t('Delete'),
+ NULL,
+ $extra);
// Show comment that is being deleted
$comment->comment = check_output($comment->comment, $comment->format);
$output .= theme('comment', $comment);
@@ -1596,6 +1635,42 @@ function theme_comment_post_forbidden()
else {
return t('login to post comments', array('%login' => url('user/login')));
}
+ }
+}
+
+function _comment_delete_single($comment) {
+ $cid = $comment->cid;
+ $pid = $comment->pid;
+ // Delete the comment:
+ db_query('DELETE FROM {comments} WHERE cid = %d', $comment->cid);
+ watchdog('special', t('Comment: deleted %subject.', array('%subject' => "$comment->subject")));
+
+ module_invoke_all('comment', 'delete', $comment);
+
+ // Rethread this comment's descendents
+ $result = db_query('SELECT cid, nid, thread FROM {comments} WHERE pid = %d ORDER BY timestamp', $cid);
+ while ($child = db_fetch_object($result)) {
+ $oldthread = $child->thread;
+ $newthread = comment_thread($child->nid, $pid);
+ db_query("UPDATE {comments} SET thread = '%s', pid = %d WHERE cid = %d", $newthread, $pid, $child->cid);
+ _comment_rethread($child->cid, strlen($oldthread)-1, rtrim($newthread,'/'));
+ }
+}
+
+/**
+ * revise the thread field of descendents of a deleted comment
+ *
+ * @param $cid comment whose descendents are rethreaded
+ * @param $oldlength length of the former thread prefix
+ * @param $newprefix revised thread prefix
+ */
+function _comment_rethread($cid, $oldlength, $newprefix) {
+ $result = db_query('SELECT cid, thread FROM {comments} WHERE pid = %d', $cid);
+ while ($child = db_fetch_object($result)) {
+ $suffix = substr($child->thread, $oldlength);
+ $thread = $newprefix . $suffix;
+ db_query("UPDATE {comments} SET thread = '%s' WHERE cid = %d", $thread, $child->cid);
+ _comment_rethread($child->cid, $oldlength, $newprefix);
}
}