3

I'm trying to display the comments on my nodes in a view rather than using drupals default comments rendering.

Is it possible to display a comment view on a node, which also renders the comments with replies, rather than rendering every comment (including replies) as a top level comment?

How would you setup views to do this?

UPDATE

I've successfully setup views, so that it renders comments and replies in the correct order.

You have to set:

Relationship -> Comment: Parent Comment
Sort Criteria -> Thread (desc)
Sort Criteria -> (Parent Comment) Comment: Post date (asc)

However the pager still counts every single comment reply as an item, so it is prone to cutting off threads in the middle and ideally I'd still like to page it.

ORIGINAL WORKINGS

What I've tried to do so far -- Show: Settings: Parent relationship

Getting the top level comments was reasonably easy, I created a view block which displays comments and then added:

Contextual filter -> Comment NID (Content ID from URL) (Shown here)

This gives a me a view block which will display comments. However all the comments are rendered as top level comments (no indented markup)

I needed the parent relationship, so I added a second relationship (comment views by default have a Comment: Content relationship),

Comment: Parent Comment

enter image description here

And then under Format: Show: Settings, I enabled:

Relationship: Parent Comment

Unfortunately on loading the node, this causes several PHP errors. views_plugin_row_comment_view.inc has a pre_render function and for some reason changing the Relationship: Parent Comment causes none of the CID's to load in the pre-render function and so it spits out all the horrible errors you see below. How am I setting this up wrong?

Undefined property: stdClass::$cid in views_plugin_row_comment_view->pre_render() (line 79 of ... sites\all\modules\views\modules\comment\views_plugin_row_comment_view.inc
Warning: array_flip(): Can only flip STRING and INTEGER values! in DrupalDefaultEntityController->load() (line 173 of C:\xampp\htdocs\basic\includes\entity.inc).
Notice: Undefined index: in template_preprocess_views_view_row_comment() (line 645 of C:\xampp\htdocs\basic\sites\all\modules\views\modules\comment.views.inc).
Notice: Trying to get property of non-object in template_preprocess_views_view_row_comment() (line 646 of C:\xampp\htdocs\basic\sites\all\modules\views\modules\comment.views.inc).
Notice: Undefined index: in template_preprocess_views_view_row_comment() (line 646 of C:\xampp\htdocs\basic\sites\all\modules\views\modules\comment.views.inc).
Notice: Trying to get property of non-object in template_preprocess_views_view_row_comment() (line 650 of C:\xampp\htdocs\basic\sites\all\modules\views\modules\comment.views.inc).
EntityMalformedException: Missing bundle property on entity of type comment. in entity_extract_ids() (line 7729 of C:\xampp\htdocs\basic\includes\common.inc).

What I've tried to do so far -- Sort: Comment Threading

I took a look at the following sandbox module and according to the issue thread it was based on https://drupal.org/node/1039494, apparently it was solved ages ago by adding in a sort criteria Comment: Thread.

I tried adding this and setting the relationship to parent comment but this also had no effect, the comments still remained in separate rows. Has anyone had success with this method?

3 Answers 3

1
+50

If i only had a specified number of nesting levels (e.g. 2) would try to use attached views.

All relationships should be from parent comment to child comment and not the other way round.

Also make sure that the relationships are not required (you want OUTER JOINS instead of INNER JOINS in order to avoid filtering out comments that don't have child comments)

So the top level view would only fetch top comments. Then the attached view would fetch child comments for the parent comment and so on.

This solution has not optimal performance and does not scale for deep nesting. However it requires no custom coding.

If you are willing to do custom coding try add a Views PHP field and use something like this https://api.drupal.org/api/drupal/modules%21comment%21comment.module/function/comment_get_thread/7

to get all comments in your thread

2
  • I did end up using comment_get_thread although in a different context. Will post a full answer when I finish. Commented Jan 26, 2015 at 22:00
  • NEVER WRITE PHP CODE TO THE DATABASE! It's a huge security risk. Do this with a custom template file instead
    – Anon Ymous
    Commented Jun 2, 2019 at 4:20
2

I recommend installing the Views Threaded Comments sandbox module.

Provides Threaded comments views plugin

I'm a developer, so I'd start there ... if you're not a developer you may not find a sandbox project as a good starting off place, your mileage may vary.

1
  • I read through the issue thread that created the module and apparently the issue was fixed and was built into a sort option Comment -> Thread. I tried adding this but it didn't have any effect. I'll give the module a try a though. Commented Jan 20, 2015 at 22:16
0

Ok so here was my final solution. I never managed to solve the pager issue so instead I used the following design:

  • Top level comments are displayed on the node in a field only view
  • Each then has a link to a comment discussion which is a separate view on a different page
  • The separate comment view renders comments as opposed to fields

The top level comment view is reasonably simple to set-up, the only slightly confusing part is the filter to only show top level comments. You need:

  • Relationship: Comment: Parent Comment
  • Filter: Comment ID - Relationship (Parent Comment) - Value = NULL

Generating the link to comment discussion requires a separate module. The issue is how you grab the correct comment and all it's replies from the database. Comments store a PID, but in a chain, this means you'd have to search recursively to find an entire chain. Instead we need to use the thread field which isn't naturally loaded.

The thread field contains values as follows:

Comment   - 01
  Reply   - 01.01
    Reply - 01.01.01
    Reply - 01.01.02
Comment   - 02

So in order to grab a whole chain all we need is the first two digits of thread and nid of the node the comment is on.

To do add thread to our we we alter the comment view we're using on the main page using hook_views_query_alter. A good explanation of how to setup the module is here.

The exact query you need is:

  if ($view->name == 'my_comment_view') {
    $query->fields['thread'] = array (
      'field' => 'thread',
      'table' => 'comment',
      'alias' => 'comment_thread',
    );
  }

You then need to create the comment discussion view with a path that contains two wildcards.

When you then generate the URL in the views template, one will need to be the id of the node the comment is on and the other will be the first two digits of the thread.

The comment discussion view will need a contextual filter:

  • Contextual Filter: Comment: NID

And you'll need to alter the query to pick out the correct thread with hook_views_query_alter alter again because this isn't possible in the UI.

if ($view->name == 'comment_discussion_page' && $view->current_display == 'page') {
    $thread_id = $view->args(1); 
    //check argument is an integer before putting it in a query
    if((is_numeric($thread_id) && $thread_id >= 1 && $thread_id == round($thread_id))) {
      $query->add_where(1, 'thread', $thread_id.'%', 'LIKE');
    } else {
      drupal_set_message(t('Whoops something has gone wrong. Go back and try reloading this page.'), 'error');
    }  
}

And congratulations we have a fully working comment system.

Actually I forgot two parts: One in order to add some indented classes I added the following code to template_preprocess_comment:

    $vars['count_fullstop'] = substr_count($vars['elements']['#comment']->thread, '.');
    if($vars['count_fullstop'] > 0 && $vars['count_fullstop'] < 4) {
      $vars['classes_array'][] = 'indented_'.$vars['count_fullstop'];
    } elseif($vars['count_fullstop'] >= 4){
      $vars['classes_array'][] = 'indented_3';
    }

In order to get around the paging problem I display the whole thread on a single page. This doesn't bother me because I don't expect huge threads and it offloads the possible performance issues onto less valuable pages.

(A sidenote. The only reason I'm using views rather than the traditional comment system, is on certain nodes I need to aggregate comments from multiple nodes and I need to be able to filter them. If that's not the case I'd stick the normal system!)

Not the answer you're looking for? Browse other questions tagged or ask your own question.