/[drupal]/contributions/modules/nodecomment/nodecomment.module
ViewVC logotype

Contents of /contributions/modules/nodecomment/nodecomment.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Thu Sep 25 17:58:03 2008 UTC (14 months ago) by sirkitree
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +236 -186 lines
File MIME type: text/x-php
setting HEAD to the same as DRUPAL-6--1-2-RC1

#310619: applying patch provided by wmostry
1 <?php
2 // $Id: nodecomment.module,v 1.3.2.15.2.4 2008/07/24 15:03:31 sirkitree Exp $
3
4 /**
5 * @file
6 * Enables users to comment on published content.
7 *
8 * When enabled, the Drupal comment module creates a discussion
9 * board for each Drupal node. Users can post comments to discuss
10 * a forum topic, weblog post, story, collaborative book page, etc.
11 */
12
13 /*
14 * Constants to define a comment's published state
15 */
16 define('COMMENT_PUBLISHED', 0);
17 define('COMMENT_NOT_PUBLISHED', 1);
18
19 /**
20 * Constants to define the viewing modes for comment listings
21 */
22 define('COMMENT_MODE_FLAT_COLLAPSED', 1);
23 define('COMMENT_MODE_FLAT_EXPANDED', 2);
24 define('COMMENT_MODE_THREADED_COLLAPSED', 3);
25 define('COMMENT_MODE_THREADED_EXPANDED', 4);
26
27 /**
28 * Constants to define the viewing orders for comment listings
29 */
30 define('COMMENT_ORDER_NEWEST_FIRST', 1);
31 define('COMMENT_ORDER_OLDEST_FIRST', 2);
32
33 /**
34 * Constants to define the position of the comment controls
35 */
36 define('COMMENT_CONTROLS_ABOVE', 0);
37 define('COMMENT_CONTROLS_BELOW', 1);
38 define('COMMENT_CONTROLS_ABOVE_BELOW', 2);
39 define('COMMENT_CONTROLS_HIDDEN', 3);
40
41 /**
42 * Constants to define the anonymous poster contact handling
43 */
44 define('COMMENT_ANONYMOUS_MAYNOT_CONTACT', 0);
45 define('COMMENT_ANONYMOUS_MAY_CONTACT', 1);
46 define('COMMENT_ANONYMOUS_MUST_CONTACT', 2);
47
48 /**
49 * Constants to define the comment form location
50 */
51 define('COMMENT_FORM_SEPARATE_PAGE', 0);
52 define('COMMENT_FORM_BELOW', 1);
53
54 /**
55 * Constants to define a node's comment state
56 */
57 define('COMMENT_NODE_DISABLED', 0);
58 define('COMMENT_NODE_READ_ONLY', 1);
59 define('COMMENT_NODE_READ_WRITE', 2);
60
61 /**
62 * Constants to define if comment preview is optional or required
63 */
64 define('COMMENT_PREVIEW_OPTIONAL', 0);
65 define('COMMENT_PREVIEW_REQUIRED', 1);
66
67 /**
68 * Implementation of hook_help().
69 */
70 function nodecomment_help($path, $arg) {
71 switch ($path) {
72 case 'admin/help#nodecomment':
73 $output = '<p>'. t('The comment module creates a discussion board for each post. Users can post comments to discuss a forum topic, weblog post, story, collaborative book page, etc. The ability to comment is an important part of involving members in a community dialogue.') .'</p>';
74 $output .= '<p>'. t('An administrator can give comment permissions to user groups, and users can (optionally) edit their last comment, assuming no others have been posted since. 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. Comments behave like other user submissions. Filters, smileys and HTML that work in nodes will also work with comments. The comment module provides specific features to inform site members when new comments have been posted.') .'</p>';
75 $output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@comment">Comment page</a>.', array('@comment' => 'http://drupal.org/handbook/modules/comment/')) .'</p>';
76 return $output;
77 }
78 }
79
80 /**
81 * Implementation of hook_menu().
82 */
83 function nodecomment_menu() {
84 $items = array();
85
86 $items['admin/settings/nodecomment'] = array(
87 'title' => 'Comments',
88 'page callback' => 'drupal_get_form',
89 'page arguments' => array('nodecomment_admin_settings'),
90 'access arguments' => array('administer comments'),
91 'description' => "Administer your site's comment settings.",
92 );
93
94 $items['node/%node/%node'] = array(
95 'title' => 'View',
96 'page callback' => 'node_page_view',
97 'type' => MENU_CALLBACK,
98 );
99
100 return $items;
101 }
102
103 /**
104 * Implementation of hook_perm().
105 */
106 function nodecomment_perm() {
107 return array(
108 'access comments',
109 'post comments',
110 'administer comments',
111 'post comments without approval'
112 );
113 }
114
115
116 /**
117 * Menu callback; presents the comment settings page.
118 */
119 function nodecomment_admin_settings() {
120 $form['posting_settings'] = array(
121 '#type' => 'fieldset',
122 '#title' => t('Posting settings'),
123 '#collapsible' => FALSE,
124 '#collapsed' => FALSE,
125 );
126
127 $form['posting_settings']['comment_anonymous'] = array(
128 '#type' => 'radios',
129 '#title' => t('Anonymous commenting'),
130 '#default_value' => variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT),
131 '#options' => array(
132 COMMENT_ANONYMOUS_MAYNOT_CONTACT => t('Anonymous posters may not enter their contact information'),
133 COMMENT_ANONYMOUS_MAY_CONTACT => t('Anonymous posters may leave their contact information'),
134 COMMENT_ANONYMOUS_MUST_CONTACT => t('Anonymous posters must leave their contact information')),
135 '#description' => t('This option is enabled when anonymous users have permission to post comments on the <a href="@url">permissions page</a>.', array('@url' => url('admin/user/access'))),
136 );
137 if (!user_access('post comments', user_load(array('uid' => 0)))) {
138 $form['posting_settings']['comment_anonymous']['#disabled'] = TRUE;
139 }
140
141 $form['posting_settings']['comment_preview'] = array(
142 '#type' => 'radios',
143 '#title' => t('Preview comment'),
144 '#default_value' => variable_get('comment_preview', COMMENT_PREVIEW_REQUIRED),
145 '#options' => array(t('Optional'), t('Required')),
146 );
147
148 $form['posting_settings']['comment_form_location'] = array(
149 '#type' => 'radios',
150 '#title' => t('Location of comment submission form'),
151 '#default_value' => variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE),
152 '#options' => array(t('Display on separate page'), t('Display below post or comments')),
153 );
154
155 $form['posting_settings']['default_comment_type'] = array(
156 '#type' => 'select',
157 '#title' => t('Default node type for comments'),
158 '#default_value' => variable_get('default_comment_type', ''),
159 '#options' => node_get_types('names'),
160 '#description' => t('The default node type to use for posting comments.'),
161 );
162
163 return system_settings_form($form);
164 }
165
166 /**
167 * Implementation of hook_form_alter().
168 */
169 function nodecomment_form_alter(&$form, $form_state, $form_id) {
170 global $user;
171
172 if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
173 $none = array('' => '-- None --');
174 $form['workflow']['comment'] = array(
175 '#type' => 'radios',
176 '#title' => t('Default comment setting'),
177 '#default_value' => variable_get('comment_'. $form['#node_type']->type, COMMENT_NODE_READ_WRITE),
178 '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')),
179 '#description' => t('Users with the <em>administer comments</em> permission will be able to override this setting.'),
180 );
181 $form['workflow']['comment_type'] = array(
182 '#type' => 'select',
183 '#title' => t('Node type for comments'),
184 '#default_value' => variable_get('comment_type_'. $form['#node_type']->type, variable_get('default_comment_type', '')),
185 '#options' => $none + node_get_types('names'),
186 '#description' => t('The node type to use when commenting on this content.'),
187 );
188
189 $options = $none;
190 $default_views = views_get_all_views();
191 if (is_array($default_views)) {
192 foreach ($default_views as $key => $view) {
193 $options[$key] = $view->name;
194 }
195 }
196 $form['workflow']['comment_view'] = array(
197 '#type' => 'select',
198 '#title' => t('Comment view'),
199 '#options' => $options,
200 '#description' => t('The view to use when dislaying comments for this node type.'),
201 '#default_value' => variable_get('comment_view_'. $form['#node_type']->type, 'node_comments'),
202 );
203
204 $form['#validate'] += array('nodecomment_comment_type_validate' => array());
205 }
206 elseif (isset($form['type'])) {
207 if ($form['type']['#value'] .'_node_form' == $form_id) {
208 $node = $form['#node'];
209
210 $is_reply = (arg(0) == 'node' && arg(1) == 'add' && is_numeric(arg(3)));
211 // We're altering a comment form, not a traditional node/add/type
212 if ($node->comment_target_nid) {
213 $form['comment_target_nid'] = array(
214 '#type' => 'value',
215 '#value' => $node->comment_target_nid,
216 );
217 if (isset($node->comment_target_cid)) {
218 $form['comment_target_cid'] = array(
219 '#type' => 'value',
220 '#value' => $node->comment_target_cid,
221 );
222 }
223
224 $anon_meta_info = variable_get('comment_anonymous', COMMENT_ANONYMOUS_MAYNOT_CONTACT);
225 if ($user->uid == 0 && ($anon_meta_info == COMMENT_ANONYMOUS_MAY_CONTACT || $anon_meta_info == COMMENT_ANONYMOUS_MUST_CONTACT)) {
226 $form['comment_info'] = array('#weight' => -10);
227 $form['comment_info']['name'] = array(
228 '#type' => 'textfield',
229 '#title' => t('Your name'),
230 '#maxlength' => 60,
231 '#size' => 30,
232 '#default_value' => $node->name ? $node->name : variable_get('anonymous', t('Anonymous')),
233 '#required' => ($anon_meta_info == COMMENT_ANONYMOUS_MUST_CONTACT)
234 );
235
236 $form['comment_info']['mail'] = array(
237 '#type' => 'textfield',
238 '#title' => t('E-mail'),
239 '#maxlength' => 64,
240 '#size' => 30,
241 '#default_value' => $node->mail,
242 '#description' => t('The content of this field is kept private and will not be shown publicly.'),
243 '#required' => ($anon_meta_info == COMMENT_ANONYMOUS_MUST_CONTACT)
244 );
245
246 $form['comment_info']['homepage'] = array(
247 '#type' => 'textfield',
248 '#title' => t('Homepage'),
249 '#maxlength' => 255,
250 '#size' => 30,
251 '#default_value' => $node->homepage,
252 '#required' => ($anon_meta_info == COMMENT_ANONYMOUS_MUST_CONTACT)
253 );
254 }
255
256 // add in the user's sig, if any as default content
257 if ($user->signature && !$form['body_filter']['body']['#default_value']) {
258 $form['body_filter']['body']['#default_value'] = "\n\n\n--\n" . $user->signature;
259 }
260
261 $form['#redirect'] = 'node/'. $node->comment_target_nid;
262 }
263 elseif ($is_reply) {
264 // This is the case of someone having clicked a "reply" link.
265 // The first task in this case is to indicate that this node should have
266 // a parent node since it is supposed to be a comment.
267 $parent_nid = is_numeric(arg(4)) ? arg(4) : arg(3);
268 $target_node = node_load($parent_nid);
269 $form['#node']->comment_target_nid = arg(3);
270
271 // If the reply link belonged to a comment node, get that node's id as well.
272 if (is_numeric(arg(4))) {
273 $form['#node']->comment_target_cid = arg(4);
274 }
275
276 // Always show the node to which this comment is replying
277 $form['#prefix'] .= node_view($target_node);
278
279 // now we send it back to nodecomment_form_alter and let it be handled as a comment.
280 return nodecomment_form_alter($form, $form_state, $form_id);
281 }
282 // Just a normal node: turn on the comment control settings.
283 else {
284 $form['comment_settings'] = array(
285 '#type' => 'fieldset',
286 '#access' => user_access('administer comments'),
287 '#title' => t('Comment settings'),
288 '#collapsible' => TRUE,
289 '#collapsed' => TRUE,
290 '#weight' => 30,
291 );
292 $form['comment_settings']['comment'] = array(
293 '#type' => 'radios',
294 '#parents' => array('comment'),
295 '#default_value' => $node->comment,
296 '#options' => array(t('Disabled'), t('Read only'), t('Read/Write')),
297 );
298 }
299 }
300 }
301 elseif ($form_id == 'system_modules') {
302 // Prevent comment module from being enabled.
303 $form['status']['#process']['nodecomment_disable_comment_module'] = array();
304 }
305 }
306
307 function nodecomment_comment_type_validate($form_id, $form_values) {
308 // if comments are enabled
309 if ($form_values['comment'] > 0) {
310 // make sure a comment_type is chosen
311 if (!$form_values['comment_type']) {
312 form_set_error('comment_type', 'You must choose a comment type.');
313 }
314 if (!$form_values['comment_view']) {
315 form_set_error('comment_view', 'You must choose a comment view.');
316 }
317 }
318 }
319
320 /**
321 * Disables the comment module checkbox so it can't be selected.
322 */
323 function nodecomment_disable_comment_module($form, $edit) {
324 $form['comment']['#default_value'] = 0;
325 $form['comment']['#attributes']['disabled'] = 'disabled';
326 return $form;
327 }
328
329
330 if (!function_exists('comment_nodeapi')) {
331 function comment_nodeapi(&$node, $op, $arg = 0) {
332 return nodecomment_nodeapi($node, $op, $arg);
333 }
334 }
335
336 /**
337 * Implementation of hook_user().
338 *
339 * Provides signature customization for the user's comments.
340 */
341 function nodecomment_user($type, $edit, &$user, $category = NULL) {
342 if ($type == 'form' && $category == 'account') {
343 // when user tries to edit his own data
344 $form['nodecomment_settings'] = array(
345 '#type' => 'fieldset',
346 '#title' => t('Comment settings'),
347 '#collapsible' => TRUE,
348 '#weight' => 4);
349 $form['nodecomment_settings']['signature'] = array(
350 '#type' => 'textarea',
351 '#title' => t('Signature'),
352 '#default_value' => $edit['signature'],
353 '#description' => t('Your signature will be publicly displayed at the end of your comments.'));
354
355 return $form;
356 }
357 }
358
359 /**
360 * Implementation of hook_nodeapi().
361 */
362 function nodecomment_nodeapi(&$node, $op, $arg = 0) {
363 // When the node HAS comments
364 // -- delete the comments
365 // -- update node_comment_statistics
366 // When the node IS a comment
367 // -- delete any children comments
368 // -- update node_comment_statistics for the parent node
369
370
371 switch ($op) {
372 case 'load':
373 $node->comment_type = variable_get('comment_type_'. $node->type, variable_get('default_comment_type', ''));
374 $comment_data = db_fetch_array(db_query('SELECT * FROM {node_comments} nc WHERE nc.cid = %d', $node->nid));
375 if ($comment_data['cid']) {
376 // It's a comment! Populate commenty stuff.
377 $comment_data['comment_target_nid'] = $comment_data['nid'];
378 unset($comment_data['nid']);
379 return $comment_data;
380 }
381 else {
382 // It's not a comment, so get its comment stats
383 return db_fetch_array(db_query("SELECT last_comment_timestamp, last_comment_name, comment_count FROM {node_comment_statistics} WHERE nid = %d", $node->nid));
384 }
385 break;
386
387 case 'prepare':
388 if (!isset($node->comment)) {
389 $node->comment = variable_get("comment_$node->type", COMMENT_NODE_READ_WRITE);
390 }
391 break;
392
393 case 'insert':
394 // if this is a comment, save it as a comment
395 if (isset($node->comment_target_nid)) {
396 nodecomment_save($node);
397 }
398 // otherwise, update it's comment statistics.
399 else {
400 db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, %d)', $node->nid, $node->created, $node->uid, 0);
401 }
402 break;
403
404 case 'delete':
405 // if this is a comment, delete it and its children comments
406 if (isset($node->comment_target_nid)) {
407 // TODO: Check to see whether this works
408 _nodecomment_delete_thread($node);
409 _nodecomment_update_node_statistics($node->comment_target_nid);
410 }
411 // otherwise, delete its children comments.
412 else {
413 // get all the comments that are owned by this node
414 $result = db_query('SELECT cid FROM {node_comments} WHERE nid = %d', $node->nid);
415 while ($row = db_fetch_object($result)) {
416 node_delete($row->cid);
417 }
418 db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
419 db_query('DELETE FROM {node_comments} WHERE nid = %d', $node->nid);
420 }
421
422 break;
423 }
424 }
425
426 /**
427 * Accepts a submission of new or changed comment content.
428 *
429 * @param $node
430 * The node that is serving as a comment to another node.
431 *
432 * @return
433 * If the comment is successfully saved the node ID of the comment is returned. If the comment
434 * is not saved, FALSE is returned.
435 */
436 function nodecomment_save($node) {
437 global $user;
438
439 if ($node->uid === $user->uid) { // '===' because we want to modify anonymous users too
440 $node->name = $user->name;
441 }
442
443 $node->thread = nodecomment_get_thread($node);
444
445 db_query("INSERT INTO {node_comments} ".
446 "(cid, nid, pid, hostname, thread, name, uid, mail, homepage)".
447 "VALUES (%d, %d, %d, '%s', '%s', '%s', %d, '%s', '%s')",
448 $node->nid, $node->comment_target_nid, $node->comment_target_cid, $_SERVER['REMOTE_ADDR'], $node->thread, $node->name, $node->uid, $node->mail, $node->homepage);
449
450 _nodecomment_update_node_statistics($node->comment_target_nid);
451
452 // Explain the approval queue if necessary, and then
453 // redirect the user to the node he's commenting on.
454 if ($node->moderate == 1) {
455 drupal_set_message(t('Your comment has been queued for moderation by site administrators and will be published after approval.'));
456 }
457 return $node->nid;
458 }
459
460 function nodecomment_form($node) {
461 $comment_type = variable_get('comment_type_'. $node->type, variable_get('default_comment_type', ''));
462 if ($comment_type) {
463 global $user;
464 $new_node = array(
465 'uid' => $user->uid,
466 'name' => $user->name,
467 'type' => $comment_type,
468 'comment_target_nid' => $node->nid,
469 );
470 require_once drupal_get_path('module', 'node') . '/node.pages.inc';
471 return drupal_get_form($comment_type .'_node_form', $new_node);
472 }
473 }
474
475
476 /**
477 * Implementation of hook_link().
478 */
479 function nodecomment_link($type, $node = NULL, $teaser = FALSE) {
480 global $user;
481 $links = array();
482
483 if ($type == 'node') {
484 if (isset($node->comment_target_nid)) {
485 // This node is a comment to a parent node
486 if ($teaser) {
487 $links = nodecomment_links($node, 0);
488 }
489 else {
490 $links = nodecomment_links($node, $teaser);
491 }
492 }
493 // can this node have comments?
494 elseif (variable_get('comment_'. $node->type, COMMENT_NODE_READ_WRITE)) {
495 // this node can have comments.
496 if ($teaser) {
497 // Main page: display the number of comments that have been posted.
498 if (user_access('access comments')) {
499 $all = nodecomment_num_all($node->nid);
500 $new = nodecomment_num_new($node->nid);
501
502 if ($all) {
503 $links['comment_comments'] = array(
504 'title' => format_plural($all, '1 comment', '@count comments'),
505 'href' => "node/$node->nid",
506 'attributes' => array('title' => t('Jump to the first comment of this posting.')),
507 'fragment' => 'comments'
508 );
509
510 if ($new) {
511 $links['comment_new_comments'] = array(
512 'title' => format_plural($new, '1 new comment', '@count new comments'),
513 'href' => "node/$node->nid",
514 'attributes' => array('title' => t('Jump to the first new comment of this posting.')),
515 'fragment' => 'new'
516 );
517 }
518 }
519 }
520 }
521 // This node needs an Add new comment link
522 $comment_type = variable_get('comment_type_'. $node->type, variable_get('default_comment_type', ''));
523 if ($comment_type && user_access("create $comment_type content")) {
524 $links['comment_add'] = array(
525 'title' => t('Add new @comment_type', array('@comment_type' => node_get_types('name', $comment_type))),
526 'attributes' => array('title' => t('Add a new comment to this page.')),
527 );
528 if (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == 1) {
529 $links['comment_add']['href'] = "node/$node->nid";
530 $links['comment_add']['fragment'] = 'node-form';
531 }
532 else {
533 $links['comment_add']['href'] = "node/add/". str_replace('_', '-', $comment_type) ."/". $node->nid;
534 }
535 }
536 else if ($user->uid == 0) {
537 // Show anonymous users the chance to login or register
538 // we cannot use drupal_get_destination() because these links sometimes appear on /node and taxo listing pages
539 if (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
540 // TODO: This is wrong and has to be addressed with the whole separate page business.
541 $destination = "destination=". drupal_urlencode("node/$node->nid#nodecomment_form");
542 }
543 else {
544 $destination = "destination=". drupal_urlencode("node/$node->nid#nodecomment_form");
545 }
546
547 $links['login_register']['html'] = TRUE;
548 if (variable_get('user_register', 1)) {
549 $links['login_register']['title'] = t('<a href="@login">login</a> or <a href="@register">register</a> to post comments', array('@login' => url('user/login', array('query' => $destination)), '@register' => url('user/register', array('query' => $destination))));
550 }
551 else {
552 $links['login_register']['title'] = t('<a href="@login">login</a> to post comments', array('@login' => url('user/login', array('query' => $destination))));
553 }
554 }
555 }
556 }
557
558 return $links;
559 }
560
561
562 function nodecomment_links($comment, $return = 1) {
563 global $user;
564
565 $links = array();
566
567 // If we are viewing just this comment, we link back to the node.
568 if ($return) {
569 $links['comment_parent'] = array(
570 'title' => t('parent'),
571 'href' => arg(0) .'/'. arg(1),
572 'fragment' => "comment-". $comment->nid,
573 );
574 }
575
576 if (node_comment_mode($comment->comment_target_nid) == COMMENT_NODE_READ_WRITE) {
577 if (node_access('update', $comment)) {
578 $links['comment_edit'] = array(
579 'title' => t('edit'),
580 'href' => "node/". $comment->cid ."/edit",
581 );
582 }
583 if (node_access('delete', $comment)) {
584 $links['comment_delete'] = array(
585 'title' => t('delete'),
586 'href' => "node/". $comment->cid ."/delete",
587 );
588 }
589 if (node_access('create', $comment)) {
590 $links['comment_reply'] = array(
591 'title' => t('reply'),
592 'href' => "node/add/". str_replace('_', '-', $comment->type) ."/". $comment->comment_target_nid ."/". $comment->nid,
593 );
594 }
595 }
596
597 return $links;
598 }
599
600 if (!function_exists('comment_render')) {
601 function comment_render($node, $cid = 0) {
602 return nodecomment_render($node, $cid);
603 }
604 }
605
606 function nodecomment_render($node, $cid = 0) {
607 global $user;
608
609 if (user_access('access comments')) {
610 // Pre-process variables.
611 $nid = $node->nid;
612 if (empty($nid)) {
613 $nid = 0;
614 }
615
616 if (is_numeric($cid)) {
617 // Single comment view.
618 if ($comment = node_load($cid)) {
619 $output = theme('node', $comment, TRUE, TRUE);
620 }
621 }
622 else {
623 $view_name = variable_get('comment_view_'. $node->type, 'node_comments');
624 if ($view_name) {
625 $output = views_embed_view($view_name, 'default', array($nid));
626 }
627 }
628
629 // If enabled, show new comment form.
630 $comment_type = variable_get('comment_type_'. $node->type, variable_get('default_comment_type', ''));
631 if (user_access("create $comment_type content") && user_access('post comments') && node_comment_mode($nid) == COMMENT_NODE_READ_WRITE && (variable_get('comment_form_location', COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_BELOW)) {
632 // There is likely a cleaner way to do this, but for now it will have to do. -- JE
633 $friendly_name = node_get_types('name', $comment_type);
634 $output .= nodecomment_form_box($node, t('Post new !type', array('!type' => $friendly_name)));
635 }
636
637 if ($output) {
638 $output = theme('nodecomment_wrapper', $output, $node);
639 }
640 }
641
642 return $output;
643 }
644
645 /**
646 * misc functions: helpers, privates, history
647 */
648
649 function nodecomment_num_all($nid) {
650 static $cache;
651
652 if (!isset($cache[$nid])) {
653 $cache[$nid] = db_result(db_query('SELECT comment_count FROM {node_comment_statistics} WHERE nid = %d', $nid));
654 }
655 return $cache[$nid];
656 }
657
658 if (!function_exists('comment_num_new')) {
659 function comment_num_new($nid) {
660 return nodecomment_num_new($nid);
661 }
662 }
663
664 /**
665 * get number of new comments for current user and specified node
666 *
667 * @param $nid node-id to count comments for
668 * @param $timestamp time to count from (defaults to time of last user access
669 * to node)
670 */
671 function nodecomment_num_new($nid, $timestamp = 0) {
672 global $user;
673
674 if ($user->uid) {
675 // Retrieve the timestamp at which the current user last viewed the
676 // specified node.
677 if (!$timestamp) {
678 $timestamp = node_last_viewed($nid);
679 }
680 $timestamp = ($timestamp > NODE_NEW_LIMIT ? $timestamp : NODE_NEW_LIMIT);
681
682 // Use the timestamp to retrieve the number of new comments.
683 $result = db_result(db_query('SELECT COUNT(cn.nid) FROM {node} n INNER JOIN {node_comments} c ON n.nid = c.nid INNER JOIN {node} cn ON c.cid = cn.nid WHERE n.nid = %d AND (cn.created > %d OR cn.changed > %d) AND cn.status = %d', $nid, $timestamp, $timestamp, 1));
684
685 return $result;
686 }
687 else {
688 return 0;
689 }
690
691 }
692
693 function nodecomment_form_box($node, $title = NULL) {
694 return theme('box', $title, nodecomment_form($node));
695 }
696
697 function _nodecomment_delete_thread($comment) {
698 if (!is_object($comment) || !is_numeric($comment->cid)) {
699 watchdog('content', 'Can not delete non-existent comment.', WATCHDOG_WARNING);
700 return;
701 }
702
703 // Delete the comment:
704 db_query('DELETE FROM {node_comments} WHERE cid = %d', $comment->cid);
705
706
707 // Delete the comment's replies
708 $result = db_query('SELECT c.* FROM {node_comments} c WHERE pid = %d', $comment->nid);
709 while ($comment = db_fetch_object($result)) {
710 $comment->name = $comment->name;
711 _nodecomment_delete_thread($comment);
712 }
713 }
714
715 /**
716 * Return an array of viewing modes for comment listings.
717 *
718 * We can't use a global variable array because the locale system
719 * is not initialized yet when the comment module is loaded.
720 */
721 function _nodecomment_get_modes() {
722 return array(
723 COMMENT_MODE_FLAT_COLLAPSED => t('Flat list - collapsed'),
724 COMMENT_MODE_FLAT_EXPANDED => t('Flat list - expanded'),
725 COMMENT_MODE_THREADED_COLLAPSED => t('Threaded list - collapsed'),
726 COMMENT_MODE_THREADED_EXPANDED => t('Threaded list - expanded')
727 );
728 }
729
730 /**
731 * Return an array of viewing orders for comment listings.
732 *
733 * We can't use a global variable array because the locale system
734 * is not initialized yet when the comment module is loaded.
735 */
736 function _nodecomment_get_orders() {
737 return array(
738 COMMENT_ORDER_NEWEST_FIRST => t('Date - newest first'),
739 COMMENT_ORDER_OLDEST_FIRST => t('Date - oldest first')
740 );
741 }
742
743 /**
744 * Return an array of "comments per page" settings from which the user
745 * can choose.
746 */
747 function _nodecomment_per_page() {
748 return drupal_map_assoc(array(10, 30, 50, 70, 90, 150, 200, 250, 300));
749 }
750
751
752 /**
753 * Updates the comment statistics for a given node. This should be called any
754 * time a comment is added, deleted, or updated.
755 *
756 * The following fields are contained in the node_comment_statistics table.
757 * - last_comment_timestamp: the timestamp of the last comment for this node or the node create stamp if no comments exist for the node.
758 * - last_comment_name: the name of the anonymous poster for the last comment
759 * - last_comment_uid: the uid of the poster for the last comment for this node or the node authors uid if no comments exists for the node.
760 * - comment_count: the total number of approved/published comments on this node.
761 */
762 function _nodecomment_update_node_statistics($nid) {
763 $count = db_result(db_query('SELECT COUNT(*) FROM {node_comments} nc INNER JOIN {node} n ON n.nid = nc.nid WHERE nc.nid = %d AND n.status = %d', $nid, 1));
764
765 // comments exist
766 if ($count > 0) {
767 $last_reply = db_fetch_object(db_query_range('SELECT nc.cid, nc.name, n.created, n.changed, n.uid FROM {node} n LEFT JOIN {node_comments} nc on n.nid = nc.cid WHERE nc.nid = %d AND n.status = 1 ORDER BY cid DESC', $nid, 1, 0, 1));
768 db_query("UPDATE {node_comment_statistics} SET comment_count = %d, last_comment_timestamp = %d, last_comment_name = '%s', last_comment_uid = %d WHERE nid = %d",
769 $count,
770 max($last_reply->created, $last_reply->changed),
771 $last_reply->uid ? '' : $last_reply->name,
772 $last_reply->uid, $nid);
773 }
774
775 // no comments
776 else {
777 $node = db_fetch_object(db_query("SELECT uid, created FROM {node} WHERE nid = %d", $nid));
778 db_query("UPDATE {node_comment_statistics} SET comment_count = 0, last_comment_timestamp = %d, last_comment_name = '', last_comment_uid = %d WHERE nid = %d", $node->created, $node->uid, $nid);
779 }
780 }
781
782 if (!function_exists('comment_theme')) {
783 function comment_theme() {
784 return nodecomment_theme();
785 }
786 }
787
788 function nodecomment_theme() {
789 return array(
790 'nodecomment_wrapper' => array(
791 'template' => 'nodecomment-wrapper',
792 'arguments' => array('content' => NULL, 'node' => NULL),
793 ),
794 );
795 }
796
797 /**
798 * Allow themable wrapping of all comments.
799 */
800 function theme_nodecomment_wrapper($content, $node) {
801 return '<div id="comments">'. $content .'</div>';
802 }
803
804 function theme_nodecomment($comment, $links = array()) {
805 $output = '<div class="comment'. ($comment->status == COMMENT_NOT_PUBLISHED ? ' comment-unpublished' : '') .'">';
806 $output .= '<div class="subject">'. l($comment->subject, $_GET['q'], NULL, NULL, "comment-$comment->cid") .' '. theme('mark', $comment->new) ."</div>\n";
807 $output .= '<div class="credit">'. t('by %a on %b', array('%a' => theme('username', $comment), '%b' => format_date($comment->timestamp))) ."</div>\n";
808 $output .= '<div class="body">'. $comment->comment .'</div>';
809 $output .= '<div class="links">'. theme('links', $links) .'</div>';
810 $output .= '</div>';
811 return $output;
812 }
813
814 function nodecomment_get_thread($node) {
815 // Here we are building the thread field. See the documentation for
816 // comment_render().
817 if ($node->comment_target_cid == 0) {
818 // This is a comment with no parent comment (depth 0): we start
819 // by retrieving the maximum thread level.
820 $max = db_result(db_query('SELECT MAX(thread) FROM {node_comments} WHERE nid = %d', $node->comment_target_nid));
821
822 // Strip the "/" from the end of the thread.
823 $max = rtrim($max, '/');
824
825 // Finally, build the thread field for this new comment.
826 $thread = nodecomment_int2vancode(nodecomment_vancode2int($max) + 1) .'/';
827 }
828 else {
829 // This is comment with a parent comment: we increase
830 // the part of the thread value at the proper depth.
831
832 // Get the parent comment:
833 $parent = node_load($node->comment_target_cid);
834
835 // Strip the "/" from the end of the parent thread.
836 $parent->thread = (string) rtrim((string) $parent->thread, '/');
837
838 // Get the max value in _this_ thread.
839 $max = db_result(db_query("SELECT MAX(thread) FROM {node_comments} WHERE thread LIKE '%s.%%' AND nid = %d", $parent->thread, $node->comment_target_nid));
840
841 if ($max == '') {
842 // First child of this parent.
843 $thread = $parent->thread .'.'. nodecomment_int2vancode(0) .'/';
844 }
845 else {
846 // Strip the "/" at the end of the thread.
847 $max = rtrim($max, '/');
848
849 // We need to get the value at the correct depth.
850 $parts = explode('.', $max);
851 $parent_depth = count(explode('.', $parent->thread));
852 $last = $parts[$parent_depth];
853
854 // Finally, build the thread field for this new comment.
855 $thread = $parent->thread .'.'. nodecomment_int2vancode(nodecomment_vancode2int($last) + 1) .'/';
856 }
857 }
858 return $thread;
859 }
860
861
862 /** Copies of comment module's vancode helper functions **/
863
864 /**
865 * Generate vancode.
866 *
867 * Consists of a leading character indicating length, followed by N digits
868 * with a numerical value in base 36. Vancodes can be sorted as strings
869 * without messing up numerical order.
870 *
871 * It goes:
872 * 00, 01, 02, ..., 0y, 0z,
873 * 110, 111, ... , 1zy, 1zz,
874 * 2100, 2101, ..., 2zzy, 2zzz,
875 * 31000, 31001, ...
876 */
877 function nodecomment_int2vancode($i = 0) {
878 $num = base_convert((int)$i, 10, 36);
879 $length = strlen($num);
880 return chr($length + ord('0') - 1) . $num;
881 }
882
883 /**
884 * Decode vancode back to an integer.
885 */
886 function nodecomment_vancode2int($c = '00') {
887 return base_convert(substr($c, 1), 36, 10);
888 }

  ViewVC Help
Powered by ViewVC 1.1.2