comment.module 61 KB
Newer Older
1
<?php
2
// $Id$
Dries's avatar
 
Dries committed
3

Dries's avatar
   
Dries committed
4
5
$GLOBALS["cmodes"] = array(1 => t("Flat list - collapsed"), 2 => t("Flat list - expanded"), 3 => t("Threaded list - collapsed"), 4 => t("Threaded list - expanded"));
$GLOBALS["corder"] = array(1 => t("Date - newest first"), 2 => t("Date - oldest first"));
Dries's avatar
   
Dries committed
6

Dries's avatar
   
Dries committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function comment_help($section = "admin/comment/help") {
  $output = "";

  switch ($section) {
    case 'admin/help':
    case 'admin/comment/help':
      $output .= "<p>When enabled, the Drupal comment module creates a discussion board for each Drupal node. Users can post comments to discuss a forum topic, weblog post, collaborative book page, etc.</p>";
      $output .= "<h3>User control of comment display</h3>";
      $output .= "<p>Attached to each comment board is a control panel for customizing the way that comments are displayed. Users can control the chronological ordering of posts (newest or oldest first) and the number of posts to display on each page. Additional settings include:</p>";
      $output .= "<ul>";
      $output .= "<li><b>Threaded</b> -- Displays the posts grouped according to conversations and subconversations, much like the subject view of an email client.</li>";
      $output .= "<li><b>Flat</b> --  Displays the posts in chronological order, in the order in which they are posted.</li>";
      $output .= "<li><b>Expanded</b> -- Displays the title and text for each post.</li>";
      $output .= "<li><b>Collapsed</b> -- Displays only the title for each post.</li>";
      $output .= "</ul>";
      $output .= strtr("<p>When a user chooses <i>save settings</i>, the comments are then redisplayed using the user's new choices. Administrators can set the default settings for the comment control panel, along with other comment defaults, in %comment-config.</p>",array("%comment-config" => l(t("site configuration &raquo; modules &raquo; comment"), "admin/system/modules/comment") ));
      $output .= "<p>NOTE: When comment moderation is enabled, users will have another control panel option to control thresholds (see below).</p>";

      $output .= "<h3>Additional comment configurations</h3>";
      $output .= strtr("<p>Comments behave like other user submissions in Drupal. Filters, smileys and HTML that work in nodes will also work with content. To prevent a single user from spamming the web site with too many comments, administrators can set a comment throttle in %site-config under <i>Submission settings</i>.</p>", array("%site-config" => l(t("site configuration"), "admin/system") ));
      $output .= strtr("<p>Administrators can control access to various comment module functions through %user-permissions. Know that in a new Drupal installation, all comment permissions are disabled by default. The choice of which permissions to grant to which roles (groups of users) is left up to the site administrator.</p>", array("%user-permissions" => l(t("user management &raquo; user permissions"), "admin/user/permission") ));
      $output .= "<p>The following permissions can be enabled for anonymous users, authenticated users, or any other user roles that the administrator chooses to define:</p>";
      $output .= "<ul>";
      $output .= "<li><b>Access comments</b> -- Allows users to view comments.</li>";
      $output .= "<li><b>Administrate comments</b> -- Allows users complete control over configuring, editing and deleting all comments on the site. Best reserved for <b>very</b> trusted users.</li>";
      $output .= "<li><b>Moderate comments</b> -- Allows users to rate comment postings (see more on moderation below).</li>";
      $output .= "<li><b>Post comments</b> -- Allows users to post comments into an administrator moderation queue. Administrators then post the comment to the site.</li>";
      $output .= "<li><b>Post comments without approval</b> -- Allows users to directly post comments. This bypasses the administrator moderation queue.</li>";
      $output .= "</ul>";

      $output .= "<h3>Notification of new comments</h3>";
      $output .= "<p>Drupal provides specific features to inform site members when new comments have been posted:</p>";
      $output .= "<ul>";
      $output .= "<li>On the home page, Drupal displays the total number of comments attached to each node, and tracks comments read by individual site members. Members which have logged in will see a notice accompanying nodes which contain comments that they have not read.</li>";
      $output .= strtr("<li>The <i>tracker</i> module, disabled by default, displays all the site's recent posts. When logged in, members will find a %tracker in their user information block with a link to the %tracker-recent page. This page is a useful way to browse new or updated nodes and comments. Content which the user has not yet read is tagged with a red star (this graphic depends on the current theme). Visit the comment board for any node, and Drupal will display a red <i>new</i> label beside the text of unread comments.</li>",array("%tracker" => l(t("view recent posts"), "tracker"), "%tracker-recent" => l(t("Recent activity"), "tracker") ));
Dries's avatar
Dries committed
42
      $output .= strtr("<li>Some administrators may want to %download-notify, install and configure the notify module. Users can then request that Drupal send them an email when new comments are posted (the notify module requires that cron.php be configured properly).</li>", array("%download-notify" => "<a href=\"http://drupal.org/node/view/68\">". t("download") ."</a>" ));
Dries's avatar
   
Dries committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
      $output .= "</ul>";

      $output .= "<h3>Comment moderation</h3>";
      $output .= "<p>On sites with active commenting from users, the administrator can turn over comment moderation to the community. </p>";
      $output .= "<p>With comment moderation, each comment is automatically assigned an initial rating. As users read comments, they can apply a vote which affects the comment rating. At the same time, users have an additional option in the control panel which allows them to set a threshold for the comments they wish to view. Those comments with ratings lower than the set threshold will not be shown.</p>";
      $output .= strtr("<p>To enable moderation, the administrator must grant %permission permissions. Then, a number of options in %comment-moderation must be configured.</p>", array("%permission" => l(t("moderate comments"), "admin/user/permissions"), "%comment-moderation" => l(t("comment management &raquo; comment moderation"), "admin/comment/moderation") ));

      $output .= "<h4>Moderation votes</h4>";
      $output .= strtr("<p>The first step is to create moderation labels which allow users to rate a comment.  Go to %comment-votes. In the <i>vote</i> field, enter the textual labels which users will see when casting their votes. Some examples are</p>", array("%comment-votes" => l(t("comment management &raquo; comment moderation &raquo; votes"), "admin/comment/moderation/votes") ));
      $output .= "<ul>";
      $output .= "<li>Excellent +3</li>";
      $output .= "<li>Insightful +2</li>";
      $output .= "<li>Caught My Attention +1</li>";
      $output .= "<li>Useful +1</li>";
      $output .= "<li>Redundant -1</li>";
      $output .= "<li>Flame -3</li>";
      $output .= "</ul>";
      $output .= "<p>So that users know how their votes affect the comment, these examples include the vote value as part of the label, although that is optional.</p>";
      $output .= "<p>Using the weight option, you can control the order in which the votes appear to users. Setting the weight heavier (positive numbers) will make the vote label appear at the bottom of the list. Lighter (a negative number) will push it to the top. To encourage positive voting, a useful order might be higher values, positive votes, at the top, with negative votes at the bottom.</p>";

Dries's avatar
   
Dries committed
63
      $output .= "<h4>Moderator vote/values matrix</h4>";
Dries's avatar
   
Dries committed
64
65
66
67

      $output .= strtr("<p>Next go to %comment-matrix.  Enter the values for the vote labels for each permission role in the vote matrix. The values entered here will be used to create the rating for each comment.</p>", array("%comment-matrix" => l(t("comment management &raquo; comment moderation &raquo; matrix"), "admin/comment/moderation/,atrix") ));
      $output .= "<p>NOTE: Comment ratings are calculated by averaging user votes with the initial rating.</p>";
      $output .= "<h4>Creating comment thresholds</h4>
Dries's avatar
   
Dries committed
68
69
70
71
72
<p>In <i>comment management &raquo; comment moderation &raquo; thresholds</i>, you'll have to create some comment thresholds to make the comment rating system useful. When comment moderation is enabled and the thresholds are created, users will find another comment control panel option for selecting thresholds. They'll use the thresholds you enter here to filter out comments with low ratings. Consequently, you'll probably want to create more than one threshold to give users some flexibility in filtering comments.</p>
<p>When creating the thresholds, note that the <i>Minimum score</i> is asking you for the lowest rating that a comment can have in order to be displayed.</p>
<p>To see a common example of how thresholds work, you might visit <a href=\"http://slashdot.org/\">Slashdot</a> and view one of their comment boards associated with a story. You can reset the thresholds in their comment control panel.</p>

<h4>Initial comment scores</h4>
Dries's avatar
   
Dries committed
73
74
75
76
<p>Finally, you may want to enter some <i>initial comment scores</i>. In <i>comment management &raquo; initial comment scores </i>you can assign a beginning rating for all comments posted by a particular permission role. If you do not assign any initial scores, Drupal will assign a rating of <b>0</b> as the default.</p>";
    break;
  }
  return t($output);
Dries's avatar
   
Dries committed
77
78
}

Dries's avatar
   
Dries committed
79
function comment_system($field) {
Kjartan's avatar
Kjartan committed
80
  $system["description"] = t("Enables user to comment on content (nodes).");
Dries's avatar
   
Dries committed
81
  $system["admin_help"] = t("Comments can be attached to any node. Below are the settings for comments. The display comes in two types, a \"flat list\" where everything is flush to the left side, and comments come in cronological order, and a \"threaded list\" where comments to other comments are placed immediately below the orignal, and slightly indented forming an outline of comments. They also come in two styles: \"expanded\", where you get to see both the title and the contents, and \"collapsed\" where you only see the titles. To set the default threshold you first have to set up thresholds in the <a href=\"%threshold\">comment management &gt;&gt; comment moderation &gt;&gt; thresholds</a> area. Preview comment forces a user to click on a \"Preview\" button so they can see what their comment will look like before they can actually add the comment to the system. If \"New comment form\" is enabled then at the bottom of every comment page there will be a form too add a new comment.", array("%threshold" => url("admin/comment/moderation/filters")));
82
83
84
  return $system[$field];
}

85
function comment_settings() {
Dries's avatar
   
Dries committed
86
  global $cmodes, $corder;
Dries's avatar
   
Dries committed
87

Dries's avatar
   
Dries committed
88
89
90
  $output .= form_select(t("Default display mode"), "comment_default_mode", variable_get("comment_default_mode", 4), $cmodes, t("The default view for comments. Expanded views display the body of the comment. Threaded views keep replies together."));
  $output .= form_select(t("Default display order"), "comment_default_order", variable_get("comment_default_order", 1), $corder, t("The default sorting for new users and anonymous users while viewing comments. These users may change their view using the comment control panel. For registered users, this change is remembered as a persistent user preference."));
  $output .= form_textfield(t("Default comments per page"), "comment_default_per_page", variable_get("comment_default_per_page", "50"), 5, 5, t("Default number of comments for each page; more comments are distributed in several pages."));
Dries's avatar
   
Dries committed
91

Dries's avatar
   
Dries committed
92
  $result = db_query("SELECT fid, filter FROM {moderation_filters} ");
Dries's avatar
   
Dries committed
93
94
  while ($filter = db_fetch_object($result)) {
    $thresholds[$filter->fid] = ($filter->filter);
Dries's avatar
   
Dries committed
95
96
  }

Dries's avatar
   
Dries committed
97
  $output .= form_select(t("Default threshold"), "comment_default_threshold", variable_get("comment_default_threshold", 0), $thresholds, t("Thresholds are values below which comments are hidden. These thresholds are useful for busy sites which want to hide poor comments from most users."));
Dries's avatar
   
Dries committed
98

Dries's avatar
   
Dries committed
99
100
101
  $output .= form_select(t("Preview comment"), "comment_preview", variable_get("comment_preview", 1), array(t("Optional"), t("Required")), t("Must users preview comments before submitting?"));
  $output .= form_select(t("New comment form"), "comment_new_form", variable_get("comment_new_form", 0), array(t("Disabled"), t("Enabled")), t("New comment form in the node page?"));
  $output .= form_select(t("Comment controls"), "comment_controls", variable_get("comment_controls", 0), array(t("Above comments"), t("Below comments"), t("Above and below")), t("Position of the comment controls box."));
Dries's avatar
   
Dries committed
102

Dries's avatar
   
Dries committed
103
  return $output;
Dries's avatar
   
Dries committed
104
105
}

Dries's avatar
   
Dries committed
106
107
108
function comment_user($type, $edit, &$user) {
  switch ($type) {
    case "view_public":
Dries's avatar
   
Dries committed
109
      if ($user->signature) {
Dries's avatar
   
Dries committed
110
        return form_item(t("Signature"), check_output($user->signature));
Dries's avatar
   
Dries committed
111
112
      }
      break;
Dries's avatar
   
Dries committed
113
    case "view_private":
Dries's avatar
   
Dries committed
114
      if ($user->signature) {
Dries's avatar
   
Dries committed
115
        return form_item(t("Signature"), check_output($user->signature));
Dries's avatar
   
Dries committed
116
117
      }
      break;
Dries's avatar
   
Dries committed
118
119
    case "edit_form":
      // when user tries to edit his own data
Dries's avatar
   
Dries committed
120
      return form_textarea(t("Signature"), "signature", $edit["signature"], 70, 3, t("Your signature will be publicly displayed at the end of your comments.") ."<br />". form_allowed_tags_text());
Dries's avatar
   
Dries committed
121
122
    case "edit_validate":
      // validate user data editing
Dries's avatar
   
Dries committed
123
      return array("signature" => $edit["signature"]);
Dries's avatar
   
Dries committed
124
125
126
  }
}

Dries's avatar
   
Dries committed
127
function comment_access($op, $comment) {
Dries's avatar
   
Dries committed
128
129
  global $user;

Dries's avatar
   
Dries committed
130
131
132
133
134
135
136
137
138
139
140
  if ($op == "edit") {

    /*
    ** Authenticated users can edit their comments as long they have
    ** not been replied to.  This, in order to avoid people changing
    ** or revising their statements based on the replies their posts
    ** got. Furthermore, users can't reply to their own comments and
    ** are encouraged to extend their original comment.
    */

    return $user->uid && $user->uid == $comment->uid && comment_num_replies($comment->cid) == 0;
Dries's avatar
   
Dries committed
141
  }
Dries's avatar
   
Dries committed
142

Dries's avatar
   
Dries committed
143
144
145
146
147
}

function comment_form($edit) {
  global $user;

Dries's avatar
   
Dries committed
148
  $form .= "<a id=\"comment\"></a>\n";
Dries's avatar
   
Dries committed
149
150
151
152
153

  // name field:
  $form .= form_item(t("Your name"), format_name($user));

  // subject field:
Dries's avatar
   
Dries committed
154
  $form .= form_textfield(t("Subject"), "subject", $edit["subject"], 50, 64);
Dries's avatar
   
Dries committed
155
156

  // comment field:
Dries's avatar
   
Dries committed
157
  $form .= form_textarea(t("Comment"), "comment", $edit["comment"] ? $edit["comment"] : $user->signature, 70, 10, form_allowed_tags_text());
Dries's avatar
   
Dries committed
158
159

  // preview button:
Dries's avatar
   
Dries committed
160
  $form .= form_hidden("cid", $edit["cid"]);
Dries's avatar
   
Dries committed
161
  $form .= form_hidden("pid", $edit["pid"]);
Dries's avatar
   
Dries committed
162
  $form .= form_hidden("nid", $edit["nid"]);
Dries's avatar
   
Dries committed
163

Dries's avatar
   
Dries committed
164
  if (!$edit["comment"] && variable_get("comment_preview", 1)) {
Dries's avatar
   
Dries committed
165
166
167
168
169
170
171
    $form .= form_submit(t("Preview comment"));
  }
  else {
    $form .= form_submit(t("Preview comment"));
    $form .= form_submit(t("Post comment"));
  }

Dries's avatar
   
Dries committed
172
  return form($form, "post", url("comment/reply/". $edit["nid"]));
Dries's avatar
   
Dries committed
173
174
}

Dries's avatar
   
Dries committed
175
176
177
function comment_edit($cid) {
  global $user;

Dries's avatar
   
Dries committed
178
  $comment = db_fetch_object(db_query("SELECT c.*, u.uid, u.name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status != 2", $cid));
Dries's avatar
   
Dries committed
179
180
181
182
183
184
185

  if (comment_access("edit", $comment)) {
    comment_preview(object2array($comment));
  }
}

function comment_reply($pid, $nid) {
Dries's avatar
   
Dries committed
186

Dries's avatar
   
Dries committed
187

188
  if (user_access("access comments")) {
Dries's avatar
   
Dries committed
189
190
191
192
193

    /*
    ** Show comment
    */

Dries's avatar
   
Dries committed
194
    if ($pid) {
Dries's avatar
   
Dries committed
195
      $comment = db_fetch_object(db_query("SELECT c.*, u.uid, u.name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = 0", $pid));
Dries's avatar
   
Dries committed
196
      comment_view($comment);
Dries's avatar
   
Dries committed
197
    }
Dries's avatar
   
Dries committed
198
    else if (user_access("access content")) {
Dries's avatar
   
Dries committed
199
200
201
      node_view(node_load(array("nid" => $nid)));
      $pid = 0;
    }
Dries's avatar
   
Dries committed
202

Dries's avatar
   
Dries committed
203
204
205
206
    /*
    ** If possible, show reply form
    */

Dries's avatar
   
Dries committed
207
    if (node_comment_mode($nid) != 2) {
Dries's avatar
   
Dries committed
208
      theme("box", t("Reply"), t("This discussion is closed: you can't post new comments."));
Kjartan's avatar
Kjartan committed
209
    }
Dries's avatar
   
Dries committed
210
    else if (user_access("post comments")) {
Dries's avatar
   
Dries committed
211
      theme("box", t("Reply"), comment_form(array("pid" => $pid, "nid" => $nid)));
Dries's avatar
   
Dries committed
212
213
    }
    else {
Dries's avatar
   
Dries committed
214
      theme("box", t("Reply"), t("You are not authorized to post comments."));
Dries's avatar
   
Dries committed
215
    }
Kjartan's avatar
Kjartan committed
216
217
  }
  else {
Dries's avatar
   
Dries committed
218
    theme("box", t("Reply"), t("You are not authorized to view comments."));
Dries's avatar
   
Dries committed
219
220
221
222
  }
}

function comment_preview($edit) {
Dries's avatar
   
Dries committed
223
  global $user;
Dries's avatar
   
Dries committed
224

Dries's avatar
   
Dries committed
225
226
227
228
  foreach ($edit as $key => $value) {
    $comment->$key = $value;
  }

Dries's avatar
   
Dries committed
229
  /*
Dries's avatar
   
Dries committed
230
  ** Attach the user and time information:
Dries's avatar
   
Dries committed
231
232
233
234
235
236
237
238
239
240
  */

  $comment->uid = $user->uid;
  $comment->name = $user->name;
  $comment->timestamp = time();

  /*
  ** Preview the comment:
  */

Dries's avatar
   
Dries committed
241
  comment_view($comment, t("reply to this comment"));
Dries's avatar
   
Dries committed
242

Dries's avatar
   
Dries committed
243
  theme("box", t("Reply"), comment_form($edit));
Kjartan's avatar
Kjartan committed
244
245

  if ($edit["pid"]) {
Dries's avatar
   
Dries committed
246
    $comment = db_fetch_object(db_query("SELECT c.*, u.uid, u.name, u.data FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = 0", $edit["pid"]));
Dries's avatar
   
Dries committed
247
    comment_view($comment);
Kjartan's avatar
Kjartan committed
248
249
250
251
252
  }
  else {
    node_view(node_load(array("nid" => $edit["nid"])));
    $edit["pid"] = 0;
  }
Dries's avatar
   
Dries committed
253
254
255
}

function comment_post($edit) {
Dries's avatar
   
Dries committed
256
  global $user;
Dries's avatar
   
Dries committed
257

Dries's avatar
   
Dries committed
258
  if (user_access("post comments") && node_comment_mode($edit["nid"]) == 2) {
Dries's avatar
   
Dries committed
259

Dries's avatar
   
Dries committed
260
261
262
263
264
    /*
    ** Validate the comment's subject.  If not specified, extract
    ** one from the comment's body.
    */

Dries's avatar
   
Dries committed
265
    $edit["subject"] = strip_tags($edit["subject"]);
Dries's avatar
   
Dries committed
266

Dries's avatar
   
Dries committed
267
268
269
    if ($edit["subject"] == "") {
      $edit["subject"] = substr(strip_tags($edit["comment"]), 0, 29);
    }
Dries's avatar
   
Dries committed
270
271
272
273
274

    /*
    ** Validate the comment's body.
    */

Dries's avatar
   
Dries committed
275
276
277
278
    if ($edit["comment"] == "") {
      return array(t("Empty comment"), t("The comment you submitted is empty."));
    }

Dries's avatar
   
Dries committed
279
280
281
282
283
    /*
    ** Check for duplicate comments.  Note that we have to use the
    ** validated/filtered data to perform such check.
    */

Dries's avatar
   
Dries committed
284
    $duplicate = db_result(db_query("SELECT COUNT(cid) FROM {comments} WHERE pid = %d AND nid = %d AND subject = '%s' AND comment = '%s'", $edit["pid"], $edit["nid"], $edit["subject"], $edit["comment"]), 0);
Dries's avatar
   
Dries committed
285
286

    if ($duplicate != 0) {
Dries's avatar
   
Dries committed
287
      watchdog("warning", "comment: duplicate '". $edit["subject"] ."'");
Dries's avatar
   
Dries committed
288
      return array(t("Duplicate comment"), t("The comment you submitted has already been inserted."));
Dries's avatar
   
Dries committed
289
290
291
    }
    else {

Dries's avatar
   
Dries committed
292
      if ($edit["cid"]) {
Dries's avatar
   
Dries committed
293

Dries's avatar
   
Dries committed
294
295
296
297
298
299
        /*
        ** Update the comment in the database.  Note that the update
        ** query will fail if the comment isn't owned by the current
        ** user.
        */

Dries's avatar
   
Dries committed
300
        db_query("UPDATE {comments} SET subject = '%s', comment = '%s' WHERE cid = %d AND uid = '$user->uid'", $edit["subject"], $edit["comment"], $edit["cid"]);
Dries's avatar
   
Dries committed
301
302
303
304
305
306

        /*
        ** Fire a hook
        */

        module_invoke_all("comment", "update", $edit);
Dries's avatar
   
Dries committed
307
308
309
310
311

        /*
        ** Add entry to the watchdog log:
        */

Dries's avatar
   
Dries committed
312
        watchdog("special", "comment: updated '". $edit["subject"] ."'", l(t("view comment"), "node/view/". $edit["nid"] ."#". $edit["cid"]));
Dries's avatar
   
Dries committed
313
314
315
316
317
318
319
320
321
322
323
324
325
      }
      else {
        /*
        ** Check the user's comment submission rate.  If exceeded,
        ** throttle() will bail out.
        */

        throttle("post comment", variable_get("max_comment_rate", 60));

        /*
        ** Add the comment to database:
        */

Dries's avatar
   
Dries committed
326
327
328
329
330
        $status = user_access("post comments without approval") ? 0 : 1;
        $roles = variable_get("comment_roles", array());
        $score = $roles[$user->rid] ? $roles[$user->rid] : 0;
        $users = serialize(array(0 => $score));

Dries's avatar
   
Dries committed
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
        /*
        ** 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."/";
          }
        }


Dries's avatar
   
Dries committed
418
        $edit["cid"] = db_next_id("comments_cid");
Dries's avatar
   
Dries committed
419

Dries's avatar
   
Dries committed
420
        db_query("INSERT INTO {comments} (cid, nid, pid, uid, subject, comment, hostname, timestamp, status, score, users, thread) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', %d, %d, %d, '%s', '%s')", $edit["cid"], $edit["nid"], $edit["pid"], $user->uid, $edit["subject"], $edit["comment"], getenv("REMOTE_ADDR"), time(), $status, $score, $users, $thread);
Dries's avatar
   
Dries committed
421
422
423
424
425
426

        /*
        ** Tell the other modules a new comment has been submitted:
        */

        module_invoke_all("comment", "insert", $edit);
Dries's avatar
   
Dries committed
427
428
429
430

        /*
        ** Add entry to the watchdog log:
        */
Dries's avatar
   
Dries committed
431

Dries's avatar
   
Dries committed
432
        watchdog("special", "comment: added '". $edit["subject"] ."'", l(t("view comment"), "node/view/". $edit["nid"] ."#". $edit["cid"]));
Dries's avatar
   
Dries committed
433
      }
Dries's avatar
   
Dries committed
434
435

      /*
Dries's avatar
   
Dries committed
436
437
      ** Clear the cache so an anonymous user can see his comment being
      ** added.
Dries's avatar
   
Dries committed
438
      */
Dries's avatar
   
Dries committed
439

Dries's avatar
   
Dries committed
440
      cache_clear_all();
Dries's avatar
   
Dries committed
441
442
    }
  }
Dries's avatar
   
Dries committed
443
444
445
446
  else {
    watchdog("error", "comment: unauthorized comment submitted or comment submitted to a closed node '". $edit["subject"] ."'");
    return array(t("Error"), t("You are not authorized to post comments, or this node doesn't accept new comments."));
  }
Dries's avatar
   
Dries committed
447
448

  /*
Dries's avatar
   
Dries committed
449
  ** Redirect the user the node he commented on, or explain queue
Dries's avatar
   
Dries committed
450
451
  */

Dries's avatar
   
Dries committed
452
453
  if ($status == 1) {
    return array(t("Comment queued"), t("Your comment has been queued for moderation by site administrators and will be published after approval."));
Dries's avatar
   
Dries committed
454
455
456
457
  }
}

function comment_links($comment, $return = 1) {
Dries's avatar
   
Dries committed
458
  global $user;
Dries's avatar
   
Dries committed
459

Dries's avatar
   
Dries committed
460
  $links = array();
Dries's avatar
   
Dries committed
461

Dries's avatar
   
Dries committed
462
463
464
465
  /*
  ** If we are viewing just this comment, we link back to the node
  */

Dries's avatar
   
Dries committed
466
  if ($return) {
Dries's avatar
   
Dries committed
467
    $links[] = l(t("parent"), "node/view/$comment->nid#$comment->cid");
Dries's avatar
   
Dries committed
468
  }
Dries's avatar
   
Dries committed
469

Dries's avatar
   
Dries committed
470
471
472
473
  /*
  ** Admin link
  */

Dries's avatar
   
Dries committed
474
  if (user_access("administer comments") && user_access("access administration pages")) {
Dries's avatar
   
Dries committed
475
    $links[] = l(t("administer"), "admin/comment/edit/$comment->cid");
Dries's avatar
   
Dries committed
476
477
  }

Dries's avatar
   
Dries committed
478
  /*
Dries's avatar
   
Dries committed
479
  ** Possibly show edit and reply links
Dries's avatar
   
Dries committed
480
  */
Dries's avatar
   
Dries committed
481

Dries's avatar
   
Dries committed
482
483
484
  if (node_comment_mode($comment->nid) == 2) {
    if (user_access("post comments")) {
      if (comment_access("edit", $comment)) {
Dries's avatar
   
Dries committed
485
        $links[] = l(t("edit your comment"), "comment/edit/$comment->cid", array("title" => t("Make changes to your comment.")));
Dries's avatar
   
Dries committed
486
      }
Dries's avatar
   
Dries committed
487
      $links[] = l(t("reply to this comment"), "comment/reply/$comment->nid/$comment->cid");
Dries's avatar
   
Dries committed
488
489
    }
    else {
490
      $links[] = theme("comment_post_forbidden");
Dries's avatar
   
Dries committed
491
    }
Dries's avatar
   
Dries committed
492
  }
Dries's avatar
   
Dries committed
493
494
495
496

  if ($moderation = comment_moderation_form($comment)) {
    $links[] = $moderation;
  }
Dries's avatar
   
Dries committed
497

Dries's avatar
   
Dries committed
498
  return theme("links", $links);
Dries's avatar
   
Dries committed
499
500
}

Dries's avatar
   
Dries committed
501
502
503
504
505
function comment_view($comment, $links = "", $visible = 1) {

  /*
  ** Switch to folded/unfolded view of the comment
  */
Dries's avatar
   
Dries committed
506

Dries's avatar
   
Dries committed
507
  if (node_is_new($comment->nid, $comment->timestamp)) {
Dries's avatar
   
Dries committed
508
    $comment->new = 1;
Dries's avatar
   
Dries committed
509
    print "<a id=\"new\"></a>\n";
Dries's avatar
   
Dries committed
510
  }
Dries's avatar
   
Dries committed
511

Dries's avatar
   
Dries committed
512
  print "<a id=\"$comment->cid\"></a>\n";
Dries's avatar
   
Dries committed
513
514

  if ($visible) {
Dries's avatar
   
Dries committed
515
    $comment->comment = check_output($comment->comment);
516
    theme("comment", $comment, $links);
Dries's avatar
   
Dries committed
517
518
  }
  else {
519
    theme("comment_folded", $comment);
Dries's avatar
   
Dries committed
520
521
522
  }
}

Dries's avatar
   
Dries committed
523
function comment_render($node, $cid = 0) {
Dries's avatar
   
Dries committed
524
525
526
527
528
529
530
  global $user;

  $mode = $_GET["mode"];
  $order = $_GET["order"];
  $threshold = $_GET["threshold"];
  $comments_per_page = $_GET["comments_per_page"];
  $comment_page = $_GET["comment_page"];
Dries's avatar
   
Dries committed
531
532
533
534
535
536
537

  if (user_access("access comments")) {

    /*
    ** Pre-process variables:
    */

Dries's avatar
   
Dries committed
538
    $nid = $node->nid;
Dries's avatar
   
Dries committed
539
540
    if (empty($nid)) {
      $nid = 0;
Dries's avatar
   
Dries committed
541
542
543
    }

    if (empty($mode)) {
Dries's avatar
   
Dries committed
544
      $mode = $user->mode ? $user->mode : variable_get("comment_default_mode", 4);
Dries's avatar
   
Dries committed
545
546
547
    }

    if (empty($order)) {
Dries's avatar
   
Dries committed
548
      $order = $user->sort ? $user->sort : variable_get("comment_default_order", 1);
Dries's avatar
   
Dries committed
549
550
551
    }

    if (empty($threshold)) {
Dries's avatar
   
Dries committed
552
      $threshold = $user->uid ? $user->threshold : variable_get("comment_default_threshold", 0);
Dries's avatar
   
Dries committed
553
    }
Dries's avatar
   
Dries committed
554
    $threshold_min = db_result(db_query("SELECT minimum FROM {moderation_filters} WHERE fid = %d", $threshold));
Dries's avatar
   
Dries committed
555

Dries's avatar
   
Dries committed
556
557
558
    if (empty($comments_per_page)) {
      $comments_per_page = $user->comments_per_page ? $user->comments_per_page : variable_get("comment_default_per_page", "50");
    }
Dries's avatar
   
Dries committed
559

Dries's avatar
   
Dries committed
560
    print "<a id=\"comment\"></a>\n";
Dries's avatar
   
Dries committed
561
562


Kjartan's avatar
Kjartan committed
563
    if ($cid) {
Dries's avatar
   
Dries committed
564
565
566
567
568

      /*
      ** Single comment view
      */

Dries's avatar
   
Dries committed
569
      print "<form method=\"post\" action=\"". url("comment") ."\"><div>\n";
Dries's avatar
   
Dries committed
570
571
      print form_hidden("nid", $nid);

Dries's avatar
   
Dries committed
572
      $result = db_query("SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.users FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status = 0 GROUP BY c.cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.users", $cid);
Dries's avatar
   
Dries committed
573

Dries's avatar
   
Dries committed
574
575
576
      if ($comment = db_fetch_object($result)) {
        comment_view($comment, comment_links($comment));
      }
Dries's avatar
   
Dries committed
577

Dries's avatar
   
Dries committed
578
      if ((comment_user_can_moderate($node)) && $user->uid != $comment->uid && !(comment_already_moderated($user->uid, $comment->users))) {
Dries's avatar
   
Dries committed
579
        print "<div style=\"text-align: center;\">". form_submit(t("Moderate comment")) ."</div><br />";
Dries's avatar
   
Dries committed
580
      }
Dries's avatar
   
Dries committed
581
      print "</div></form>";
Dries's avatar
   
Dries committed
582
    }
Dries's avatar
   
Dries committed
583
    else {
Dries's avatar
   
Dries committed
584

Dries's avatar
   
Dries committed
585
586
587
588
      /*
      ** Multiple comments view
      */

Dries's avatar
   
Dries committed
589
      $query .= "SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.users, c.thread FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = '". check_query($nid) ."' AND c.status = 0";
Dries's avatar
   
Dries committed
590
591

      $query .= " GROUP BY c.cid, c.pid, c.nid, c.subject, c.comment, c.timestamp, u.uid, u.name, u.data, c.score, c.users, c.thread";
Dries's avatar
   
Dries committed
592

Dries's avatar
   
Dries committed
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
      /*
      ** We want to use the standard pager, but threads would need every
      ** comment to build the thread structure, so we need to store some
      ** extra info.
      **
      ** We use a "thread" field to store this extra info. The basic idea
      ** is to store a value and to order by that value. The "thread" field
      ** keeps this data in a way which is easy to update and convenient
      ** to use.
      **
      ** A "thread" value starts at "1". If we add a child (A) to this
      ** comment, we assign it a "thread" = "1.1". A child of (A) will have
      ** "1.1.1". Next brother of (A) will get "1.2". Next brother of the
      ** parent of (A) will get "2" and so on.
      **
      ** First of all note that the thread field stores the depth of the
      ** comment: depth 0 will be "X", depth 1 "X.X", depth 2 "X.X.X", etc.
      **
      ** Now to get the ordering right, consider this example:
      **
      ** 1
      ** 1.1
      ** 1.1.1
      ** 1.2
      ** 2
      **
      ** If we "ORDER BY thread ASC" we get the above result, and this is
      ** the natural order sorted by time.  However, if we "ORDER BY thread
      ** DESC" we get:
      **
      ** 2
      ** 1.2
      ** 1.1.1
      ** 1.1
      ** 1
      **
      ** Clearly, this is not a natural way to see a thread, and users
      ** will get confused. The natural order to show a thread by time
      ** desc would be:
      **
      ** 2
      ** 1
      ** 1.2
      ** 1.1
      ** 1.1.1
      **
      ** which is what we already did before the standard pager patch. To
      ** achieve this we simply add a "/" at the end of each "thread" value.
      ** This way out thread fields will look like depicted below:
      **
      ** 1/
      ** 1.1/
      ** 1.1.1/
      ** 1.2/
      ** 2/
      **
      ** we add "/" since this char is, in ASCII, higher than every number,
      ** so if now we "ORDER BY thread DESC" we get the correct order.  Try
      ** it, it works ;).  However this would spoil the "ORDER BY thread ASC"
      ** Here, we do not need to consider the trailing "/" so we use a
      ** substring only.
      */
Dries's avatar
   
Dries committed
655
656

      if ($order == 1) {
Dries's avatar
   
Dries committed
657
658
659
660
661
662
        if ($mode == 1 || $mode == 2) {
          $query .= " ORDER BY c.timestamp DESC";
        }
        else {
          $query .= " ORDER BY c.thread DESC";
        }
Dries's avatar
   
Dries committed
663
      }
Dries's avatar
   
Dries committed
664
      else if ($order == 2) {
Dries's avatar
   
Dries committed
665
666
667
668
669
670
671
672
673
674
675
676
677
        if ($mode == 1 || $mode == 2) {
          $query .= " ORDER BY c.timestamp";
        }
        else {

          /*
          ** See comment above.  Analysis learns that this doesn't cost
          ** too much.  It scales much much better than having the whole
          ** comment structure.
          */

          $query .= " ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))";
        }
Dries's avatar
   
Dries committed
678
679
680
      }

      /*
Dries's avatar
   
Dries committed
681
      ** Start a form, to use with comment control and moderation.
Dries's avatar
   
Dries committed
682
683
      */

Dries's avatar
   
Dries committed
684
      $result = pager_query($query, $comments_per_page, 0, "SELECT COUNT(*) FROM {comments} WHERE nid = '".check_query($nid)."'");
Dries's avatar
   
Dries committed
685

Dries's avatar
   
Dries committed
686
      if ((variable_get("comment_controls", 0) == 0) || (variable_get("comment_controls", 0) == 2)) {
Dries's avatar
   
Dries committed
687
        print "<form method=\"post\" action=\"". url("comment") ."\"><div>\n";
Dries's avatar
   
Dries committed
688
        theme("comment_controls", $threshold, $mode, $order, $comments_per_page);
Dries's avatar
   
Dries committed
689
        print form_hidden("nid", $nid);
Dries's avatar
   
Dries committed
690
        print "</div></form>";
Dries's avatar
   
Dries committed
691
      }
Dries's avatar
   
Dries committed
692

Dries's avatar
   
Dries committed
693
      print "<form method=\"post\" action=\"". url("comment") ."\"><div>\n";
Dries's avatar
   
Dries committed
694
695
      print form_hidden("nid", $nid);

Dries's avatar
   
Dries committed
696
697
      while ($comment = db_fetch_object($result)) {
        $comment->depth = count(explode(".", $comment->thread)) - 1;
Dries's avatar
   
Dries committed
698

Dries's avatar
   
Dries committed
699
700
        if ($mode == 1) {
          theme("comment_flat_collapsed", $comment, $threshold_min);
Dries's avatar
   
Dries committed
701
        }
Dries's avatar
   
Dries committed
702
        else if ($mode == 2) {
Dries's avatar
   
Dries committed
703
          theme("comment_flat_expanded", $comment, $threshold_min);
Dries's avatar
   
Dries committed
704
        }
Dries's avatar
   
Dries committed
705
        else if ($mode == 3) {
Dries's avatar
   
Dries committed
706
          theme("comment_thread_min", $comment, $threshold_min);
Dries's avatar
   
Dries committed
707
        }
Dries's avatar
   
Dries committed
708
709
710
711
        else if ($mode == 4) {
          theme("comment_thread_max", $comment, $threshold_min);
        }
      }
Dries's avatar
   
Dries committed
712

Dries's avatar
   
Dries committed
713
714
715
716
717
718
719
      /*
      ** Use the standard pager, $pager_total is the number of returned rows,
      ** is global and defined in pager.inc
      */
      if ($pager = pager_display(NULL, $comments_per_page, 0, "default", array("comments_per_page" => $comments_per_page))) {
        print $pager;
      }
Dries's avatar
   
Dries committed
720

Dries's avatar
   
Dries committed
721
722
      if (comment_user_can_moderate($node)) {
        print "<div align=\"center\">". form_submit(t("Moderate comments")) ."</div><br />";
Dries's avatar
   
Dries committed
723
      }
Dries's avatar
   
Dries committed
724

Dries's avatar
   
Dries committed
725
      print "</div></form>";
Dries's avatar
   
Dries committed
726

Dries's avatar
   
Dries committed
727
      if ((variable_get("comment_controls", 0) == 1) || (variable_get("comment_controls", 0) == 2)) {
Dries's avatar
   
Dries committed
728
        print "<form method=\"post\" action=\"". url("comment") ."\"><div>\n";
Dries's avatar
   
Dries committed
729
        theme("comment_controls", $threshold, $mode, $order, $comments_per_page);
Dries's avatar
   
Dries committed
730
        print form_hidden("nid", $nid);
Dries's avatar
   
Dries committed
731
        print "</div></form>";
Dries's avatar
   
Dries committed
732
      }
Dries's avatar
   
Dries committed
733
734
    }

Dries's avatar
   
Dries committed
735
736
737
738
739
    /*
    ** If enabled, show new comment form
    */

    if (user_access("post comments") && node_comment_mode($nid) == 2 && variable_get("comment_new_form", 0)) {
Dries's avatar
   
Dries committed
740
      theme("box", t("Post new comment"), comment_form(array("nid" => $nid)));
Dries's avatar
   
Dries committed
741
    }
Dries's avatar
   
Dries committed
742
743
744
745

  }
}

Dries's avatar
   
Dries committed
746
747
748
function comment_perm() {
  return array("access comments", "post comments", "administer comments", "moderate comments", "post comments without approval", "administer moderation");
}
Dries's avatar
   
Dries committed
749

Dries's avatar
   
Dries committed
750
function comment_link($type, $node = 0, $main = 0) {
Dries's avatar
   
Dries committed
751

Dries's avatar
   
Dries committed
752
  if ($type == "node" && $node->comment) {
Dries's avatar
   
Dries committed
753
754
755
756
757
758
759
760

    if ($main) {

      /*
      ** Main page: display the number of comments that have been posted.
      */

      if (user_access("access comments")) {
Dries's avatar
   
Dries committed
761
        $all = comment_num_all($node->nid);
Dries's avatar
   
Dries committed
762
        $new = comment_num_new($node->nid);
Dries's avatar
   
Dries committed
763

Dries's avatar
   
Dries committed
764
        if ($all) {
Dries's avatar
   
Dries committed
765
          $links[] = l(format_plural($all, "1 comment", "%count comments"), "node/view/$node->nid#comment", array("title" => t("Jump to the first comment of this posting.")));
Dries's avatar
   
Dries committed
766

Dries's avatar
   
Dries committed
767
          if ($new) {
Dries's avatar
   
Dries committed
768
            $links[] = l(format_plural($new, "1 new comment", "%count new comments"), "node/view/$node->nid#new", array("title" => t("Jump to the first new comment of this posting.")));
Dries's avatar
   
Dries committed
769
770
771
          }
        }
        else {
Dries's avatar
   
Dries committed
772
773
774
775
776
777
778
          if ($node->comment == 2) {
            if (user_access("post comments")) {
              $links[] = l(t("add new comment"), "comment/reply/$node->nid", array("title" => t("Add a new comment to this page.")));
            }
            else {
              $links[] = theme("comment_post_forbidden");
            }
Dries's avatar
   
Dries committed
779
780
          }
        }
Dries's avatar
   
Dries committed
781
782
783
784
785
      }
    }
    else {
      /*
      ** Node page: add a "post comment" link if the user is allowed to
Dries's avatar
   
Dries committed
786
      ** post comments and if this node is not read-only
Dries's avatar
   
Dries committed
787
788
      */

Dries's avatar
   
Dries committed
789
790
      if ($node->comment == 2) {
        if (user_access("post comments")) {
Dries's avatar
   
Dries committed
791
          $links[] = l(t("add new comment"), "comment/reply/$node->nid#comment", array("title" => t("Share your thoughts and opinions related to this posting.")));
Kjartan's avatar
Kjartan committed
792
793
        }
        else {
794
          $links[] = theme("comment_post_forbidden");
Dries's avatar
   
Dries committed
795
        }
Dries's avatar
   
Dries committed
796
797
798
799
      }
    }
  }

Dries's avatar
   
Dries committed
800
  if ($type == "admin" && user_access("administer comments")) {
Dries's avatar
   
Dries committed
801
802
803
804
805
806

    menu("admin/comment", "comment management", "comment_admin", comment_help("admin/comment"), 2);
    menu("admin/comment/comments", "comment overview",NULL, comment_help("admin/comment/comments"), 2);
    menu("admin/comment/comments/0", "new or updated comments", "comment_admin", comment_help("admin/comment/comments/0"), 1);
    menu("admin/comment/comments/1", "comment approval queue", "comment_admin", comment_help("admin/comment/comments/1"), 2);
    menu("admin/comment/search", "search comments", "comment_admin", comment_help("admin/comment/search"), 8);
Dries's avatar
   
Dries committed
807
808
    menu("admin/comment/help", "help", "comment_help", NULL, 9);
    menu("admin/comment/edit", "edit comment", "comment_admin", NULL, 0, 1);
Dries's avatar
   
Dries committed
809
810
811

    // comment settings:
    if (user_access("administer moderation")) {
Dries's avatar
   
Dries committed
812
813
814
815
      menu("admin/comment/moderation", "comment moderation", NULL, comment_help("admin/comment/moderation"), 3);
      menu("admin/comment/moderation/votes", "votes", "comment_admin", comment_help("admin/comment/moderation/votes"));
      menu("admin/comment/moderation/matrix", "matrix", "comment_admin", comment_help("admin/comment/moderation/matrix"));
      menu("admin/comment/moderation/filters", "thresholds", "comment_admin", comment_help("admin/comment/moderation/filters"));
Dries's avatar
   
Dries committed
816
      menu("admin/comment/moderation/roles", "initial comment scores", "comment_admin", comment_help("admin/comment/roles"), 6);
Dries's avatar
   
Dries committed
817
818
819
    }
  }

Dries's avatar
   
Dries committed
820
  return $links ? $links : array();
Dries's avatar
   
Dries committed
821
822
}

Dries's avatar
   
Dries committed
823
function comment_page() {
Dries's avatar
   
Dries committed
824
825
  $op = $_POST["op"];
  $edit = $_POST["edit"];
Dries's avatar
   
Dries committed
826
827
828
829

  if (empty($op)) {
    $op = arg(1);
  }
Dries's avatar
   
Dries committed
830
831
832

  switch ($op) {
    case "edit":
Dries's avatar
   
Dries committed
833
      theme("header");
Dries's avatar
   
Dries committed
834
      comment_edit(check_query(arg(2)));
Dries's avatar
   
Dries committed
835
      theme("footer");
Dries's avatar
   
Dries committed
836
      break;
Dries's avatar
   
Dries committed
837
838
839
    case t("Moderate comments"):
    case t("Moderate comment"):
      comment_moderate($edit);
Dries's avatar
   
Dries committed
840
      drupal_goto(url("node/view/". $edit["nid"]));
Dries's avatar
   
Dries committed
841
      break;
Dries's avatar
   
Dries committed
842
    case "reply":
Dries's avatar
   
Dries committed
843
      theme("header");
Dries's avatar
   
Dries committed
844
      comment_reply(check_query(arg(3)), check_query(arg(2)));
Dries's avatar
   
Dries committed
845
      theme("footer");
Dries's avatar
   
Dries committed
846
847
      break;
    case t("Preview comment"):
Dries's avatar
   
Dries committed
848
      theme("header");
Dries's avatar
   
Dries committed
849
      comment_preview($edit);
Dries's avatar
   
Dries committed
850
      theme("footer");
Dries's avatar
   
Dries committed
851
852
      break;
    case t("Post comment"):
Dries's avatar
   
Dries committed
853
854
      list($error_title, $error_body) = comment_post($edit);
      if ($error_body) {
Dries's avatar
   
Dries committed
855
856
857
        theme("header");
        theme("box", $error_title, $error_body);
        theme("footer");
Dries's avatar
   
Dries committed
858
859
      }
      else {
Dries's avatar
   
Dries committed
860
        drupal_goto(url("node/view/". $edit["nid"]));
Dries's avatar
   
Dries committed
861
      }
Dries's avatar
   
Dries committed
862
      break;
863
    case t("Save settings"):
Dries's avatar
   
Dries committed
864
865
866
867
868
      $mode = $_POST["mode"];
      $order = $_POST["order"];
      $threshold = $_POST["threshold"];
      $comments_per_page = $_POST["comments_per_page"];

869
      comment_save_settings(check_query($mode), check_query($order), check_query($threshold), check_query($comments_per_page));
Dries's avatar
   
Dries committed
870
      drupal_goto(url("node/view/". $edit["nid"], "mode=$mode&order=$order&threshold=$threshold&comments_per_page=$comments_per_page"));
Dries's avatar
   
Dries committed
871
872
873
874
      break;
  }
}

Dries's avatar
   
Dries committed
875
876
877
/**
*** admin functions
**/
Dries's avatar
   
Dries committed
878

Dries's avatar
   
Dries committed
879
function comment_node_link($node) {
Dries's avatar
 
Dries committed
880

Dries's avatar
   
Dries committed
881
  if (user_access("administer comments")) {
Dries's avatar
 
Dries committed
882

Dries's avatar
   
Dries committed
883
884
885
    /*
    ** Edit comments:
    */
Dries's avatar
 
Dries committed
886

Dries's avatar
   
Dries committed
887
    $result = db_query("SELECT c.cid, c.subject, u.uid, u.name FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE nid = %d AND c.status = 0 ORDER BY c.timestamp", $node->nid);
Dries's avatar
   
Dries committed
888

Dries's avatar
   
Dries committed
889
890

    $header = array(t("title"), t("author"), array("data" => t("operations"), "colspan" => 3));
Dries's avatar
   
Dries committed
891
892

    while ($comment = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
893
      $rows[] = array(l($comment->subject, "node/view/$node->nid#$comment->cid"), format_name($comment), l(t("view comment"), "node/view/$node->nid#$comment->cid"), l(t("edit comment"), "admin/comment/edit/$comment->cid"), l(t("delete comment"), "admin/comment/delete/$comment->cid"));
Dries's avatar
   
Dries committed
894
895
    }

Dries's avatar
   
Dries committed
896
897
898
899
    if ($rows) {
      $output  = "<h3>". t("Edit comments") ."</h3>";
      $output .= table($header, $rows);
    }
Dries's avatar
   
Dries committed
900
901

    return $output;
Dries's avatar
 
Dries committed
902
  }
Dries's avatar
   
Dries committed
903
}
Dries's avatar
   
Dries committed
904

Dries's avatar
   
Dries committed
905
906
function comment_admin_edit($id) {

Dries's avatar
   
Dries committed
907
  $result = db_query("SELECT c.*, u.name, u.uid FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = %d AND c.status != 2", $id);
Dries's avatar
   
Dries committed
908
909
910
911
912
913
914
915
916
917
918
919
920
921
  $comment = db_fetch_object($result);

  // if a comment is "deleted", it's deleted
  if ($comment) {
    $form .= form_item(t("Author"), format_name($comment));
    $form .= form_textfield(t("Subject"), "subject", $comment->subject, 70, 128);
    $form .= form_textarea(t("Comment"), "comment", $comment->comment, 70, 15);
    $form .= form_select(t("Status"), "status", $comment->status, array("published", "not published"));
    $form .= form_hidden("cid", $id);
    $form .= form_submit(t("Submit"));
    $form .= form_submit(t("Delete"));

    return form($form);
  }
Dries's avatar
 
Dries committed
922
923
}

Dries's avatar
   
Dries committed
924
925
926
function comment_delete($edit) {

  if ($edit["confirm"]) {
Dries's avatar
   
Dries committed
927
    db_query("UPDATE {comments} SET status = 2 WHERE cid = %d", $edit["cid"]);
Dries's avatar
   
Dries committed
928
    watchdog("special", "comment: deleted comment #". $edit["cid"]);
Dries's avatar
   
Dries committed
929
    $output = "deleted comment.";
Dries's avatar
   
Dries committed
930
931
932
933
934
935
936
937
938
939
  }
  else {
    $output .= form_item(t("Confirm deletion"), "");
    $output .= form_hidden("cid", $edit["cid"]);
    $output .= form_hidden("confirm", 1);
    $output .= form_submit(t("Delete"));
    $output = form($output);
  }

  return $output;
Dries's avatar
   
Dries committed
940
941
}

Dries's avatar
   
Dries committed
942
function comment_save($id, $edit) {
Dries's avatar
   
Dries committed
943
  db_query("UPDATE {comments} SET subject = '%s', comment = '%s', status = %d WHERE cid = %d", $edit["subject"], $edit["comment"], $edit["status"], $id);
Dries's avatar
   
Dries committed
944
  watchdog("special", "comment: modified '". $edit["subject"] ."'");
Dries's avatar
   
Dries committed
945
  return "updated comment.";
Dries's avatar
   
Dries committed
946
947
}

Dries's avatar
   
Dries committed
948
function comment_admin_overview($status = 0) {
Dries's avatar
   
Dries committed
949

Dries's avatar
   
Dries committed
950
  $header = array(
Dries's avatar
Dries committed
951
952
953
954
    array("data" => t("subject"), "field" => "subject"),
    array("data" => t("author"), "field" => "u.name"),
    array("data" => t("status"), "field" => "status"),
    array("data" => t("time"), "field" => "timestamp", "sort" => "desc"),
Dries's avatar
   
Dries committed
955
956
957
    array("data" => t("operations"), "colspan" => 2)
  );

Dries's avatar
   
Dries committed
958
  $sql = "SELECT c.*, u.name, u.uid FROM {comments} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.status = ". check_query($status);
Dries's avatar
   
Dries committed
959
960
  $sql .= tablesort_sql($header);
  $result = pager_query($sql,  50);
Dries's avatar
   
Dries committed
961
962

  while ($comment = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
963
    $rows[] = array(l($comment->subject, "node/view/$comment->nid/$comment->cid#$comment->cid", array("title" => htmlspecialchars(substr($comment->comment, 0, 128)))) ." ". (node_is_new($comment->nid, $comment->timestamp) ? theme_mark() : ""), format_name($comment), ($comment->status == 0 ? t("published") : t("not published")) ."</td><td>". format_date($comment->timestamp, "small"). "</td><td>". l(t("edit comment"), "admin/comment/edit/$comment->cid"), l(t("delete comment"), "admin/comment/delete/$comment->cid"));
Dries's avatar
   
Dries committed
964
965
  }

Dries's avatar
   
Dries committed
966
967
  if ($pager = pager_display(NULL, 50, 0, "admin", tablesort_pager())) {
    $rows[] = array(array("data" => $pager, "colspan" => 6));
Dries's avatar
   
Dries committed
968
969
  }

Dries's avatar
   
Dries committed
970
  return table($header, $rows);
Dries's avatar
   
Dries committed
971
972
973
974
}

function comment_mod_matrix($edit) {

Dries's avatar
   
Dries committed
975
  $output .= "<h3>Moderation vote/value matrix</h3>";
Dries's avatar
   
Dries committed
976

Dries's avatar
Dries committed
977
  if ($edit) {
Dries's avatar
   
Dries committed
978
    db_query("DELETE FROM {moderation_roles} ");
Dries's avatar
Dries committed
979
    foreach ($edit as $role_id => $votes) {
Dries's avatar
   
Dries committed
980
      foreach ($votes as $mid => $value) {
Dries's avatar
   
Dries committed
981
        $sql[] = "('$mid', '$role_id', '". ($value ? $value : 0 ) ."')";
Dries's avatar
   
Dries committed
982
983
      }
    }
Dries's avatar
   
Dries committed
984
    db_query("INSERT INTO {moderation_roles} (mid, rid, value) VALUES ". implode(", ", $sql));
Dries's avatar
   
Dries committed
985
    $output = status("Vote values saved");
Dries's avatar
   
Dries committed
986
987
  }

Dries's avatar
   
Dries committed
988
  $result = db_query("SELECT r.rid, r.name FROM {role} r, {permission} p WHERE r.rid = p.rid AND p.perm LIKE '%moderate comments%'");
Dries's avatar
   
Dries committed
989
990
991
992
993
  $role_names = array();
  while ($role = db_fetch_object($result)) {
    $role_names[$role->rid] = $role->name;
  }

Dries's avatar
   
Dries committed
994
  $result = db_query("SELECT rid, mid, value FROM {moderation_roles} ");
Dries's avatar
   
Dries committed
995
996
997
998
  while ($role = db_fetch_object($result)) {
    $mod_roles[$role->rid][$role->mid] = $role->value;
  }

Dries's avatar
Dries committed
999
  $header = array_merge(array(t("votes")), array_values($role_names));
Dries's avatar
   
Dries committed
1000

Dries's avatar
   
Dries committed
1001
  $result = db_query("SELECT mid, vote FROM {moderation_votes} ORDER BY weight");
Dries's avatar
   
Dries committed
1002
  while ($vote = db_fetch_object($result)) {
Dries's avatar
Dries committed
1003
    $row = array($vote->vote);
Dries's avatar
   
Dries committed
1004
    foreach (array_keys($role_names) as $rid) {
Dries's avatar
Dries committed
1005
      $row[] = array("data" => form_textfield(NULL, "$rid][$vote->mid", $mod_roles[$rid][$vote->mid], 4, 3), "align" => "center");
Dries's avatar
   
Dries committed
1006
    }
Dries's avatar
Dries committed
1007
    $rows[] = $row;
Dries's avatar
   
Dries committed
1008
  }
Dries's avatar
Dries committed
1009
  $output .= table($header, $rows);
Dries's avatar
   
Dries committed
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
  $output .= "<br />". form_submit(t("Submit votes"));

  return form($output);
}

function comment_mod_roles($edit) {

  $output .= "<h3>Initial comment scores</h3>";

  if ($edit) {
    variable_set("comment_roles", $edit);
Dries's avatar
   
Dries committed
1021
    $output = status("Comment scores saved");
Dries's avatar
   
Dries committed
1022
1023
1024
1025
  }

  $start_values = variable_get("comment_roles", array());

Dries's avatar
   
Dries committed
1026
  $result = db_query("SELECT r.rid, r.name FROM {role} r, {permission} p WHERE r.rid = p.rid AND p.perm LIKE '%post comments%'");
Dries's avatar
   
Dries committed
1027

Dries's avatar
Dries committed
1028
  $header = array(t("user role"), t("initial score"));
Dries's avatar
   
Dries committed
1029
1030

  while ($role = db_fetch_object($result)) {
Dries's avatar
Dries committed
1031
    $rows[] = array($role->name, array("data" => form_textfield(NULL, $role->rid, $start_values[$role->rid], 4, 3), "align" => "center"));
Dries's avatar
   
Dries committed
1032
1033
  }

Dries's avatar
Dries committed
1034
  $output .= table($header, $rows);
Dries's avatar
   
Dries committed
1035
1036
1037
1038
1039
1040
  $output .= "<br />". form_submit(t("Save scores"));

  return form($output);
}

function comment_mod_votes($edit) {
Dries's avatar
   
Dries committed
1041
  $op = $_POST["op"];
Dries's avatar
   
Dries committed
1042

Dries's avatar
   
Dries committed
1043
  $mid = arg(4);
Dries's avatar
   
Dries committed
1044
1045

  if ($op == t("Save vote")) {
Dries's avatar
   
Dries committed
1046
    db_query("UPDATE {moderation_votes} SET vote = '%s', weight = %d WHERE mid = %d", $edit["vote"], $edit["weight"], $mid);
Dries's avatar
   
Dries committed
1047
    $mid = 0;
Dries's avatar
   
Dries committed
1048
    $output = status("Vote saved");
Dries's avatar
   
Dries committed
1049
1050
  }
  else