Same name and namespace in other branches
  1. 4.7.x modules/comment.module \comment_render()
  2. 5.x modules/comment/comment.module \comment_render()
  3. 6.x modules/comment/comment.module \comment_render()
1 call to comment_render()
node_show in modules/node.module
Generate a page displaying a single node, along with its comments.

File

modules/comment.module, line 711
Enables users to comment on published content.

Code

function comment_render($node, $cid = 0) {
  global $user;
  $mode = $_GET['mode'];
  $order = $_GET['order'];
  $threshold = $_GET['threshold'];
  $comments_per_page = $_GET['comments_per_page'];
  $comment_page = $_GET['comment_page'];
  $output = '';
  if (user_access('access comments')) {

    // Pre-process variables.
    $nid = $node->nid;
    if (empty($nid)) {
      $nid = 0;
    }
    if (empty($mode)) {
      $mode = $user->mode ? $user->mode : ($_SESSION['comment_mode'] ? $_SESSION['comment_mode'] : variable_get('comment_default_mode', 4));
    }
    if (empty($order)) {
      $order = $user->sort ? $user->sort : ($_SESSION['comment_sort'] ? $_SESSION['comment_sort'] : variable_get('comment_default_order', 1));
    }
    if (empty($threshold)) {
      $threshold = $user->threshold ? $user->threshold : ($_SESSION['comment_threshold'] ? $_SESSION['comment_threshold'] : variable_get('comment_default_threshold', 0));
    }
    $threshold_min = db_result(db_query('SELECT minimum FROM {moderation_filters} WHERE fid = %d', $threshold));
    if (empty($comments_per_page)) {
      $comments_per_page = $user->comments_per_page ? $user->comments_per_page : ($_SESSION['comment_comments_per_page'] ? $_SESSION['comment_comments_per_page'] : variable_get('comment_default_per_page', '50'));
    }
    $output .= "<a id=\"comment\"></a>\n";
    if ($cid) {

      // Single comment view.
      $output .= '<form method="post" action="' . url('comment') . "\"><div>\n";
      $output .= form_hidden('nid', $nid);
      $result = db_query('SELECT c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, 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.format, c.timestamp, c.name, c.mail, u.picture, c.homepage, u.uid, u.name, u.picture, u.data, c.score, c.users', $cid);
      if ($comment = db_fetch_object($result)) {
        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
        $output .= theme('comment_view', $comment, theme('links', module_invoke_all('link', 'comment', $comment, 1)));
      }
      if (comment_user_can_moderate($node) && $user->uid != $comment->uid && !comment_already_moderated($user->uid, $comment->users)) {
        $output .= '<div style="text-align: center;">' . form_submit(t('Moderate comment')) . '</div><br />';
      }
      $output .= '</div>' . form_token() . '</form>';
    }
    else {

      // Multiple comment view
      $query .= "SELECT c.cid as cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name , c.mail, c.homepage, u.uid, u.name AS registered_name, u.picture, u.data, c.score, c.users, c.thread FROM {comments} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.nid = %d AND c.status = 0";
      $query .= ' GROUP BY c.cid, c.pid, c.nid, c.subject, c.comment, c.format, c.timestamp, c.name, c.mail, u.picture, c.homepage, u.uid, u.name, u.picture, u.data, c.score, c.users, c.thread';

      /*
       ** 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.
       */
      if ($order == 1) {
        if ($mode == 1 || $mode == 2) {
          $query .= ' ORDER BY c.timestamp DESC';
        }
        else {
          $query .= ' ORDER BY c.thread DESC';
        }
      }
      else {
        if ($order == 2) {
          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))';
          }
        }
      }

      // Start a form, for use with comment control and moderation.
      $result = pager_query($query, $comments_per_page, 0, "SELECT COUNT(*) FROM {comments} WHERE status = 0 AND nid = %d", $nid);
      if (db_num_rows($result) && (variable_get('comment_controls', 3) == 0 || variable_get('comment_controls', 3) == 2)) {
        $output .= '<form method="post" action="' . url('comment') . "\"><div>\n";
        $output .= theme('comment_controls', $threshold, $mode, $order, $comments_per_page);
        $output .= form_hidden('nid', $nid);
        $output .= '</div>' . form_token() . '</form>';
      }
      $output .= '<form method="post" action="' . url('comment') . "\"><div>\n";
      $output .= form_hidden('nid', $nid);
      while ($comment = db_fetch_object($result)) {
        $comment = drupal_unpack($comment);
        $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
        $comment->depth = count(explode('.', $comment->thread)) - 1;
        if ($mode == 1) {
          $output .= theme('comment_flat_collapsed', $comment, $threshold_min);
        }
        else {
          if ($mode == 2) {
            $output .= theme('comment_flat_expanded', $comment, $threshold_min);
          }
          else {
            if ($mode == 3) {
              $output .= theme('comment_thread_min', $comment, $threshold_min);
            }
            else {
              if ($mode == 4) {
                $output .= theme('comment_thread_max', $comment, $threshold_min);
              }
            }
          }
        }
      }

      // Use the standard pager; $pager_total is the number of returned rows,
      // is global and defined in pager.inc.
      if ($pager = theme('pager', NULL, $comments_per_page, 0, array(
        'comments_per_page' => $comments_per_page,
      ))) {
        $output .= $pager;
      }
      if (db_num_rows($result) && comment_user_can_moderate($node)) {
        $output .= '<div id="comment-moderation-button">' . form_submit(t('Moderate comments')) . '</div>';
      }
      $output .= '</div>' . form_token() . '</form>';
      if (db_num_rows($result) && (variable_get('comment_controls', 3) == 1 || variable_get('comment_controls', 3) == 2)) {
        $output .= '<form method="post" action="' . url('comment') . "\"><div>\n";
        $output .= theme('comment_controls', $threshold, $mode, $order, $comments_per_page);
        $output .= form_hidden('nid', $nid);
        $output .= '</div>' . form_token() . '</form>';
      }
    }

    // If enabled, show new comment form.
    if (user_access('post comments') && node_comment_mode($nid) == 2 && variable_get('comment_form_location', 0)) {
      $output .= theme('comment_form', array(
        'nid' => $nid,
      ), t('Post new comment'));
    }
  }
  return $output;
}