comment.module 61.4 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", $user->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
}
Dries's avatar
   
Dries committed
144
145
146
147
148
149
150
151
152
153
154
function comment_referer_save() {
  $_SESSION["comment_referer"] = arg(0)."/".arg(1)."/".arg(2);
}

/*
** Restores the referer from a persistent variable:
*/

function comment_referer_load() {
  return $_SESSION["comment_referer"];
}
Dries's avatar
   
Dries committed
155
156
157
158

function comment_form($edit) {
  global $user;

Dries's avatar
   
Dries committed
159
  $form .= "<a id=\"comment\"></a>\n";
Dries's avatar
   
Dries committed
160
161
162
163
164

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

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

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

  // preview button:
Dries's avatar
   
Dries committed
171
  $form .= form_hidden("cid", $edit["cid"]);
Dries's avatar
   
Dries committed
172
  $form .= form_hidden("pid", $edit["pid"]);
Dries's avatar
   
Dries committed
173
  $form .= form_hidden("nid", $edit["nid"]);
Dries's avatar
   
Dries committed
174

Dries's avatar
   
Dries committed
175
  if (!$edit["comment"] && variable_get("comment_preview", 1)) {
Dries's avatar
   
Dries committed
176
177
178
179
180
181
182
    $form .= form_submit(t("Preview comment"));
  }
  else {
    $form .= form_submit(t("Preview comment"));
    $form .= form_submit(t("Post comment"));
  }

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

Dries's avatar
   
Dries committed
186
187
188
function comment_edit($cid) {
  global $user;

Dries's avatar
   
Dries committed
189
  $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
190
191
192
193
194
195
196

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

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

Dries's avatar
   
Dries committed
198

199
  if (user_access("access comments")) {
Dries's avatar
   
Dries committed
200
201
202
203
204

    /*
    ** Show comment
    */

Dries's avatar
   
Dries committed
205
    if ($pid) {
Dries's avatar
   
Dries committed
206
      $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
207
      comment_view($comment);
Dries's avatar
   
Dries committed
208
    }
Dries's avatar
   
Dries committed
209
    else if (user_access("access content")) {
Dries's avatar
   
Dries committed
210
      node_view(node_load(array("nid" => $nid)));
Dries's avatar
   
Dries committed
211
212
      $pid = 0;
    }
Dries's avatar
   
Dries committed
213

Dries's avatar
   
Dries committed
214
215
216
217
    /*
    ** If possible, show reply form
    */

Dries's avatar
   
Dries committed
218
    if (node_comment_mode($nid) != 2) {
Dries's avatar
   
Dries committed
219
      theme("box", t("Reply"), t("This discussion is closed: you can't post new comments."));
Kjartan's avatar
Kjartan committed
220
    }
Dries's avatar
   
Dries committed
221
    else if (user_access("post comments")) {
Dries's avatar
   
Dries committed
222
      theme("box", t("Reply"), comment_form(array("pid" => $pid, "nid" => $nid)));
Dries's avatar
   
Dries committed
223
224
    }
    else {
Dries's avatar
   
Dries committed
225
      theme("box", t("Reply"), t("You are not authorized to post comments."));
Dries's avatar
   
Dries committed
226
    }
Kjartan's avatar
Kjartan committed
227
228
  }
  else {
Dries's avatar
   
Dries committed
229
    theme("box", t("Reply"), t("You are not authorized to view comments."));
Dries's avatar
   
Dries committed
230
231
232
233
  }
}

function comment_preview($edit) {
Dries's avatar
   
Dries committed
234
  global $user;
Dries's avatar
   
Dries committed
235

Dries's avatar
   
Dries committed
236
237
238
239
  foreach ($edit as $key => $value) {
    $comment->$key = $value;
  }

Dries's avatar
   
Dries committed
240
  /*
Dries's avatar
   
Dries committed
241
  ** Attach the user and time information:
Dries's avatar
   
Dries committed
242
243
244
245
246
247
248
249
250
251
  */

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

  /*
  ** Preview the comment:
  */

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

Dries's avatar
   
Dries committed
254
  theme("box", t("Reply"), comment_form($edit));
Kjartan's avatar
Kjartan committed
255
256

  if ($edit["pid"]) {
Dries's avatar
   
Dries committed
257
    $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
258
    comment_view($comment);
Kjartan's avatar
Kjartan committed
259
260
  }
  else {
Dries's avatar
   
Dries committed
261
    node_view(node_load(array("nid" => $edit["nid"])));
Kjartan's avatar
Kjartan committed
262
263
    $edit["pid"] = 0;
  }
Dries's avatar
   
Dries committed
264
265
266
}

function comment_post($edit) {
Dries's avatar
   
Dries committed
267
  global $user;
Dries's avatar
   
Dries committed
268

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

Dries's avatar
   
Dries committed
271
272
273
274
275
    /*
    ** Validate the comment's subject.  If not specified, extract
    ** one from the comment's body.
    */

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

Dries's avatar
   
Dries committed
278
279
280
    if ($edit["subject"] == "") {
      $edit["subject"] = substr(strip_tags($edit["comment"]), 0, 29);
    }
Dries's avatar
   
Dries committed
281
282
283
284
285

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

Dries's avatar
   
Dries committed
286
287
288
289
    if ($edit["comment"] == "") {
      return array(t("Empty comment"), t("The comment you submitted is empty."));
    }

Dries's avatar
   
Dries committed
290
291
292
293
294
    /*
    ** Check for duplicate comments.  Note that we have to use the
    ** validated/filtered data to perform such check.
    */

Dries's avatar
   
Dries committed
295
    $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
296
297

    if ($duplicate != 0) {
Dries's avatar
   
Dries committed
298
      watchdog("warning", "comment: duplicate '". $edit["subject"] ."'");
Dries's avatar
   
Dries committed
299
      return array(t("Duplicate comment"), t("The comment you submitted has already been inserted."));
Dries's avatar
   
Dries committed
300
301
302
    }
    else {

Dries's avatar
   
Dries committed
303
      if ($edit["cid"]) {
Dries's avatar
   
Dries committed
304

Dries's avatar
   
Dries committed
305
306
307
308
309
310
        /*
        ** 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
311
        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
312
313
314
315
316
317

        /*
        ** Fire a hook
        */

        module_invoke_all("comment", "update", $edit);
Dries's avatar
   
Dries committed
318
319
320
321
322

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

Dries's avatar
   
Dries committed
323
        watchdog("special", "comment: updated '". $edit["subject"] ."'", l(t("view comment"), "node/view/". $edit["nid"] ."#". $edit["cid"]));
Dries's avatar
   
Dries committed
324
325
326
327
328
329
330
331
332
333
334
335
336
      }
      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
337
338
339
340
341
        $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
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
418
419
420
421
422
423
424
425
426
427
428
        /*
        ** 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
429
        $edit["cid"] = db_next_id("comments_cid");
Dries's avatar
   
Dries committed
430

Dries's avatar
   
Dries committed
431
        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
432
433
434
435
436
437

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

        module_invoke_all("comment", "insert", $edit);
Dries's avatar
   
Dries committed
438
439
440
441

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

Dries's avatar
   
Dries committed
443
        watchdog("special", "comment: added '". $edit["subject"] ."'", l(t("view comment"), "node/view/". $edit["nid"] ."#". $edit["cid"]));
Dries's avatar
   
Dries committed
444
      }
Dries's avatar
   
Dries committed
445
446

      /*
Dries's avatar
   
Dries committed
447
448
      ** Clear the cache so an anonymous user can see his comment being
      ** added.
Dries's avatar
   
Dries committed
449
      */
Dries's avatar
   
Dries committed
450

Dries's avatar
   
Dries committed
451
      cache_clear_all();
Dries's avatar
   
Dries committed
452
453
    }
  }
Dries's avatar
   
Dries committed
454
455
456
457
  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
458
459

  /*
Dries's avatar
   
Dries committed
460
  ** Redirect the user the node he commented on, or explain queue
Dries's avatar
   
Dries committed
461
462
  */

Dries's avatar
   
Dries committed
463
464
  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
465
466
467
468
  }
}

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

Dries's avatar
   
Dries committed
471
  $links = array();
Dries's avatar
   
Dries committed
472

Dries's avatar
   
Dries committed
473
474
475
476
  /*
  ** If we are viewing just this comment, we link back to the node
  */

Dries's avatar
   
Dries committed
477
  if ($return) {
Dries's avatar
   
Dries committed
478
    $links[] = l(t("parent"), comment_referer_load()."#$comment->cid");
Dries's avatar
   
Dries committed
479
  }
Dries's avatar
   
Dries committed
480

Dries's avatar
   
Dries committed
481
482
483
484
  /*
  ** Admin link
  */

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

Dries's avatar
   
Dries committed
489
  /*
Dries's avatar
   
Dries committed
490
  ** Possibly show edit and reply links
Dries's avatar
   
Dries committed
491
  */
Dries's avatar
   
Dries committed
492

Dries's avatar
   
Dries committed
493
494
495
  if (node_comment_mode($comment->nid) == 2) {
    if (user_access("post comments")) {
      if (comment_access("edit", $comment)) {
Dries's avatar
   
Dries committed
496
        $links[] = l(t("edit your comment"), "comment/edit/$comment->cid", array("title" => t("Make changes to your comment.")));
Dries's avatar
   
Dries committed
497
      }
Dries's avatar
   
Dries committed
498
      $links[] = l(t("reply to this comment"), "comment/reply/$comment->nid/$comment->cid");
Dries's avatar
   
Dries committed
499
500
    }
    else {
501
      $links[] = theme("comment_post_forbidden");
Dries's avatar
   
Dries committed
502
    }
Dries's avatar
   
Dries committed
503
  }
Dries's avatar
   
Dries committed
504
505
506
507

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

Dries's avatar
   
Dries committed
509
  return theme("links", $links);
Dries's avatar
   
Dries committed
510
511
}

Dries's avatar
   
Dries committed
512
513
514
515
516
function comment_view($comment, $links = "", $visible = 1) {

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

Dries's avatar
   
Dries committed
518
  if (node_is_new($comment->nid, $comment->timestamp)) {
Dries's avatar
   
Dries committed
519
    $comment->new = 1;
Dries's avatar
   
Dries committed
520
    print "<a id=\"new\"></a>\n";
Dries's avatar
   
Dries committed
521
  }
Dries's avatar
   
Dries committed
522

Dries's avatar
   
Dries committed
523
  print "<a id=\"$comment->cid\"></a>\n";
Dries's avatar
   
Dries committed
524
525

  if ($visible) {
Dries's avatar
   
Dries committed
526
    $comment->comment = check_output($comment->comment);
527
    theme("comment", $comment, $links);
Dries's avatar
   
Dries committed
528
529
  }
  else {
530
    theme("comment_folded", $comment);
Dries's avatar
   
Dries committed
531
532
533
  }
}

Dries's avatar
   
Dries committed
534
function comment_render($node, $cid = 0) {
Dries's avatar
   
Dries committed
535
536
537
538
539
540
541
  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
542
543
544
545
546
547
548

  if (user_access("access comments")) {

    /*
    ** Pre-process variables:
    */

Dries's avatar
   
Dries committed
549
    $nid = $node->nid;
Dries's avatar
   
Dries committed
550
551
    if (empty($nid)) {
      $nid = 0;
Dries's avatar
   
Dries committed
552
553
554
    }

    if (empty($mode)) {
Dries's avatar
   
Dries committed
555
      $mode = $user->mode ? $user->mode : variable_get("comment_default_mode", 4);
Dries's avatar
   
Dries committed
556
557
558
    }

    if (empty($order)) {
Dries's avatar
   
Dries committed
559
      $order = $user->sort ? $user->sort : variable_get("comment_default_order", 1);
Dries's avatar
   
Dries committed
560
561
562
    }

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

Dries's avatar
   
Dries committed
567
568
569
    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
570

Dries's avatar
   
Dries committed
571
    print "<a id=\"comment\"></a>\n";
Dries's avatar
   
Dries committed
572
573


Kjartan's avatar
Kjartan committed
574
    if ($cid) {
Dries's avatar
   
Dries committed
575
576
577
578
579

      /*
      ** Single comment view
      */

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

Dries's avatar
   
Dries committed
583
      $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
584

Dries's avatar
   
Dries committed
585
586
587
      if ($comment = db_fetch_object($result)) {
        comment_view($comment, comment_links($comment));
      }
Dries's avatar
   
Dries committed
588

Dries's avatar
   
Dries committed
589
      if ((comment_user_can_moderate($node)) && $user->uid != $comment->uid && !(comment_already_moderated($user->uid, $comment->users))) {
Dries's avatar
   
Dries committed
590
        print "<div style=\"text-align: center;\">". form_submit(t("Moderate comment")) ."</div><br />";
Dries's avatar
   
Dries committed
591
      }
Dries's avatar
   
Dries committed
592
      print "</div></form>";
Dries's avatar
   
Dries committed
593
    }
Dries's avatar
   
Dries committed
594
    else {
Dries's avatar
   
Dries committed
595

Dries's avatar
   
Dries committed
596
597
598
599
      /*
      ** Multiple comments view
      */

Dries's avatar
   
Dries committed
600
      $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
601
602

      $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
603

Dries's avatar
   
Dries committed
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
655
656
657
658
659
660
661
662
663
664
665
      /*
      ** 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
666
667

      if ($order == 1) {
Dries's avatar
   
Dries committed
668
669
670
671
672
673
        if ($mode == 1 || $mode == 2) {
          $query .= " ORDER BY c.timestamp DESC";
        }
        else {
          $query .= " ORDER BY c.thread DESC";
        }
Dries's avatar
   
Dries committed
674
      }
Dries's avatar
   
Dries committed
675
      else if ($order == 2) {
Dries's avatar
   
Dries committed
676
677
678
679
680
681
682
683
684
685
686
687
688
        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
689
690
691
      }

      /*
Dries's avatar
   
Dries committed
692
      ** Start a form, to use with comment control and moderation.
Dries's avatar
   
Dries committed
693
694
      */

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

Dries's avatar
   
Dries committed
697
      if ((variable_get("comment_controls", 0) == 0) || (variable_get("comment_controls", 0) == 2)) {
Dries's avatar
   
Dries committed
698
        print "<form method=\"post\" action=\"". url("comment") ."\"><div>\n";
Dries's avatar
   
Dries committed
699
        theme("comment_controls", $threshold, $mode, $order, $comments_per_page);
Dries's avatar
   
Dries committed
700
        print form_hidden("nid", $nid);
Dries's avatar
   
Dries committed
701
        print "</div></form>";
Dries's avatar
   
Dries committed
702
      }
Dries's avatar
   
Dries committed
703

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

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

Dries's avatar
   
Dries committed
710
711
        if ($mode == 1) {
          theme("comment_flat_collapsed", $comment, $threshold_min);
Dries's avatar
   
Dries committed
712
        }
Dries's avatar
   
Dries committed
713
        else if ($mode == 2) {
Dries's avatar
   
Dries committed
714
          theme("comment_flat_expanded", $comment, $threshold_min);
Dries's avatar
   
Dries committed
715
        }
Dries's avatar
   
Dries committed
716
        else if ($mode == 3) {
Dries's avatar
   
Dries committed
717
          theme("comment_thread_min", $comment, $threshold_min);
Dries's avatar
   
Dries committed
718
        }
Dries's avatar
   
Dries committed
719
720
721
722
        else if ($mode == 4) {
          theme("comment_thread_max", $comment, $threshold_min);
        }
      }
Dries's avatar
   
Dries committed
723

Dries's avatar
   
Dries committed
724
725
726
727
728
729
730
      /*
      ** 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
731

Dries's avatar
   
Dries committed
732
733
      if (comment_user_can_moderate($node)) {
        print "<div align=\"center\">". form_submit(t("Moderate comments")) ."</div><br />";
Dries's avatar
   
Dries committed
734
      }
Dries's avatar
   
Dries committed
735

Dries's avatar
   
Dries committed
736
      print "</div></form>";
Dries's avatar
   
Dries committed
737

Dries's avatar
   
Dries committed
738
      if ((variable_get("comment_controls", 0) == 1) || (variable_get("comment_controls", 0) == 2)) {
Dries's avatar
   
Dries committed
739
        print "<form method=\"post\" action=\"". url("comment") ."\"><div>\n";
Dries's avatar
   
Dries committed
740
        theme("comment_controls", $threshold, $mode, $order, $comments_per_page);
Dries's avatar
   
Dries committed
741
        print form_hidden("nid", $nid);
Dries's avatar
   
Dries committed
742
        print "</div></form>";
Dries's avatar
   
Dries committed
743
      }
Dries's avatar
   
Dries committed
744
745
    }

Dries's avatar
   
Dries committed
746
747
748
749
750
    /*
    ** 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
751
      theme("box", t("Post new comment"), comment_form(array("nid" => $nid)));
Dries's avatar
   
Dries committed
752
    }
Dries's avatar
   
Dries committed
753

Dries's avatar
   
Dries committed
754
755
756
757
758
    /*
    ** Save were we come from so we can go back after a reply
    */

    comment_referer_save();
Dries's avatar
   
Dries committed
759
760
761
  }
}

Dries's avatar
   
Dries committed
762
763
764
function comment_perm() {
  return array("access comments", "post comments", "administer comments", "moderate comments", "post comments without approval", "administer moderation");
}
Dries's avatar
   
Dries committed
765

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

Dries's avatar
   
Dries committed
768
  if ($type == "node" && $node->comment) {
Dries's avatar
   
Dries committed
769
770
771
772
773
774
775
776

    if ($main) {

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

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

Dries's avatar
   
Dries committed
780
        if ($all) {
Dries's avatar
   
Dries committed
781
          $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
782

Dries's avatar
   
Dries committed
783
          if ($new) {
Dries's avatar
   
Dries committed
784
            $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
785
786
787
          }
        }
        else {
Dries's avatar
   
Dries committed
788
789
790
791
792
793
794
          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
795
796
          }
        }
Dries's avatar
   
Dries committed
797
798
799
800
801
      }
    }
    else {
      /*
      ** Node page: add a "post comment" link if the user is allowed to
Dries's avatar
   
Dries committed
802
      ** post comments and if this node is not read-only
Dries's avatar
   
Dries committed
803
804
      */

Dries's avatar
   
Dries committed
805
806
      if ($node->comment == 2) {
        if (user_access("post comments")) {
Dries's avatar
   
Dries committed
807
          $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
808
809
        }
        else {
810
          $links[] = theme("comment_post_forbidden");
Dries's avatar
   
Dries committed
811
        }
Dries's avatar
   
Dries committed
812
813
814
815
      }
    }
  }

Dries's avatar
   
Dries committed
816
817
818
  if ($type == "system") {
    if (user_access("administer comments")) {

Dries's avatar
   
Dries committed
819
820
821
822
823
824
825
      menu("admin/comment", t("comments"), "comment_admin", comment_help("admin/comment"), 1);
      menu("admin/comment/comments", t("overview"), NULL, comment_help("admin/comment/comments"), 2);
      menu("admin/comment/comments/0", t("new/updated"), "comment_admin", comment_help("admin/comment/comments/0"), 1);
      menu("admin/comment/comments/1", t("approval queue"), "comment_admin", comment_help("admin/comment/comments/1"), 2);
      menu("admin/comment/search", t("search"), "comment_admin", comment_help("admin/comment/search"), 8);
      menu("admin/comment/help", t("help"), "comment_help", NULL, 9);
      menu("admin/comment/edit", t("edit comment"), "comment_admin", NULL, 0, 1);
Dries's avatar
   
Dries committed
826
827
828

      // comment settings:
      if (user_access("administer moderation")) {
Dries's avatar
   
Dries committed
829
830
831
832
833
        menu("admin/comment/moderation", t("moderation"), NULL, comment_help("admin/comment/moderation"), 3);
        menu("admin/comment/moderation/votes", t("votes"), "comment_admin", comment_help("admin/comment/moderation/votes"));
        menu("admin/comment/moderation/matrix", t("matrix"), "comment_admin", comment_help("admin/comment/moderation/matrix"));
        menu("admin/comment/moderation/filters", t("thresholds"), "comment_admin", comment_help("admin/comment/moderation/filters"));
        menu("admin/comment/moderation/roles", t("initial scores"), "comment_admin", comment_help("admin/comment/roles"), 6);
Dries's avatar
   
Dries committed
834
      }
Dries's avatar
   
Dries committed
835
836
837
    }
  }

Dries's avatar
   
Dries committed
838
  return $links ? $links : array();
Dries's avatar
   
Dries committed
839
840
}

Dries's avatar
   
Dries committed
841
function comment_page() {
Dries's avatar
   
Dries committed
842
843
  $op = $_POST["op"];
  $edit = $_POST["edit"];
Dries's avatar
   
Dries committed
844
845
846
847

  if (empty($op)) {
    $op = arg(1);
  }
Dries's avatar
   
Dries committed
848
849
850

  switch ($op) {
    case "edit":
Dries's avatar
   
Dries committed
851
      theme("header");
Dries's avatar
   
Dries committed
852
      comment_edit(check_query(arg(2)));
Dries's avatar
   
Dries committed
853
      theme("footer");
Dries's avatar
   
Dries committed
854
      break;
Dries's avatar
   
Dries committed
855
856
857
    case t("Moderate comments"):
    case t("Moderate comment"):
      comment_moderate($edit);
Dries's avatar
   
Dries committed
858
      drupal_goto(url(comment_referer_load()));
Dries's avatar
   
Dries committed
859
      break;
Dries's avatar
   
Dries committed
860
    case "reply":
Dries's avatar
   
Dries committed
861
      theme("header");
Dries's avatar
   
Dries committed
862
      comment_reply(check_query(arg(3)), check_query(arg(2)));
Dries's avatar
   
Dries committed
863
      theme("footer");
Dries's avatar
   
Dries committed
864
865
      break;
    case t("Preview comment"):
Dries's avatar
   
Dries committed
866
      theme("header");
Dries's avatar
   
Dries committed
867
      comment_preview($edit);
Dries's avatar
   
Dries committed
868
      theme("footer");
Dries's avatar
   
Dries committed
869
870
      break;
    case t("Post comment"):
Dries's avatar
   
Dries committed
871
872
      list($error_title, $error_body) = comment_post($edit);
      if ($error_body) {
Dries's avatar
   
Dries committed
873
874
875
        theme("header");
        theme("box", $error_title, $error_body);
        theme("footer");
Dries's avatar
   
Dries committed
876
877
      }
      else {
Dries's avatar
   
Dries committed
878
        drupal_goto(url(comment_referer_load()));
Dries's avatar
   
Dries committed
879
      }
Dries's avatar
   
Dries committed
880
      break;
881
    case t("Save settings"):
Dries's avatar
   
Dries committed
882
883
884
885
886
      $mode = $_POST["mode"];
      $order = $_POST["order"];
      $threshold = $_POST["threshold"];
      $comments_per_page = $_POST["comments_per_page"];

887
      comment_save_settings(check_query($mode), check_query($order), check_query($threshold), check_query($comments_per_page));
Dries's avatar
   
Dries committed
888
889
      //drupal_goto(url(comment_referer_load(), "mode=$mode&order=$order&threshold=$threshold&comments_per_page=$comments_per_page"));
      drupal_goto(url(comment_referer_load()));
Dries's avatar
   
Dries committed
890
891
892
893
      break;
  }
}

Dries's avatar
   
Dries committed
894
895
896
/**
*** admin functions
**/
Dries's avatar
   
Dries committed
897

Dries's avatar
   
Dries committed
898
function comment_node_link($node) {
Dries's avatar
 
Dries committed
899

Dries's avatar
   
Dries committed
900
  if (user_access("administer comments")) {
Dries's avatar
 
Dries committed
901

Dries's avatar
   
Dries committed
902
903
904
    /*
    ** Edit comments:
    */
Dries's avatar
 
Dries committed
905

Dries's avatar
   
Dries committed
906
    $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
907

Dries's avatar
   
Dries committed
908
909

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

    while ($comment = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
912
      $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
913
914
    }

Dries's avatar
   
Dries committed
915
916
917
918
    if ($rows) {
      $output  = "<h3>". t("Edit comments") ."</h3>";
      $output .= table($header, $rows);
    }
Dries's avatar
   
Dries committed
919
920

    return $output;
Dries's avatar
 
Dries committed
921
  }
Dries's avatar
   
Dries committed
922
}
Dries's avatar
   
Dries committed
923

Dries's avatar
   
Dries committed
924
925
function comment_admin_edit($id) {

Dries's avatar
   
Dries committed
926
  $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
927
928
929
930
931
932
933
934
935
936
937
938
939
940
  $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
941
942
}

Dries's avatar
   
Dries committed
943
944
945
function comment_delete($edit) {

  if ($edit["confirm"]) {
Dries's avatar
   
Dries committed
946
    db_query("UPDATE {comments} SET status = 2 WHERE cid = %d", $edit["cid"]);
Dries's avatar
   
Dries committed
947
    watchdog("special", "comment: deleted comment #". $edit["cid"]);
Dries's avatar
   
Dries committed
948
    $output = "deleted comment.";
Dries's avatar
   
Dries committed
949
950
951
952
953
954
955
956
957
958
  }
  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
959
960
}

Dries's avatar
   
Dries committed
961
function comment_save($id, $edit) {
Dries's avatar
   
Dries committed
962
  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
963
  watchdog("special", "comment: modified '". $edit["subject"] ."'");
Dries's avatar
   
Dries committed
964
  return "updated comment.";
Dries's avatar
   
Dries committed
965
966
}

Dries's avatar
   
Dries committed
967
function comment_admin_overview($status = 0) {
Dries's avatar
   
Dries committed
968

Dries's avatar
   
Dries committed
969
  $header = array(
Dries's avatar
Dries committed
970
971
972
973
    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
974
975
976
    array("data" => t("operations"), "colspan" => 2)
  );

Dries's avatar
   
Dries committed
977
  $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
978
979
  $sql .= tablesort_sql($header);
  $result = pager_query($sql,  50);
Dries's avatar
   
Dries committed
980
981

  while ($comment = db_fetch_object($result)) {
Dries's avatar
   
Dries committed
982
    $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
983
984
  }

Dries's avatar
   
Dries committed
985
986
  if ($pager = pager_display(NULL, 50, 0, "admin", tablesort_pager())) {
    $rows[] = array(array("data" => $pager, "colspan" => 6));
Dries's avatar
   
Dries committed
987
988
  }

Dries's avatar
   
Dries committed
989
  return table($header, $rows);
Dries's avatar
   
Dries committed
990
991
992
993
}

function comment_mod_matrix($edit) {

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

Dries's avatar
Dries committed
996
  if ($edit) {
Dries's avatar
   
Dries committed
997
    db_query("DELETE FROM {moderation_roles} ");
Dries's avatar
Dries committed
998
    foreach ($edit as $role_id => $votes) {
Dries's avatar
   
Dries committed
999
      foreach ($votes as $mid => $value) {
Dries's avatar
   
Dries committed
1000
        $sql[] = "('$mid', '$role_id', '". ($value ? $value : 0 ) ."')";
Dries's avatar
   
Dries committed
1001
1002
      }
    }
Dries's avatar
   
Dries committed
1003
    db_query("INSERT INTO {moderation_roles} (mid, rid, value) VALUES ". implode(", ", $sql));
Dries's avatar
   
Dries committed
1004
    $output = status("Vote values saved");
Dries's avatar
   
Dries committed
1005
1006
  }

Dries's avatar
   
Dries committed
1007
  $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
1008
1009
1010
1011
1012
  $role_names = array();
  while ($role = db_fetch_object($result)) {
    $role_names[$role->rid] = $role->name;
  }

Dries's avatar
   
Dries committed
1013
  $result = db_query("SELECT rid, mid, value FROM {moderation_roles} ");
Dries's avatar
   
Dries committed
1014
1015
1016
1017
  while ($role = db_fetch_object($result)) {
    $mod_roles[$role->rid][$role->mid] = $role->value;
  }

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

Dries's avatar
   
Dries committed
1020
  $result = db_query("SELECT mid, vote FROM {moderation_votes} ORDER BY weight");
Dries's avatar
   
Dries committed
1021
  while ($vote = db_fetch_object($result)) {
Dries's avatar
Dries committed
1022
    $row = array($vote->vote);
Dries's avatar
   
Dries committed
1023
    foreach (array_keys($role_names) as $rid) {
Dries's avatar
Dries committed
1024
      $row[] = array("data" => form_textfield(NULL, "$rid][$vote->mid", $mod_roles[$rid][$vote->mid], 4, 3), "align" => "center");
Dries's avatar
   
Dries committed
1025
    }
Dries's avatar
Dries committed
1026
    $rows[] = $row;
Dries's avatar
   
Dries committed
1027
  }
Dries's avatar
Dries committed
1028
  $output .= table($header, $rows);
Dries's avatar
   
Dries committed
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
  $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
1040
    $output = status("Comment scores saved");
Dries's avatar
   
Dries committed
1041
1042
1043
1044
  }

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

Dries's avatar
   
Dries committed
1045
  $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
1046

Dries's avatar
Dries committed
1047
  $header = array(t("user role"), t("initial score"));
Dries's avatar
   
Dries committed
1048
1049

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

Dries's avatar
Dries committed
1053
  $output .= table($header, $rows);
Dries's avatar
   
Dries committed
1054
1055
1056
1057
1058
1059
  $output .= "<br />". form_submit(t("Save scores"));

  return form($output);
}

function comment_mod_votes($edit) {
Dries's avatar