Jump to content

FieldtypeComments - how to customize


modifiedcontent
 Share

Recommended Posts

Render Comments with options is this:

Spoiler

    echo $page->comments->render(array(
    'headline' => '<h2>Comments</h2>',
    'commentHeader' => 'Posted by {cite} on {created}',
    'dateFormat' => 'l, F jS Y g:i a',
    'encoding' => 'UTF-8',
    'admin' => false, // shows unapproved comments if true
    ));

 

{cite} inserts the username. I want to display the commenter's Firstname Lastname instead - I have a field for that called 'fullname'. Where is {cite} defined? How can I change it?

This should be functionally the same (?) and would give me control to define and change lots of stuff, including "cite" and adding profile picture etc.:

Spoiler

foreach($page->comments as $comment) {
    if($comment->status < 1) continue; // skip unapproved or spam comments
    $commenter = $users->get(htmlentities($comment->cite));
    $cite = $commenter->fullname; // make sure output is entity encoded
    $text = htmlentities($comment->text);
    $date = date('l, F jS Y g:i a', $comment->created); // format the date
    echo "<p><strong>Posted by $cite on $date</strong><br />$text</p>";
}

 

But with this, the 'Reply' link is missing from the comment. How can I add that 'Reply' link and make sure those replies-to-comments or replies-to-replies-to-comments are stored in the proper way?

Or will that get me into a hopeless mess and should I just stick to the render method with a simple way to make {cite} render the full name instead of a username?

edit: I see the comments just end up on the same level anyway, with either method - Comment1 Comment2 Comment3. 'Reply Depth' is set to '2' in the Comments field settings. Does threaded comments not work?

 

Link to comment
Share on other sites

@modifiedcontent Not quite your question but in your template, where you are rendering the comments entry form, you can do this instead. This should set up the correct value for the cite field for new entries...

<?php
echo $page->comments->renderForm([
    'presets' => [
        'cite' => wire()->sanitizer->entities($user->fullname),
    ],
]);

For existing entries, I think you can iterate the comments and then set the cite attribute to the value you want.

  • Like 1
Link to comment
Share on other sites

Thanks @netcarver. So 'presets' is an array somewhere that contains 'cite' and other things?

Username is OK for the comment form, because comments will only be open to logged-in members. The module enters the logged-in users name and email address, so I can just hide those fields - or is there a way not to require them at all?

The updated second method in my original post also produces the result I want, minus the Reply link. That Reply link doesn't seem to do anything special anyway; comments are all created on the same level, Comment1, Comment2, Comment3. 

I am now mostly puzzled by how to make threaded comments work - 'Reply Depth', reply-to-comment. 

Edit: Another problem; where does the module get the name + email address that are prefilled in the comment form? They are not consistently the name + email from the logged-in user as I assumed.

When I test logged-in with different accounts, only the name + email of the first account I tested with show up in the comment form. Is there a way to just let the comment form take the name + email, or just ID, of the logged-in user? 

Edit 2: Javascript sets a persistant cookie for whoever posts a comment? I guess I should replace that with Javascript that enters the logged-in user's name+email then. Or is there any way via PHP without editing the module core files?

 

Link to comment
Share on other sites

Hi @modifiedcontent

It's really easy, and I suggest you to copy the MyCommentForm.php file from /wire/fieltype/fieldtypeComments, put it in your template directory then rename it to _MyCommentForm.php and modify this file to your need - for you it's the renderFormThread() function which is interesting and there to be tweaked.

Then in a template, you put the following code :

include("./_MyCommentForm.php");

CommentStars::setDefault('star', '<i class="fa fa-star"></i>'); //<= star item using fontawesome icon
		
$options = array(...); // options of your form, check `myCommentForm.php`
                                                                        
$myCommentsForm = new MyCommentForm($page, $page->comments, $options);                                                                       
echo $myCommentsForm->render();

 

You have also a good function to start here to control all the comments markup :

Spoiler


// Get comments threaded
    // use in template file: echo getComments($page->comments, $page);
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}'>". __('répondre') ."</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);
            $stars = ($comment->stars > 0) ? $comment->renderStars() : '';
            $emailHash = md5(strtolower(trim($comment->email)));
            //$http = new WireHttp();
            $imgGravatarUrl = false; "https://www.gravatar.com/avatar/". $emailHash ."/?r=g&s=85&r=g&d=404";
            //$response = $http->get($imgGravatarUrl);
            //if(strlen($response) < 14) $imgGravatarUrl = false;
            $avatar = ($u->avatar) ? $u->avatar->size(75, 75)->url : (($imgGravatarUrl) ? $imgGravatarUrl : wire('config')->urls->templates.'img/placeholder-avatar2.svg'); // 'http://placeskull.com/78/78/'. $colors[rand(0, 2)] .'/'. rand(1, 45); // wire('config')->urls->templates.'img/placeholder-avatar.svg';
            $out .= "<div id='comment-{$comment->id}' class='card {$child}' style='width: 100%;'>
                        <div class='card-header d-flex align-items-center px-0'>
                            <img class='avatar mr-3' src='{$avatar}' alt='avatar-{$cite}' style='border-radius: 50%;'>
                                <span class='card-title m-0 p-0'>{$cite}</span>
                                <small class='card-subtitle text-muted m-0 ml-2 p-0'><time datetime='comment_date'>". wireRelativeTimeStr($date, true) ."</time></small>
                                <span class='stars pull-right'>{$stars}</span>
                        </div>
                        <div class='card-body px-0 pt-0'>
                            <p class='card-text'>". nl2br($text) ."</p>
                    ";
            // nest child
            $out .= "   </div>";
            $out .=     getComments($comments, $page, $comment->id, false, "child-comment");
            $out .= "</div>";
            
		}
	}
	return $out;
}

> Credit :   @fbg13

An screenshot of what can be done (sorry for the screencast, I can't resize it.)

  • Like 2
Link to comment
Share on other sites

I am currently working on custom comment form output and custom comment list output. I copied `CommentForm.php` as `CommentFormUikit.php` and copied `CommentList.php` as `CommentListUikit.php`.

Renamed class names on these and extend base classes  files and removed not used codes and modified needed sections.

When i want to use my custom outputs :

<?php
// include customization classes
include __DIR__ . '/CommentListUikit.php';
include __DIR__ . '/CommentFormUikit.php';

// custom list output
echo $page->comments->render(['className' => 'CommentListUikit']);
// custom form output
echo $page->comments->renderForm(['className' => 'CommentFormUikit']);
?>

CommentListUikit.php

<?php

namespace ProcessWire;

class CommentListUikit extends CommentList
{
// do your customizations
}

CommentFormUikit.php

<?php

namespace ProcessWire;

class CommentFormUikit extends CommentForm
{
// do your customizations
}

Example output for uikit 3 frontend framework, still working on it, specially writing a javascript for comment form

425478768_EkranResmi2020-12-2218_26_31.thumb.png.3a57f88e62a1c95ade560619b57244f1.png

  • Like 1
Link to comment
Share on other sites

Thanks @ukyo. I'll try this in my next steps. 

In the meantime I have found out why my threaded comments - 'Reply Depth' etc. - didn't work. Threaded comments relies on jQuery in comments.min.js in wire/modules/Fieldtype/FieldtypeComments/

I load jQuery in my head with these lines:

Spoiler

<script type='text/javascript' src='https://code.jquery.com/jquery-3.5.1.min.js'></script>
<script type='text/javascript' src='https://code.jquery.com/jquery-migrate-3.3.1.min.js'></script>

 

I think Processwire has jQuery "built in", but have always been confused how to use it. When I just remove my lines from head, all my jQuery breaks. If I already have jQuery in my site, why doesn't the jQuery in the module work? Does Processwire require a specific version of jQuery?

The module's jQuery works fine when I copy it from comments.js to my template and replace jQuery with another var:

Spoiler

var jWhatever = jQuery.noConflict();

function CommentActionReplyClick() {
	
	var $this = jWhatever(this);
	var $item = $this.closest('.CommentListItem');
	...etc.

 

I have also removed all the cookie stuff from the module's javascript. I think without it the comment form name+email fields are prefilled with data from the logged-in user, which is what I needed.

Is there a way to add the Reply link with the foreach($page->comments as $comment) method? If not, I'll figure something out with @netcarver, @flydev ?? or @ukyo's suggestions - thanks!

 

Link to comment
Share on other sites

I can't figure this out. I have added a comment.php file in my templates/forms folder with the following:

Spoiler

<?php namespace ProcessWire;

class CustomComment extends CommentForm
{
	public function getFormMarkup() {
        echo '<p>Does this show up anywhere?</p>';
	}

}

?>

 

With this in the page's template:

Spoiler

    include_once $config->paths->templates . 'forms/comment.php';

	// comments form with all options specified (these are the defaults)
    echo $page->comments->renderForm(array(
    'className' => 'CustomComment',
    'headline' => '<h2>Share your thoughts</h2>',
    'successMessage' => '<p class=success>Thank you for your comment.</p>',
    'errorMessage' => '<p class=error>Your submission was not saved due to one or more errors. Please check that you have completed all fields before submitting again.</p>',
    'processInput' => true,
	...etc.

 

This doesn't do anything - the echo from comment.php doesn't show up anywhere. I am not an experienced/full-time PHP programmer. It is not obvious to me what is going on in these scripts. 

@ukyo, what does '// do your customizations ' look like? Could you or anyone else give a basic example?

Should I copy entire functions from CommentForm.php or CommentFormCustom.php (?), change a few things within those functions and then those customizations will replace the functions in /wire? Should I rename the functions?

Or does whatever I put in '// do your customizations ' run after CommentForm.php in /wire - adding not replacing?

I also tried to follow the instructions in CommentFormCustom.php, but did not understand any of it. I've copy/pasted different parts and functions from that file into my custom comment.php, but could not get a result with anything.

Continuing with this tomorrow... Any hints very much appreciated.

 

Link to comment
Share on other sites

@modifiedcontent Can you put these files under a folder something like : templates/extends or site/src. After do that can you add this path to wire classLoader.

You can do this on ready.php file or you can try it before apply your customizations (didn't try that).

<?php
// ready.php example

$template = $page->template->name;

if (in_array($template, ['template-with-comment-field'])) {
  wire('classLoader')->addNamespace('ProcessWire', wire('config')->paths->templates . '/extends');
  // or
  wire('classLoader')->addNamespace('ProcessWire', wire('config')->paths->site . '/src');
}

or (didn't tested)

<?php
wire('classLoader')->addNamespace('ProcessWire', wire('config')->paths->templates . '/extends');
// or
wire('classLoader')->addNamespace('ProcessWire', wire('config')->paths->site . '/src');

$page->comments->render(['className' => 'CommentListCustom']);
$page->comments->renderForm(['className' => 'CommentFormCustom']);

 

Link to comment
Share on other sites

Thanks @ukyo, but what is that supposed to do? I plan to have my custom files in templates/forms. What difference would putting them in templates/extend or site/src make? Why site/src - is adding folders outside templates a good idea?

Those classLoader lines apply to the entire folder, not a specific file?

Are the general principles how to work with classes and customize modules in Processwire explained anywhere? I haven't been able to find it. 

This produces a result:

Spoiler

include $config->paths->templates . 'inc/CommentListCustom.php';

echo $page->comments->render(array(
  'className' => 'CommentListCustom',
  'headline' => '<h2>Comments</h2>',
  'commentHeader' => 'Posted by {cite} on {created}',
  'dateFormat' => 'l, F jS Y g:i a',
  'encoding' => 'UTF-8',
  'admin' => false, // shows unapproved comments if true
));

 

CommentListCustom.php copied from the wire module into my templates/inc folder. The custom file is now used to display the comments. I can now make edits in that file to somehow change {cite} to the commenter's full name. 

Wtf is {cite} anyway? It's not a PHP variable. How is it defined? How can I redefine it? I can't do something like {cite} = $users->get({cite})->fullname; What syntax should I use? What rules apply to these {something} "thingies"?

Why does this produce Fatal Error  Uncaught Error: Call to a member function get() on null?

Spoiler

$cite = $comment->getFormatted('cite');
$cite = $users->get($cite)->fullname;

 

This seems to work though:

Spoiler

$cite = $comment->getFormatted('cite');
$cite = users()->get($cite)->fullname;

 

 

For the form it works the same of course:

Spoiler

include $config->paths->templates . 'forms/CommentFormCustom.php';

echo $page->comments->renderForm(array(
'className' => 'CommentFormCustom',
'headline' => '<h2>Share your thoughts</h2>',
'successMessage' => '<p class=success>Thank you for your comment.</p>',
...

 

Then make edits in CommentFormCustom.php as required. In my case I added 'hidden' to the cite and email input fields, so logged-in users only get a text field, don't have to enter any other info - the module enters logged-in user name and email in the hidden fields if you remove/turn off all the cookie stuff.

Two next issues to solve:

1. Is the upvote/downvote system cookie-based? What would it take to turn that into logged-in user ID-based? Or is that the default if I turn off cookies/remove cookie javascript?

2. Users will expect a way to delete and edit their comments. Has anyone done that? Suggestions welcome.

Link to comment
Share on other sites

  • 9 months later...
  • 2 months later...

 @tires , to use Full Name, or whatever field you need, I now use this in CommentListCustom:

Spoiler
protected function ___renderItem(Comment $comment, $options = array()) {

	...

	$options = is_array($options) ? array_merge($defaults, $options) : $defaults;
	...
	$cite = $comment->getFormatted('cite');
	$fullname = users()->get($cite)->fullname;
	...

...

	$placeholders = array(
		'id' => $comment->id,
		'cite' => $cite,
		'fullname' => $fullname,
		...

 

And then use {fullname} in your markup instead of {cite}.

 

Continuing my Christmas tradition; upgrading my websites. Last year I got a basic comment system working. This Christmas I want to add edit/delete buttons to comments, absolutely essential for any modern comment system. How can I do that?

I have a working comment system based on these CommentListCustom and CommentFormCustom files. 'delete | edit' buttons would go somewhere in CommentListCustom, something like this in the CommentFooter:

				<div class='CommentFooter'>
					<p class='CommentAction'>
						{reply}
						{permalink} | delete | edit
					</p>
				</div>

The 'delete | edit' buttons - later icons of course - should only show up for the author of the comment, so they would be wrapped in something like this:

if ( $user->isLoggedin() && $user->name == {cite} ) { echo 'delete | edit'; }

Using '{cite}' there would probably not work, right? What should I use instead?

To delete a comment I would have to identify the comment and then do something like $comment->delete(); somewhere I guess. These comments are not pages I think, so maybe deleting them works differently?

Comments are numbered, like id="Comment24" and data-comment="24". How can I target that ID to delete that comment?

Or could I just use clever/complicated PHP magic like $this to target the element the delete button is in? Or was that jQuery...? Are we using jQuery anyway to process these actions? I see $this->etc. is used a lot in CommentListCustom.

I see there is a 'delete comment' method here.

// basic usage
$mixed = $fieldtypeComments->deleteComment(Page $page, Field $field, Comment $comment);

And for an 'edit' button I would use updateComment()?

What values would these functions use? $page would be the page the comment is on I guess. Wouldn't $field be comment field by definition? Would the value for $comment be that ID number? Is there a code example how to use these somewhere?

The deleteComment() function in FieldtypeComments.module:

Spoiler
	/**
	 * Delete a given comment
	 *
	 * @param Page $page
	 * @param Field $field
	 * @param Comment $comment
	 * @param string $notes
	 * @return mixed
	 *
	 */
	public function deleteComment(Page $page, Field $field, Comment $comment, $notes = '') {
		
		$approved = $comment->isApproved();
		$database = $this->wire()->database;
		
		if($field->get('depth') > 0) {
			foreach($comment->children() as $child) {
				$this->deleteComment($page, $field, $child); 
			}
		}
		
		$table = $database->escapeTable($field->getTable());
		$sql = "DELETE FROM `$table` WHERE id=:id AND pages_id=:pages_id";
		$query = $database->prepare($sql); 
		$query->bindValue(':id', $comment->id, \PDO::PARAM_INT);
		$query->bindValue(':pages_id', $page->id, \PDO::PARAM_INT);
		$comments = $page->get($field->name); 
		
		try {
			if($approved) $this->triggerPageFieldSaveReady($page, $field);
			$result = $query->execute();
			if($comments) $comments->remove($comment); 
			$this->commentDeleted($page, $field, $comment, $notes); 
			if($approved) $this->triggerPageFieldSaved($page, $field);
			
		} catch(\Exception $e) {
			$this->error($e->getMessage()); 
			$result = false;
		}
		
		return $result;
	}

 

Should I just "do" `$this->deleteComment($page, $field, $comment);` and if triggered from within the element it will delete that comment including replies if any? Use jQuery or PHP?

Something like this?

Spoiler
<?php
if($input->post->deletecomment) {
	$this->deleteComment($page, $field, $comment);
}
?>

<form>
	<input type=submit name=deletecomment value='Delete comment'>
</form>

 

Or use jQuery as event handler and then somehow trigger a PHP function? I know how to post form data via ajax, but how would that work with `deleteComment($page, $field, $comment)`? The jQuery would send those variable values to a php file with the function that would send a result back to the element I guess.

This works to alert the comment ID:

Spoiler
<span class=deletecomment>delete</span>

<script>
jCmmnts('.deletecomment').click(function() {
	var comment = jCmmnts(this).closest('li').data('comment');
	alert( comment );
});
</script>

 

Now I can send that comment ID to PHP via ajax and do `deleteComment($page, $field, $comment)`. What should I use for $page and $field? I guess the ID of the page the comment is on, but what is $field supposed to be?

 

Link to comment
Share on other sites

How can I use $fieldtypeComments->deleteComment($page, $field, $comment) to delete a comment if I have the comment's ID?

I have the ID of the comment, but I guess this function needs the entire object? So I guess I first have to use this:

$comment = $fieldtypeComments->getCommentByID($page, $field, int $id);

Are $page and $field required for both? $page is the page where the comment is on I guess, but where do I get $field?

What does return value 'mixed' mean? I see the delete function returns a variable $result, so I'll try to echo that.

How should I put this together? Are there examples anywhere?

If I echo $page from within my comments.php file, I get an ID that should be usable for the delete function, but I get nothing from $field. What the hell is that $field supposed to be? Where can I get it?

This put in a template with the comments produces `Uncaught Error: Call to a member function deleteComment() on null`:

$fieldtypeComments->deleteComment( '3156', 'comments', '25' );

I get the same error on any $fieldtypeComments-> function. Should I use FieldtypeComments:: instead? Or $this->...? Or wire()something? Or "declare" a class or globals? Please point me to the basics if you know.

This produces a more promising `Uncaught TypeError: Argument 3 passed to FieldtypeComments::deleteComment() must be an instance of Comment, string given`:

FieldtypeComments::deleteComment( $page, $field, '25' );

Trying to get a $comment instance (?), this produces another error: `Fatal Error: Uncaught Error: Using $this when not in object context in ...`:

$comment = FieldtypeComments::getCommentByID($page, $field, '25');

I see there is also a public function deleteComment() in commentfield.php that doesn't require $field, but requires (?) $notes:

Spoiler
	public function deleteComment(Page $page, Comment $comment, $notes = '') {
		return $this->getFieldtype()->deleteComment($page, $this, $comment, $notes);
	}

I still get `Fatal Error: Uncaught Error: Call to undefined function deleteComment() in...` when I try that in different places in the template.

Getting closer. This produces some kind of result:

CommentField::deleteComment($page, 25, $notes = '');

Still results in Fatal Error: Uncaught TypeError: Argument 2 passed to CommentField::deleteComment() must be an instance of Comment, int given ... I have also tried $comment, $comment = "25" and "25", but got the same error. 

What is 'an instance of Comment'? How can I get it?

This produces an interesting error:

$comment = $page->comments->get('25');
CommentField::deleteComment($page, $comment, $notes = '');

Error: Exception: Class 'CommentArray' doesn't yet implement method 'makeBlankItem()' and it needs to. (in wire/core/WireArray.php line 197)

??

Link to comment
Share on other sites

Does anybody know how to use $fieldtypeComments->deleteComment($page, $field, $comment)? See previous post for details.

Or how to use functions like this in general. A 'basic usage' is given, but I can't find examples and whatever I try I get errors like 'Call to undefined function' or 'Argument 2 ... must be an instance of Comment' or 'Call to a member function ... on null' or 'Class 'CommentArray' doesn't yet implement method 'makeBlankItem()' and it needs to' or it complains about wrong use of $this because not in context or whatever.

Running out of ideas, so please help if you understand this stuff. 

Link to comment
Share on other sites

Hey @modifiedcontent. I’m not the best person to answer this because I’ve never used FieldtypeComments, but since there are no other takers, let’s see…

First and foremost, do you really need to call that method? It seems to me that it’s mostly intended for internal use by the usual save functionality. You should be able to delete a comment by just removing it from the WireArray and saving the Page or the Field.

What you want to do should work like this, I believe:

/* Get the field by whatever name you called it.
 * This will be of type CommentField. */
$field = $page->getField('mycommentsfield');

/* Get the Comment object you want to delete by
 * its ID. Note how we call getFieldtype() to
 * get to the Fieldtype itself. That will be
 * FieldtypeComments.
 * If you have already loaded the comments (and
 * the right pagination page) it may be better
 * to get it from there, as this will go all the
 * way to the database: */
$deleteMe = $field->getFieldtype()->getCommentById($page, $field, $id);

/* Now since you already have your CommentField
 * you can call deleteComment on that. It’s the
 * same thing as calling the method of the same
 * name on FieldtypeComments and putting $field
 * in the $field argument. */
$field->deleteComment($page, $deleteMe); //don’t need the notes
/* Get the field by whatever name you called it.
 * This will be of type CommentField. */
$field = $page->getField('mycommentsfield');

/* Get the Comment object you want to delete by
 * its ID. Note how we call getFieldtype() to
 * get to the Fieldtype itself. That will be
 * FieldtypeComments.
 * If you have already loaded the comments (and
 * the right pagination page) it may be better
 * to get it from there, as this will go all the
 * way to the database: */
$deleteMe = $field->getFieldtype()->getCommentById($id);

/* Now since you already have your CommentField
 * you can call deleteComment on that. It’s the
 * same thing as calling the method of the same
 * name on FieldtypeComments and putting $field
 * in the $field argument. */
$field->deleteComment($page, $deleteMe); //don’t need the notes

Now if you already had the Comment object, you could get all the information from there. Let’s assume it’s called $deleteMe again:

$deleteMe->field->deleteComment($deleteMe->page, $deleteMe); //note how the comment itself contains references to its CommentField and its Page

As to why the return type is mixed, if you check out the method’s code you’ll notice that it returns a variable called $result which may either be False, in case an exception happens when talking to the database, or if everything goes well it may be whatever $query->execute() returns. By default, DatabaseQuery->execute() returns an object of type PDOStatement, so it’s impossible to know the return type of deleteComment ahead of time. It might end up being a Boolean or it might end up being a PDOStatement, so it’s mixed.

Like I said, I haven’t tested any of this myself, so I may have missed something and the above code may be faulty.

  • Like 1
Link to comment
Share on other sites

Hello @Jan Romero, thank you so much. This gives me a lot of new stuff to work with and try tomorrow morning. ?

Happy New Year!

Edit: I kept getting similar errors with your suggestions, but after trying a lot of variations with your input, this seems to work:

$field = $page->getField('comments');
$comment = $field->getFieldtype()->getCommentById($page, $field, '26');
if ($comment !== NULL) { $field->deleteComment($page, $comment); }

Still not entirely sure what getFieldtype() does, but that is apparently essential. Thank you!

Now putting together the complete comment delete button solution, will post in next comment below...

  • Like 1
Link to comment
Share on other sites

Comment delete button

The delete button itself; only shows up for the logged-in author of the comment:

Spoiler
class CommentListCustom extends CommentList {

	protected $markup = array(
		'gravatar' => "<img class='CommentGravatar' src='{src}' alt='{alt}' />",
		'website' => "<a href='{href}' rel='nofollow' target='_blank'>{cite}</a>",
		...
		'item' => "
			<li id='Comment{id}' class='{class}' data-comment='{id}'>
              ...              
              <div class='CommentFooter'>
					<p class='CommentAction'>
						{reply}
						{permalink}
						{deletebutton}
					</p>
		...
                  
        'noticeSuccessClass' => 'success',
		'noticeErrorClass' => 'error',
	);
...
/**
* Render the comment 
*
...	 
*/
	protected function ___renderItem(Comment $comment, $options = array()) {
		...		
		$classes = $this->getCommentItemClasses($comment); 
		$gravatar = '';
		$permalink = '';
		$reply = '';
		$replies = '';

		if ($cite === $this->user->name) {
		$deletebutton = '<span class=deletecomment style="float:right"><ion-icon name=trash></ion-icon></span>';
		} else {
		$deletebutton = '';
		}
		
		if($this->options['useGravatar']) {
		...

		$placeholders = array(
			'id' => $comment->id,
			'cite' => $cite,
			'fullname' => $fullname,
			'deletebutton' => $deletebutton,
			...

 

jQuery to handle a click on the delete button via ajax:

Spoiler
jCmmnts('.deletecomment').click(function() {

	var comment = jCmmnts(this).closest('li').data('comment');
	var page = <?php echo $page ?>

	request = jCmmnts.ajax({ 
		url: window.location.origin,
		data: { deletecomment: comment, page: page },
		type: 'post',
	});

	request.done(function (response, textStatus, jqXHR){
			jCmmnts('li[data-comment=' + comment + ']').html( response );
	});

	request.fail(function (jqXHR, textStatus, errorThrown){
		console.error(
			"The following error occurred: "+
			textStatus, errorThrown
		);
	});

});	

 

PHP to process the ajax request and delete the comment:

Spoiler
if ( $input->post['deletecomment'] ) {

		// comment delete

		$page = $input->post['page'];
		$page = $pages->get($page);		
		
		$comment = $input->post['deletecomment'];
		
		$field = $page->getField('comments');
		$comment = $field->getFieldtype()->getCommentById($page, $field, $comment);

		$field->deleteComment($page, $comment); 

		echo 'comment deleted';
		
};

 

This seems to work. Let me know if you see mistakes or ways to do this better. 

Next I need a comment edit button...

 

Link to comment
Share on other sites

On 12/31/2021 at 8:51 PM, modifiedcontent said:

Hello @Jan Romero, thank you so much. This gives me a lot of new stuff to work with and try tomorrow morning. ?

Happy New Year!

Edit: I kept getting similar errors with your suggestions, but after trying a lot of variations with your input, this seems to work:

Haha yeah, sorry, I forgot to supply getCommentByID with the $page and $field arguments… Glad you got it working, happy New Year to you too!

Regarding comment editing, have you considered just rolling your own comment system with Pages (maybe even custom page classes) or multi fields like Repeaters? That would allow you to use common ProcessWire skills instead of fighting this specific module.

  • Like 1
Link to comment
Share on other sites

Quote

'... have you considered just rolling your own comment system with Pages ... ?'

Why would I do that? I now have the delete button figured out - with your help! - so why would I start over again?

I do normally avoid modules and try to use built-in methods that I understand. Agreed with your point. 

But for the comments section, this is a module by our fearless leader @ryanand as far as I understand it, I like his approach; looks like a solid future-proof basis to move forward with. 

So I need to sort out an edit button next, probably next Christmas... If anyone has any ideas, please post in this thread. I guess for an 'edit' button you would use updateComment()? Edit field via ajax?

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...