Jump to content

Threaded Comments


matjash
 Share

Recommended Posts

I need some help with threaded comments.

 

1. I want to use custom markup and display only 1 level deep, but I dont know how to iterate through array to output correctly.

2. I tried the general example by using function renderALL(), but the reply doesn't work. (I have put css in head and script to body)

I tried with this code but it doesn't work because it double prints comments with children:

                          <?php

                          foreach($page->blog_comments as $comment) {
                          if($comment->status < 1) continue; // skip unapproved or spam comments
                          $cite = htmlentities($comment->cite); // make sure output is entity encoded
                          $text = htmlentities($comment->text);
                          $date = date('m/d/y g:ia', $comment->created); // format the date         

						  //If comment has children display parant and child
                          if ($comment->children->count >= 1) {
                            foreach ($comment->children as $children) {
                          $cite2 = htmlentities($children->cite); // make sure output is entity encoded
                          $text2 = htmlentities($children->text);
                          $date2 = date('m/d/y g:ia', $children->created); // format the date 
                          
                             include('rs-template/includes/comments/commentL2.php');
                           }
						//Display only parent
                         } else {
                          include('rs-template/includes/comments/commentL1.php'); 
                        }                                     
                        }
                        ?>   

 

Link to comment
Share on other sites

This is how i do it:

function getComments($comments, $page, $parentID = 0, $reply = true, $child = null)
{
	$out = "";
	foreach($comments as $comment)
	{
		if($comment->parent_id == $parentID)
		{
			$reply = ($reply == true) ? "<a class='CommentActionReply comment-reply-link' data-comment-id='{$comment->id}' href='#Comment{$comment->id}'>Reply</a>" : "";
			if($comment->status < 1) continue;
			$cite = htmlentities($comment->cite);
			$text = htmlentities($comment->text);
			$userID = $comment->created_users_id;
			$u = wire("pages")->get($userID);
			$name = ($u->displayName) ? $u->displayName : $u->name;
			$date = date('m/d/y g:ia', $comment->created);
			$out .= "
			<div class='{$child}'>
			<article id='comment-{$comment->id}' class='comment-body single-comment'>
				<header class='comment-meta'>
					<img src='{$u->avatar->size(75,75)->url}'>
					<strong>{$name}</strong>
					<a href='{$page->httpUrl}#comment-{$comment->id}' title='Link to comment' class='comment-link'><time datetime='comment_date'>{$date}</time></a>
				</header>
				<div class='comment-content'>{$text}</div>
				{$reply}";
			$out .= "</article>";
			$out .= getComments($comments, $page, $comment->id, false, "child-comment");
			$out .= "</div>";
		}
	}
	return $out;
}
           
// and use in the template file
echo getComments($page->comments, $page);

If you have trouble understanding let me know and i'll explain, going to sleep now.

  • Like 4
Link to comment
Share on other sites

Thank you the display is perfect, now i need to customize the reply button but i have a problem also with default method if I render form  via renderAll() method as stated in documentation. The reply doesnt work.

On click the hashtag gets comment id, and window moves to input form.

Which functionality should then happen? Does the original message gets send to the cookie or does the form get some data from comment.

Js and css gets loaded correctly.

Link to comment
Share on other sites

Thanks again everything is working fine. I'm just fine tuning the form output. I'm pasting my code so someone with same problems can quickly view how to customize it based on your initial answer I had to add $childFinish since my child output was in UL tag:

<?php 
function getComments($comments, $page, $parentID = 0, $reply = true, $child = null, $childFinish = null)
{
  $out = "";
  foreach($comments as $comment)
  {
    if($comment->parent_id == $parentID)
    {
      $reply = ($reply == true) ? "<a class='comment__reply js-comment-reply CommentActionReply comment-reply-link' data-comment-id='{$comment->id}' href='#Comment{$comment->id}'>Reply</a>" : "";
      if($comment->status < 1) continue;
      $cite = htmlentities($comment->cite);
      $text = htmlentities($comment->text);
      $userID = $comment->created_users_id;
      $u = wire("pages")->get($userID);
      $name = ($u->displayName) ? $u->displayName : $u->name;
      $date = date('m/d/y g:ia', $comment->created);

      $out .= $child . "
      <li class='comment__item'>
        <div class='comment__item-body js-comment-item'>
          <div class='comment__avatar'><img src=" . wire('config')->urls->templates . "rs-template/assets/media-demo/avatars/01.jpg alt=''></div>
              <div class='comment__item-right'>
                <button class='comment__item-btn'>Edit</button>
                <button class='comment__item-btn'>Delete</button>
              </div>     
              <div class='comment__info'><span class='comment__author'>" . $cite . "</span><span class='comment__date'>" . $date . "</span>
              <div class='comment__content'>
                <p>" . $text ."</p>
              </div>
            " . $reply ."</div>
        </div>
        <!-- end of block .comment__item-body-->
      ";     
	  
      $out .= "</li>" . $childFinish;

      $out .= getComments($comments, $page, $comment->id, false, "<ul class='comment__children'>", "</ul>");
    }
  }
  return $out;
}
           
echo getComments($page->blog_comments, $page);
?>                            

 

  • Like 4
Link to comment
Share on other sites

  • 4 weeks later...

If comments are sorted newest to oldest than the nested ones are also sorted like that.

To have the nested comments sorted oldest to newest add

if( $parentID !== 0 ){
	$comments = $comments->sort("created");
}

at the top of the function.

  • Like 1
Link to comment
Share on other sites

  • 6 months later...

@fbg13 I used parts of your code for my Latest commeents block and it works fine, but I have a little issue I am trying to figure out - when I try to echo $cite it shows nothing instead of showing the author. I made it work by using your way:

$userID = $comment->created_users_id;
      $u = wire("pages")->get($userID);
      $name = ($u->displayName) ? $u->displayName : $u->name;

However I am trying to figure out why $cite would be empty as it is much easier to use that instead of the extra lines. Any ideas or thoughts about possible reasons?

My code sample is in this topic 

Link to comment
Share on other sites

Remember that the "cite" field is not storing the same info as the "created_users_id". In most cases, "created_users_id" will be "40" - the ID of the guest user. "cite" can be entered manually. Have you checked the "cite" field in the DB table for the comment field? Is it actually being populated?

May or may not be useful, but if your users are always logged in, check out this very old PR: https://github.com/ryancramerdesign/ProcessWire/pull/954 

Link to comment
Share on other sites

@adrian  Thanks very much for the shared info and the link. As far as I am just finding out some pieces of the way comments can be pulled through the API, I did not went that far yet to check in the DB but will do. In case the cite in database does not have any value, are there any settings to have the values added for the comments or do you know of any possible reason why 'cite' would stay empty? So far I tried to add a few users to the site and post a few comments and they show perfectly well so the code borrowed from FBG worked in my case but not using $cite.

@fbg13 What you are saying seems the same as adrian. Let me check if the DB holds any cite values and see what could be the issue if not.

Link to comment
Share on other sites

3 minutes ago, MilenKo said:

So far I tried to add a few users to the site and post a few comments and they show perfectly well so the code borrowed from FBG worked in my case but not using $cite.

Again - using @fbg13's code is not pulling the value from the cite field, but rather from the details of the currently logged in user. If you require that a user is logged in before commenting, that will be fine, but if not, it will always return the guest user, so you would need to figure out the issue with cite.

Let us know what you find regarding the cite DB column/field.

As for why it might not be being populated, are you using $page->comments->renderForm() to generate the comment form, or are you creating it manually? Is it asking for "Your Name" along with email address and the actual comment The "Your Name" field is what populated the "cite" field in the db.

Link to comment
Share on other sites

Oh, now after reading what you say, I might have an issue with the form that adds the comments as I did decided to allow the commenting for the registered users only (intending to provide an option for switching in the admin later), so if the user is logged on, I populate the name in the form directly leaving only the comment block to have hold the text. The name and email are hidden, so if cite is populated through the name, then there has to be something wrong with the value...

Here is my comments block code:

Spoiler

<!-- Comments -->
<div id="comments" class="comments-area">

    <?php 
                                $comm_count = count($page->comments);
                                if($comm_count) { ?>
        <h2 class="comments-title section-title h3"><i class="line"></i>There are <?=$comm_count?> comment(s) approved in this article:</h2>
        <? } ?>
            <?php   foreach($page->comments as $comment) {
                                            if($comment->status < 1) continue; // skip unapproved or spam comments
                                            $text = htmlentities($comment->text);
                                            $date = date('d/m/y \a\t G:i', $comment->created); // format the date
                                            $datetime = date('Y-m-d\TH:m:s', $comment->created);

                                            // Grab the author ID
                                            $userID = $comment->created_users_id;

                                            // Obtain the displayName using $u variable
                                            $u = wire("pages")->get($userID);

                                            // Obtain the user name and assign it to $name for printing
                                            $name = ($u->displayName) ? $u->displayName : $u->name;

                                            ?>

                <ol class="comment-list">
                    <li id="comment-<?=$comment->id?>" class="comment even thread-even depth-1">
                        <article id="div-comment-<?=$comment->id?>" class="comment-body">
                            <footer class="comment-meta">
                                <div class="comment-author vcard">
                                    <img alt="" src="http://1.gravatar.com/avatar/?s=50&amp;d=mm&amp;r=g" srcset="http://1.gravatar.com/avatar/?s=100&amp;d=mm&amp;r=g 2x" class="avatar avatar-50 photo avatar-default" height="50" width="50"> <b class="fn"><?=$name?></b>
                                    <span class="says">said on <a href="<?=$page->url?>#comment-<?=$comment->id?>"><time datetime="<?=$datetime?>"><?=$date?> </time></a>: <br/><br/>
                                                                    <p><?=$text?></p>
                                                                </span> </div>
                                <!-- .comment-author -->

                            </footer>
                            <!-- .comment-meta -->

                            <div class="comment-content">
                            </div>
                            <!-- .comment-content -->

                            <div class="reply comment-reply text-right"><a class="comment-reply-link btn btn-custom btn-sm" href="?replytocom=<?=$comment->id?>#respond" onclick="return addComment.moveForm( &quot;div-comment-<?=$comment->id?>&quot;, &quot;<?=$comment->id?>&quot;, &quot;respond&quot;, &quot;193&quot; )" aria-label="Reply to ">Reply</a></div>
                        </article>
                        <!-- .comment-body -->
                    </li>
                    <!-- #comment-## -->
                </ol>

                <? } 

                                            if ($user->isGuest()) { ?>

                    <div id="respond" class="comment-respond">
                        <div class="alert alert-warning alert-custom">
                            <i class="fa fa-warning text-danger"></i>
                            <h4>Want to add a comment?</h4> You must be <a href="#">logged in</a> to post a comment.
                        </div>
                    </div>
                    <!-- #respond -->

                    <? } else {

                                                // Process submitted comments
                                                if ($input->post->submit) {

                                                    $c = new Comment();
                                                    $c->name = $sanitizer->name($input->post['name']);  
                                                    $c->email = $sanitizer->email($input->post['email']);   
                                                    $c->text = $sanitizer->textarea($input->post['text']);                                                  
                                                    $c->created = time();
                                                    $c->user_agent = $_SERVER['HTTP_USER_AGENT']; 
                                                    $c->ip = $_SERVER['REMOTE_ADDR'];
                                                    $c->created_users_id = $user->id;
                                                    $c->sort = count($page->comments)+1;

                                                    // set status (Spam = -2; Pending = 0;  Approved = 1; )
                                                    $c->status = 1;

                                                    // add new comment object to the page "comments" field  
                                                    $page->setOutputFormatting(false);
                                                    $page->comments->add($c);
                                                    $page->save('comments');
                                                    $session->redirect("./"); 

                                                } ?>

                        <div id="respond" class="comment-respond form-border">
                            <h3 id="reply-title" class="comment-reply-title section-title"><br />
                                                    <i class="line"/>Leave a Reply <small class="pull-right">
                                                        <a rel="nofollow" id="cancel-comment-reply-link" href="<?=$page->url?>#respond" style="display:none;" class="btn btn-custom btn-xs">Cancel reply</a>
                                                    </small>
                                                </h3>
                            <form action="./" method="post" id="commentform" class="comment-form" novalidate="">
                                <div class="row">
                                    <div class="col-md-12">
                                        <div class="comment-form-author form-group">
                                            <input id="name" name="name" type="hidden" class="form-control" value="<?=$user->name?>" size="30">
                                        </div>

                                        <div class="comment-form-email form-group">
                                            <input id="email" name="email" type="hidden" class="form-control" value="<?=$user->email?>" size="30">
                                        </div>

                                    </div>
                                    <div class="col-md-12">
                                        <div class="form-group">
                                            <textarea id="text" name="text" class="form-control" cols="45" rows="8" aria-required="true"></textarea>
                                        </div>
                                    </div>
                                </div>
                                <p class="form-submit">
                                    <input name="submit" type="submit" id="submit" class="submit btn btn-custom btn-lg" value="Share your opinion" />
                                </p>
                            </form>
                        </div>
                        <? } ?>

</div>
<!-- Comments -->

 

 

Link to comment
Share on other sites

6 minutes ago, MilenKo said:

$c->name = $sanitizer->name($input->post['name']);

You're setting the "name", but there isn't a "name" field, it's the "cite" field that you need to populate the new comment with.

Maybe you could take a look at my old PR and update it for PW 3 and re-submit because it takes care of this without manually building/processing the comment submission form.

  • Like 1
Link to comment
Share on other sites

@adrian PR? I just remembered, that the form was actually having the cite but I did not realized that I modified it to name without considering the fact that the field is caled cite but not name. Let me change it and see if it would populate the cite... 

Link to comment
Share on other sites

Yes, it did populate the name and you were perfectly right (as always ;) ) @adrian

So now I will just remove the comments and test the cite for populating the official name of the user. How would you approach leaving a comment from non-registered user? Would you allow to post and then moderate or just offer to register and then comment?

Link to comment
Share on other sites

9 hours ago, MilenKo said:

PR?

Github Pull Request - I linked to it above, but here it is again: https://github.com/ryancramerdesign/ProcessWire/pull/954

 

9 hours ago, MilenKo said:

How would you approach leaving a comment from non-registered user? Would you allow to post and then moderate or just offer to register and then comment?

That really depends on how many comments the site is likely to get and how much time there is for moderation :) But then again, if there is no approval process for registration, it doesn't prevent spam comments anyway.

 

Link to comment
Share on other sites

I got you, @adrian  Well as far as the platform is intended to be used as an internal knowledge database, I would leave the registrations up to someone who will be charged for that, so I can eliminate the login-register forms etc. For sure I will have a look to see how it is done, but as of now it is all working.

I noticed that in the comments form I was populating cite with $user->name but even if I post as a different user, all comment authors show admin instead of the user who posted the comment.

Link to comment
Share on other sites

7 minutes ago, MilenKo said:

I noticed that in the comments form I was populating cite with $user->name but even if I post as a different user, all comment authors show admin instead of the user who posted the comment.

How are you posting as a different user? Are you logged in as a different user, or just entering a different name and email address? How are you retrieving the author - via "cite", or "created_user_id"?

Link to comment
Share on other sites

OK. After figuring out why the cite was not populating, I changed the code to my Latest comments and in the articles-inner so that the author comes from $cite. Now for the tests I am logging as a different user (created one via the admin) and logged on as it to test the comments adding.

Here is my comments adding form:

<div id="respond" class="comment-respond form-border">
    <h3 id="reply-title" class="comment-reply-title section-title"><br />
      <i class="line"/>Leave a Reply <small class="pull-right">
      <a rel="nofollow" id="cancel-comment-reply-link" href="<?=$page->url?>#respond" style="display:none;" class="btn btn-custom btn-xs">Cancel reply</a>
      </small>
  	</h3>
    <form action="./" method="post" id="commentform" class="comment-form" novalidate="">
        <div class="row">
            <div class="col-md-12">
                <div class="comment-form-author form-group">
                    <input id="cite" name="cite" type="hidden" class="form-control" value="<?=$user->name?>" size="30">
                </div>

                <div class="comment-form-email form-group">
                    <input id="email" name="email" type="hidden" class="form-control" value="<?=$user->email?>" size="30">
                </div>

            </div>
            <div class="col-md-12">
                <div class="form-group">
                    <textarea id="text" name="text" class="form-control" cols="45" rows="8" aria-required="true"></textarea>
                </div>
            </div>
        </div>
        <p class="form-submit">
            <input name="submit" type="submit" id="submit" class="submit btn btn-custom btn-lg" value="Share your opinion" />
        </p>
    </form>
</div>
<? } ?>

So I thought that $user->name would populate the name of the current user and if I am logged on as test, than the 'cite' would get populated with 'test' as author, but it shows admin on all comments in the DB and in the frontend.

Link to comment
Share on other sites

Ok, but when looking at the comment form, is $user->name correctly populating the username of the currently logged in user?

What about when you are processing the submission form - are you still using:

$c = new Comment();
$c->name = $sanitizer->name($input->post['name']);

or did you change this to the correct:

$c->cite = $input->post->name('cite');

Note that I am using the $input sanitizer, but the key thing is that I am making use of the POSTed 'cite' field.

Link to comment
Share on other sites

Well to populate the form I replaced name with cite in all instances. Here is the whole part of processing the comments:

Spoiler

<div id="respond" class="comment-respond">
    <div class="alert alert-warning alert-custom">
        <i class="fa fa-warning text-danger"></i>
        <h4>Want to add a comment?</h4> You must be <a href="#">logged in</a> to post a comment.
    </div>
</div>
<!-- #respond -->

<? } else {

        // Process submitted comments
        if ($input->post->submit) {

            $c = new Comment();
            $c->cite = $sanitizer->name($input->post['cite']);  
            $c->email = $sanitizer->email($input->post['email']);   
            $c->text = $sanitizer->textarea($input->post['text']);                                                  
            $c->created = time();
            $c->user_agent = $_SERVER['HTTP_USER_AGENT']; 
            $c->ip = $_SERVER['REMOTE_ADDR'];
            $c->created_users_id = $user->id;
            $c->sort = count($page->comments)+1;

            // set status (Spam = -2; Pending = 0;  Approved = 1; )
            $c->status = 1;

            // add new comment object to the page "comments" field  
            $page->setOutputFormatting(false);
            $page->comments->add($c);
            $page->save('comments');
            $session->redirect("./"); 

        } ?>

    <div id="respond" class="comment-respond form-border">
        <h3 id="reply-title" class="comment-reply-title section-title"><br />
            <i class="line"/>Leave a Reply <small class="pull-right">
                <a rel="nofollow" id="cancel-comment-reply-link" href="<?=$page->url?>#respond" style="display:none;" class="btn btn-custom btn-xs">Cancel reply</a>
            </small>
        </h3>
        <form action="./" method="post" id="commentform" class="comment-form" novalidate="">
            <div class="row">
                <div class="col-md-12">
                    <div class="comment-form-author form-group">
                        <input id="cite" name="cite" type="hidden" class="form-control" value="<?=$user->name?>" size="30">
                    </div>

                    <div class="comment-form-email form-group">
                        <input id="email" name="email" type="hidden" class="form-control" value="<?=$user->email?>" size="30">
                    </div>

                </div>
                <div class="col-md-12">
                    <div class="form-group">
                        <textarea id="text" name="text" class="form-control" cols="45" rows="8" aria-required="true"></textarea>
                    </div>
                </div>
            </div>
            <p class="form-submit">
                <input name="submit" type="submit" id="submit" class="submit btn btn-custom btn-lg" value="Share your opinion" />
            </p>
        </form>
    </div>
    <? } ?>

 

 

Link to comment
Share on other sites

Did you clarify that the hidden cite form field is being populated with the correct value from $user->name ?

In the DB for the comments field, you mention that the cite field getting populated with "admin" - if that is happening, then it's got to be due to the form population or processing and adding of the comment via the API. Do a test debug of the value of $input->post->cite in your code to make sure it is showing "test" and not "admin". Tracy Debugger's bd($input->post->cite) would be the easiest approach to this.

 

Link to comment
Share on other sites

@adrian I am not sure how can I debug the $input->post->cite in Tracy Debugger's bd. I tried to unhide the Name and remove the value from it so that it is populated with the field content, but the comment does not show up and is not in NonApproved comments attached to the page. So something must be wrong with the form submission...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...