diff --git modules/comment/comment.module modules/comment/comment.module index 84843ee..899c989 100644 --- modules/comment/comment.module +++ modules/comment/comment.module @@ -104,34 +104,18 @@ function comment_theme() { 'arguments' => array(), ), 'comment_preview' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1), - ), - 'comment_view' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array(), 'visible' => 1), + 'arguments' => array('comment' => NULL), ), 'comment' => array( 'template' => 'comment', - 'arguments' => array('comment' => NULL, 'node' => NULL, 'links' => array()), - ), - 'comment_form_box' => array( - 'arguments' => array('edit' => NULL, 'title' => NULL), - ), - 'comment_folded' => array( - 'template' => 'comment-folded', - 'arguments' => array('comment' => NULL, 'node' => NULL), - ), - 'comment_flat_expanded' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL), - ), - 'comment_thread_expanded' => array( - 'arguments' => array('comment' => NULL, 'node' => NULL), + 'arguments' => array('elements' => NULL), ), 'comment_post_forbidden' => array( 'arguments' => array('nid' => NULL), ), 'comment_wrapper' => array( 'template' => 'comment-wrapper', - 'arguments' => array('content' => NULL, 'node' => NULL), + 'arguments' => array('elements' => NULL), ), 'comment_submitted' => array( 'arguments' => array('comment' => NULL), @@ -168,10 +152,12 @@ function comment_menu() { 'access arguments' => array('administer comments'), 'type' => MENU_CALLBACK, ); - $items['comment/edit'] = array( + $items['comment/edit/%comment'] = array( 'title' => 'Edit comment', 'page callback' => 'comment_edit', - 'access arguments' => array('post comments'), + 'access callback' => 'comment_access', + 'page arguments' => array(2), + 'access arguments' => array('edit', 2), 'type' => MENU_CALLBACK, ); $items['comment/reply/%node'] = array( @@ -532,14 +518,306 @@ function comment_node_view($node, $build_mode) { '#attributes' => array('class' => 'links inline'), ); - // Append the list of comments to $node->content for node detail pages. - if ($node->comment && (bool)menu_get_object() && empty($node->in_preview)) { - $node->content['comments'] = array( - '#markup' => comment_render($node), - '#sorted' => TRUE, - ); + // Only append comments when we are building a node on its own node detail page. + $page_node = menu_get_object(); + if ($node->comment && isset($page_node->nid) && $page_node->nid == $node->nid && empty($node->in_preview) && user_access('access comments')) { + comment_node_page_additions($node); + } + } +} + +/** + * Add the comment-related elements to $node->content for node detail pages. + * + * @param $node + * A node object. + */ +function comment_node_page_additions(&$node) { + // Only attempt to render comments if the node has visible comments. + // Unpublished comments are not included in $node->comment_count, so show + // comments unconditionally if the user is an administrator. + if ($node->comment_count || user_access('administer comments')) { + if ($cids = comment_get_thread($node)) { + $comments = comment_load_multiple($cids); + comment_prepare_thread($comments); + $build = comment_build_multiple($comments); + $build['#attached_css'][] = drupal_get_path('module', 'comment') . '/comment.css'; + $build['pager']['#theme'] = 'pager'; + $build['#weight'] = 0; + $node->content['comments']['comments'] = $build; + } + } + + // Append comment form if needed. + if (user_access('post comments') && $node->comment == COMMENT_NODE_OPEN && (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW) == COMMENT_FORM_BELOW)) { + $build = drupal_get_form('comment_form', array('nid' => $node->nid)); + $build['#prefix'] = '

' . t('Post new comment') . '

'; + $build['#suffix'] = '
'; + $build['#weight'] = 1; + $node->content['comments']['comment_form'] = $build; + } + + if (isset($node->content['comments'])) { + $node->content['comments'] += array( + '#theme_wrapper' => 'comment_wrapper', + // Prepend 'Comments' heading if needed. + '#prefix' => '

' . t('Comments') . '

', + '#node' => $node, + ); + } +} + +/** + * Retrieve comment(s) for a thread. + * + * @param $node + * The node whose comment(s) needs rendering. + * + * To display threaded comments in the correct order we keep a 'thread' field + * and order by that value. This 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, the + * thread fields will look like this: + * + * 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. However this would + * spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need + * to consider the trailing "/" so we use a substring only. + */ + function comment_get_thread($node) { + $mode = _comment_get_display_setting('mode', $node); + $comments_per_page = _comment_get_display_setting('comments_per_page', $node); + + $query = db_select('comment', 'c')->extend('PagerDefault'); + $query->addField('c', 'cid'); + $query + ->condition('c.nid', $node->nid) + ->addTag('node_access') + ->limit($comments_per_page); + + $count_query = db_select('comment', 'c'); + $count_query->addExpression('COUNT(*)'); + $count_query + ->condition('c.nid', $node->nid) + ->addTag('node_access'); + + if (!user_access('administer comments')) { + $query->condition('c.status', COMMENT_PUBLISHED); + $count_query->condition('c.status', COMMENT_PUBLISHED); + } + if ($mode === COMMENT_MODE_FLAT) { + $query->orderBy('c.cid', 'ASC'); + } + else { + // See comment above. Analysis reveals that this doesn't cost too + // much. It scales much much better than having the whole comment + // structure. + $query->orderBy('SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))', 'ASC'); + } + + $query->setCountQuery($count_query); + $cids = $query->execute()->fetchCol(); + + return $cids; +} + +/** + * Loop over comment thread, noting indentation level. + * + * @param array $comments + * An array of comment objects, keyed by cid. + * @return + * The $comments argument is altered by reference with indentation information. + */ +function comment_prepare_thread(&$comments) { + // A flag stating if we are still searching for first new comment on the thread. + $first_new = TRUE; + + // A counter that helps track how indented we are. + $divs = 0; + + foreach ($comments as $key => $comment) { + if ($first_new && $comment->new != MARK_READ) { + // Assign the anchor only for the first new comment. This avoids duplicate + // id attributes on a page. + $first_new = FALSE; + $comment->first_new = TRUE; + } + + // The $divs element instructs #prefix whether to add an indent div or + // close existing divs (a negative value). + $comment->depth = count(explode('.', $comment->thread)) - 1; + if ($comment->depth > $divs) { + $comment->divs = 1; + $divs++; + } + else { + $comment->divs = $comment->depth - $divs; + while ($comment->depth < $divs) { + $divs--; + } } + $comments[$key] = $comment; } + + // The final comment must close up some hanging divs + $comments[$key]->divs_final = $divs; +} + +/** + * Generate an array for rendering the given comment. + * + * @param $comment + * A comment object. + * @param $build_mode + * Build mode, e.g. 'full', 'teaser'... + * + * @return + * An array as expected by drupal_render(). + */ +function comment_build($comment, $build_mode = 'full') { + $node = node_load($comment->nid); + $comment = comment_build_content($comment, $build_mode); + + $build = $comment->content; + + $build += array( + '#theme' => 'comment', + '#comment' => $comment, + '#build_mode' => $build_mode, + ); + + $prefix = ''; + $is_threaded = isset($comment->divs) && _comment_get_display_setting('mode', $node) == COMMENT_MODE_THREADED; + + // Add 'new' anchor if needed. + if (!empty($comment->first_new)) { + $prefix .= "\n"; + } + + // Add indentation div or close open divs as needed. + if ($is_threaded) { + $prefix .= $comment->divs <= 0 ? str_repeat('', abs($comment->divs)) : "\n" . '
'; + } + + // Add anchor for each comment. + $prefix .= "cid\">\n"; + $build['#prefix'] = $prefix; + + // Close all open divs. + if ($is_threaded && !empty($comment->divs_final)) { + $build['#suffix'] = str_repeat('
', $comment->divs_final); + } + + return $build; +} + +/** + * Builds a structured array representing the comment's content. + * + * The content built for the comment (field values, comments, file attachments or + * other comment components) will vary depending on the $build_mode parameter. + * + * @param $comment + * A comment object. + * @param $build_mode + * Build mode, e.g. 'full', 'teaser'... + * @return + * A structured array containing the individual elements + * of the comment's content. + */ +function comment_build_content($comment, $build_mode = 'full') { + if (empty($comment->content)) { + $comment->content = array(); + } + + // Build comment body. + $comment->content['comment_body'] = array( + '#markup' => check_markup($comment->comment, $comment->format, '', FALSE), + ); + + if (empty($comment->in_preview)) { + $comment->content['links']['comment'] = array( + '#theme' => 'links', + '#links' => comment_links($comment), + '#attributes' => array('class' => 'links inline'), + ); + } + + // Allow modules to make their own additions to the comment. + module_invoke_all('comment_view', $comment, $build_mode); + + // Allow modules to modify the structured comment. + drupal_alter('comment_build', $comment, $build_mode); + + return $comment; +} + +/** + * Construct a drupal_render() style array from an array of loaded comments. + * + * @param $comments + * An array of comments as returned by comment_load_multiple(). + * @param $build_mode + * Build mode, e.g. 'full', 'teaser'... + * @param $weight + * An integer representing the weight of the first comment in the list. + * @return + * An array in the format expected by drupal_render(). + */ +function comment_build_multiple($comments, $build_mode = 'full', $weight = 0) { + $build = array( + '#sorted' => TRUE, + ); + foreach ($comments as $comment) { + $build[$comment->cid] = comment_build($comment, $build_mode); + $build[$comment->cid]['#weight'] = $weight; + $weight++; + } + return $build; } /** @@ -878,7 +1156,7 @@ function comment_save($comment) { } else { // Add the comment to database. This next section builds the thread field. - // Also see the documentation for comment_render(). + // Also see the documentation for comment_build(). if ($comment->pid == 0) { // This is a comment with no parent comment (depth 0): we start // by retrieving the maximum thread level. @@ -977,24 +1255,13 @@ function comment_link($type, $object, $build_mode) { * * @param $comment * The comment to which the links will be related. - * @param $return - * Not used. * @return * An associative array containing the links. */ -function comment_links($comment, $return = 1) { +function comment_links(&$comment) { global $user; $links = array(); - // If viewing just this comment, link back to the in-context view. - if ($return) { - $links['comment_parent'] = array( - 'title' => t('parent'), - 'href' => 'comment/' . $comment->cid, - 'fragment' => "comment-$comment->cid" - ); - } - $node = node_load($comment->nid); if ($node->comment == COMMENT_NODE_OPEN) { if (user_access('administer comments') && user_access('post comments')) { @@ -1042,181 +1309,9 @@ function comment_links($comment, $return = 1) { } } - return $links; -} - -/** - * Renders comment(s). - * - * @param $node - * The node which comment(s) needs rendering. - * @param $cid - * Optional, if given, only one comment is rendered. - * - * To display threaded comments in the correct order we keep a 'thread' field - * and order by that value. This 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, the - * thread fields will look like this: - * - * 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. However this would - * spoil the reverse ordering, "ORDER BY thread ASC" -- here, we do not need - * to consider the trailing "/" so we use a substring only. - */ -function comment_render($node, $cid = 0) { - global $user; - $output = ''; - - if (user_access('access comments')) { - // Pre-process variables. - $nid = $node->nid; - if (empty($nid)) { - $nid = 0; - } - - $mode = _comment_get_display_setting('mode', $node); - $comments_per_page = _comment_get_display_setting('comments_per_page', $node); - - if ($cid && is_numeric($cid)) { - $comment = current(comment_load_multiple(array('cid' => $cid, 'status' => COMMENT_PUBLISHED))); - // Single comment view. - if ($comment) { - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - $links = module_invoke_all('link', 'comment', $comment, 1); - drupal_alter('link', $links, $node); - - $output .= theme('comment_view', $comment, $node, $links); - } - } - // Only attempt to render comments if the node has visible comments. - // Unpublished comments are not included in $node->comment_count, so show - // comments unconditionally if the user is an administrator. - elseif ($node->comment_count || user_access('administer comments')) { - - // Multiple comment view. - $query = db_select('comment', 'c')->extend('PagerDefault'); - $query->addField('c', 'cid'); - $query - ->condition('c.nid', $nid) - ->addTag('node_access') - ->limit($comments_per_page); - - $count_query = db_select('comment', 'c'); - $count_query->addExpression('COUNT(*)'); - $count_query - ->condition('c.nid', $nid) - ->addTag('node_access'); - - if (!user_access('administer comments')) { - $query->condition('c.status', COMMENT_PUBLISHED); - $count_query->condition('c.status', COMMENT_PUBLISHED); - } - if ($mode === COMMENT_MODE_FLAT) { - $query->orderBy('c.cid', 'ASC'); - } - else { - // See comment above. Analysis reveals that this doesn't cost too - // much. It scales much much better than having the whole comment - // structure. - $query->orderBy('SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))', 'ASC'); - } - - $query->setCountQuery($count_query); - $cids = $query->execute()->fetchCol(); - - $divs = 0; - $num_rows = FALSE; - $render = ''; - $comments = comment_load_multiple($cids); - drupal_add_css(drupal_get_path('module', 'comment') . '/comment.css'); - foreach ($comments as $comment) { - $comment = drupal_unpack($comment); - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - $comment->depth = count(explode('.', $comment->thread)) - 1; - - if ($mode == COMMENT_MODE_THREADED) { - if ($comment->depth > $divs) { - $divs++; - $render .= '
'; - } - else { - while ($comment->depth < $divs) { - $divs--; - $render .= '
'; - } - } - } - - if ($mode == COMMENT_MODE_FLAT) { - $render .= theme('comment_flat_expanded', $comment, $node); - } - elseif ($mode == COMMENT_MODE_THREADED) { - $render .= theme('comment_thread_expanded', $comment, $node); - } - $num_rows = TRUE; - } - while ($divs-- > 0) { - $render .= ''; - } - $output .= $render; - $output .= theme('pager', NULL); - } - // If enabled, show new comment form if it's not already being displayed. - $reply = arg(0) == 'comment' && arg(1) == 'reply'; - if (user_access('post comments') && $node->comment == COMMENT_NODE_OPEN && (variable_get('comment_form_location_' . $node->type, COMMENT_FORM_BELOW) == COMMENT_FORM_BELOW) && !$reply) { - $output .= theme('comment_form_box', array('nid' => $nid), t('Post new comment')); - } - if ($output) { - $output = theme('comment_wrapper', $output, $node); - } - } - return $output; + return $links; } /** @@ -1287,6 +1382,14 @@ function comment_load_multiple($cids = array(), $conditions = array()) { $comments = $query->execute()->fetchAllAssoc('cid'); } + // Setup standard comment properties. + foreach ($comments as $key => $comment) { + $comment = drupal_unpack($comment); + $comment->name = $comment->uid ? $comment->registered_name : $comment->name; + $comment->new = node_mark($comment->nid, $comment->timestamp); + $comments[$key] = $comment; + } + // Invoke hook_comment_load(). if (!empty($comments)) { module_invoke_all('comment_load', $comments); @@ -1396,7 +1499,7 @@ function comment_get_display_ordinal($cid, $node_type) { else { // For threaded comments, the c.thread column is used for ordering. We can // use the vancode for comparison, but must remove the trailing slash. - // @see comment_render(). + // @see comment_build_multiple(). $query->where('SUBSTRING(c1.thread, 1, (LENGTH(c1.thread) -1)) < SUBSTRING(c2.thread, 1, (LENGTH(c2.thread) -1))'); } @@ -1425,20 +1528,18 @@ function comment_get_display_page($cid, $node_type) { /** * Generate the basic commenting form, for appending to a node or display on a separate page. * - * @param $title - * Not used. * @ingroup forms * @see comment_form_validate() * @see comment_form_submit() */ -function comment_form(&$form_state, $edit, $title = NULL) { +function comment_form(&$form_state, $edit = array()) { global $user; $op = isset($_POST['op']) ? $_POST['op'] : ''; $node = node_load($edit['nid']); if (!$user->uid && variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) != COMMENT_ANONYMOUS_MAYNOT_CONTACT) { - drupal_add_js(drupal_get_path('module', 'comment') . '/comment.js'); + $form_state['#attached_js'][] = drupal_get_path('module', 'comment') . '/comment.js'; } // Take into account multi-step rebuilding. @@ -1676,22 +1777,6 @@ function comment_form(&$form_state, $edit, $title = NULL) { } /** - * Theme the comment form box. - * - * @param $edit - * The form structure. - * @param $title - * The form title. - * @return - * A string containing the box output. - */ -function theme_comment_form_box($edit, $title = NULL) { - $content = drupal_render(drupal_get_form('comment_form', $edit, $title)); - $output = '

' . $title . '

' . $content . '
'; - return $output; -} - -/** * Build a preview from submitted form values. */ function comment_form_build_preview($form, &$form_state) { @@ -1729,38 +1814,31 @@ function comment_preview($comment) { } $comment->timestamp = !empty($edit['timestamp']) ? $edit['timestamp'] : REQUEST_TIME; - $output = theme('comment_view', $comment, $node); - } - else { - $output = ''; - } + $comment->in_preview = TRUE; + $comment_build = comment_build($comment); + $comment_build += array( + '#weight' => -100, + '#prefix' => '
', + '#suffix' => '
', + ); - $form['comment_preview'] = array( - '#markup' => $output, - '#weight' => -100, - '#prefix' => '
', - '#suffix' => '
', - ); + $form['comment_preview'] = $comment_build; + } if ($comment->pid) { $parent_comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array( ':cid' => $comment->pid, ':status' => COMMENT_PUBLISHED, ))->fetchObject(); - $parent_comment = drupal_unpack($parent_comment); - $parent_comment->name = $parent_comment->uid ? $parent_comment->registered_name : $parent_comment->name; - $output_below = theme('comment_view', $parent_comment, $node); + + $build = comment_build($parent_comment); } else { - $suffix = empty($form['#suffix']) ? '' : $form['#suffix']; - $form['#suffix'] = $suffix . drupal_render(node_build($node)); - $output_below = ''; + $build = node_build($node); } - $form['comment_preview_below'] = array( - '#markup' => $output_below, - '#weight' => 100, - ); + $form['comment_output_below'] = $build; + $form['comment_output_below']['#weight'] = 100; return $form; } @@ -1905,67 +1983,25 @@ function comment_form_submit($form, &$form_state) { } /** - * Theme a single comment block. - * - * @param $comment - * The comment object. - * @param $node - * The comment node. - * @param $links - * An associative array containing control links. - * @param $visible - * Switches between folded/unfolded view. - * @ingroup themeable - */ -function theme_comment_view($comment, $node, $links = array(), $visible = TRUE) { - $first_new = &drupal_static(__FUNCTION__, TRUE); - $comment->new = node_mark($comment->nid, $comment->timestamp); - $output = ''; - - if ($first_new && $comment->new != MARK_READ) { - // Assign the anchor only for the first new comment. This avoids duplicate - // id attributes on a page. - $first_new = FALSE; - $output .= "\n"; - } - - $output .= "cid\">\n"; - - // Switch to folded/unfolded view of the comment. - if ($visible) { - $comment->comment = check_markup($comment->comment, $comment->format, '', FALSE); - // Comment API hook. - module_invoke_all('comment_view', $comment); - $output .= theme('comment', $comment, $node, $links); - } - else { - $output .= theme('comment_folded', $comment, $node); - } - - return $output; -} - -/** * Process variables for comment.tpl.php. * * @see comment.tpl.php - * @see theme_comment() */ function template_preprocess_comment(&$variables) { - $comment = $variables['comment']; - $node = $variables['node']; + $comment = $variables['elements']['#comment']; + $variables['comment'] = $comment; + $variables['node'] = node_load($comment->nid); $variables['author'] = theme('username', $comment); - $variables['content'] = $comment->comment; + $variables['content'] = $comment->content; $variables['date'] = format_date($comment->timestamp); - $variables['links'] = isset($variables['links']) ? theme('links', $variables['links']) : ''; - $variables['new'] = $comment->new ? t('new') : ''; + $variables['new'] = !empty($comment->new) ? t('new') : ''; $variables['picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', $comment) : ''; $variables['signature'] = $comment->signature; $variables['submitted'] = theme('comment_submitted', $comment); $variables['title'] = l($comment->subject, 'comment/' . $comment->cid, array('fragment' => "comment-$comment->cid")); - $variables['template_files'][] = 'comment-' . $node->type; + $variables['template_files'][] = 'comment-' . $variables['node']->type; // Set status to a string representation of comment->status. - if (isset($comment->preview)) { + if (isset($comment->in_preview)) { $variables['status'] = 'comment-preview'; } else { @@ -1986,72 +2022,13 @@ function template_preprocess_comment(&$variables) { if ($comment->uid === $variables['user']->uid) { $variables['classes_array'][] = 'comment-by-viewer'; } - if ($comment->new) { + if ($variables['new']) { $variables['classes_array'][] = 'comment-new'; } } } /** - * Process variables for comment-folded.tpl.php. - * - * @see comment-folded.tpl.php - * @see theme_comment_folded() - */ -function template_preprocess_comment_folded(&$variables) { - $comment = $variables['comment']; - $variables['author'] = theme('username', $comment); - $variables['date'] = format_date($comment->timestamp); - $variables['new'] = $comment->new ? t('new') : ''; - $variables['title'] = l($comment->subject, 'comment/' . $comment->cid, array('fragment' => "comment-$comment->cid")); - // Gather comment classes. - if ($comment->uid === 0) { - $variables['classes_array'][] = 'comment-by-anonymous'; - } - else { - if ($comment->status == COMMENT_NOT_PUBLISHED) { - $variables['classes_array'][] = 'comment-unpublished'; - } - if ($comment->uid === $variables['node']->uid) { - $variables['classes_array'][] = 'comment-by-node-author'; - } - if ($comment->uid === $variables['user']->uid) { - $variables['classes_array'][] = 'comment-by-viewer'; - } - if ($comment->new) { - $variables['classes_array'][] = 'comment-new'; - } - } - -} - -/** - * Theme comment flat expanded view. - * - * @param $comment - * The comment to be themed. - * @param $node - * The comment node. - * @ingroup themeable - */ -function theme_comment_flat_expanded($comment, $node) { - return theme('comment_view', $comment, $node, module_invoke_all('link', 'comment', $comment, 0)); -} - -/** - * Theme comment thread expanded view. - * - * @param $comment - * The comment to be themed. - * @param $node - * The comment node. - * @ingroup themeable - */ -function theme_comment_thread_expanded($comment, $node) { - return theme('comment_view', $comment, $node, module_invoke_all('link', 'comment', $comment, 0)); -} - -/** * Theme a "you can't post comments" notice. * * @param $node @@ -2095,6 +2072,9 @@ function theme_comment_post_forbidden($node) { * @see theme_comment_wrapper() */ function template_preprocess_comment_wrapper(&$variables) { + $variables['node'] = $variables['elements']['#node']; + $variables['content'] = $variables['elements']['#children']; + // Provide contextual information. $variables['display_mode'] = _comment_get_display_setting('mode', $variables['node']); $variables['template_files'][] = 'comment-wrapper-' . $variables['node']->type; diff --git modules/comment/comment.pages.inc modules/comment/comment.pages.inc index 226a389..dabe033 100644 --- modules/comment/comment.pages.inc +++ modules/comment/comment.pages.inc @@ -7,24 +7,14 @@ */ /** - * Form builder; generate a comment editing form. + * A menu callback; build a comment editing form. * - * @param $cid - * ID of the comment to be edited. + * @param $comment + * The comment to be edited. * @ingroup forms */ -function comment_edit($cid) { - global $user; - $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid', array(':cid' => $cid))->fetchObject(); - $comment = drupal_unpack($comment); - $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - - if (comment_access('edit', $comment)) { - return theme('comment_form_box', (array)$comment); - } - else { - drupal_access_denied(); - } +function comment_edit($comment) { + return drupal_get_form('comment_form', (array)$comment); } /** @@ -52,13 +42,13 @@ function comment_reply($node, $pid = NULL) { // Set the breadcrumb trail. drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/' . $node->nid))); $op = isset($_POST['op']) ? $_POST['op'] : ''; - $output = ''; + $build = array(); if (user_access('access comments')) { // The user is previewing a comment prior to submitting it. if ($op == t('Preview')) { if (user_access('post comments')) { - $output .= theme('comment_form_box', array('pid' => $pid, 'nid' => $node->nid), NULL); + $build['comment_form'] = drupal_get_form('comment_form', array('pid' => $pid, 'nid' => $node->nid)); } else { drupal_set_message(t('You are not authorized to post comments.'), 'error'); @@ -84,7 +74,7 @@ function comment_reply($node, $pid = NULL) { // Display the parent comment $comment = drupal_unpack($comment); $comment->name = $comment->uid ? $comment->registered_name : $comment->name; - $output .= theme('comment_view', $comment, $node); + $build['comment_parent'] = comment_build($comment); } else { drupal_set_message(t('The comment you are replying to does not exist.'), 'error'); @@ -93,7 +83,7 @@ function comment_reply($node, $pid = NULL) { } // This is the case where the comment is in response to a node. Display the node. elseif (user_access('access content')) { - $output .= drupal_render(node_build($node)); + $build['comment_node'] = node_build($node); } // Should we show the reply box? @@ -102,7 +92,8 @@ function comment_reply($node, $pid = NULL) { drupal_goto("node/$node->nid"); } elseif (user_access('post comments')) { - $output .= theme('comment_form_box', array('pid' => $pid, 'nid' => $node->nid), t('Add new comment')); + $edit = array('nid' => $node->nid, 'pid' => $pid); + $build['comment_form'] = drupal_get_form('comment_form', $edit); } else { drupal_set_message(t('You are not authorized to post comments.'), 'error'); @@ -115,11 +106,11 @@ function comment_reply($node, $pid = NULL) { drupal_goto("node/$node->nid"); } - return $output; + return $build; } /** - * Publish specified comment. + * Menu callback; publish specified comment. * * @param $cid ID of comment to be published. */ diff --git modules/comment/comment.test modules/comment/comment.test index 0fd3cce..7e1aa83 100644 --- modules/comment/comment.test +++ modules/comment/comment.test @@ -76,7 +76,7 @@ class CommentHelperCase extends DrupalWebTestCase { $regex .= 'subject . '(.*?)'; // Match subject. $regex .= $comment->comment . '(.*?)'; // Match comment. - $regex .= '<\/div>/s'; // Dot matches newlines and ensure that match doesn't bleed outside comment div. + $regex .= '/s'; return (boolean)preg_match($regex, $this->drupalGetContent()); } @@ -446,7 +446,7 @@ class CommentAnonymous extends CommentHelperCase { // "Login or register to post comments" type link may be shown. $this->drupalLogout(); $this->drupalGet('node/' . $this->node->nid); - $this->assertNoRaw('
', t('Comments were not displayed.')); + $this->assertNoPattern('/
]*?)id="comments"([^>]*?)>/', t('Comments were not displayed.')); $this->assertNoLink('Add new comment', t('Link to add comment was found.')); // Attempt to view node-comment form while disallowed. @@ -459,7 +459,7 @@ class CommentAnonymous extends CommentHelperCase { $this->setAnonymousUserComment(TRUE, FALSE, FALSE); $this->drupalLogout(); $this->drupalGet('node/' . $this->node->nid); - $this->assertRaw('
', t('Comments were displayed.')); + $this->assertPattern('/
]*?)id="comments"([^>]*?)>/', t('Comments were displayed.')); $this->assertLink('Login', 1, t('Link to login was found.')); $this->assertLink('register', 1, t('Link to register was found.')); } diff --git modules/comment/comment.tpl.php modules/comment/comment.tpl.php index d65e327..512cc21 100644 --- modules/comment/comment.tpl.php +++ modules/comment/comment.tpl.php @@ -7,9 +7,11 @@ * * Available variables: * - $author: Comment author. Can be link or plain text. - * - $content: Body of the post. + * - $content: An array of comment items. Use render($content) to print them all, or + * print a subset such as render($content['field_example']). Use + * hide($content['field_example']) to temporarily suppress the printing of a + * given element. * - $date: Date and time of posting. - * - $links: Various operational links. * - $new: New comment marker. * - $picture: Authors picture. * - $signature: Authors signature. @@ -46,7 +48,7 @@
- new): ?> + @@ -57,7 +59,11 @@
- +
@@ -65,5 +71,5 @@
- +
diff --git themes/garland/comment.tpl.php themes/garland/comment.tpl.php index 809d57c..9d75460 100644 --- themes/garland/comment.tpl.php +++ themes/garland/comment.tpl.php @@ -8,7 +8,7 @@ - new) : ?> + @@ -17,7 +17,7 @@

- +
@@ -27,7 +27,5 @@
- - - +
diff --git themes/garland/template.php themes/garland/template.php index 1952353..97fab30 100644 --- themes/garland/template.php +++ themes/garland/template.php @@ -15,18 +15,6 @@ function garland_breadcrumb($breadcrumb) { } /** - * Allow themable wrapping of all comments. - */ -function garland_comment_wrapper($content, $node) { - if (!$content || $node->type == 'forum') { - return '
' . $content . '
'; - } - else { - return '

' . t('Comments') . '

' . $content . '
'; - } -} - -/** * Override or insert variables into the page template. */ function garland_preprocess_page(&$vars) {