Customizing 'Comments' (code / tutorial)

Hi All,

As some of you have probably already seen from other posts around the elgg community I've been tinkering with having my own customized comments system for use within a plugin. So far I've had some pretty pleasing results (thanks to the support of the elgg community & despite my not especially solid programming).

So its time to share what I have so far - The end result is basically a comments form that allows for a comment (text, ->candid) a rating (radio button, ->rate) and a feature (checkbox, ->features). Of course this can be extended to whatever you want to get feedback on or whatever areas you want users to provide input. I have.

Two significant problems/issues so far are:

1. It turns out this will overwrite the default comments system for all other instances in other plugins (i.e the default BLOG, or PAGES etc). This might be fine for you - My intention was for it to be a comments system for the specific plugin (i.e so the comments form can relate to the specific plugin its housed in so to speak.)

2. The delete function for the comments works - but returns a fatal error before doing as desired.

Elgg community feedback & suggestions are greatly appreciated. This should be a resource for all to take advantage of & I hope in posting this I'm helping & not opening a big ol can of worms....

CODE TO HELP CUSTOMIZE COMMENTS!

1.0 myplugin/start.php

1.1 myplugin/actions/comments/add.php

1.2 myplugin/actions/comments/delete.php

1.3 myplugin/views/default/comments/forms/edit.php

2.0 Get the comments and display them

2.1 Add a delete button to each comment so the owner of the object can delete rubbish

2.2 Show the comments input form for users to add comments

 

1.0 -------> myplugin/start.php

 

<?php  

//all the other usual start.php stuff

 

function myplugin_annotate_comments($hook, $entity_type, $returnvalue, $params)

{

$entity = $params['entity'];

$full = $params['full'];

if (

($entity instanceof ElggEntity) && // Is the right type 

($entity->getSubtype() == 'myplugin') &&  // Is the right subtype

($entity->comments_on!='Off') && // Comments are enabled

($full) // This is the full view

)

{

// Display comments

return elgg_view_comments($entity);

}

}

//plus register the actions for the comments

register_action("myplugin/comment/add",false,$CONFIG->pluginspath . "myplugin/actions/comments/add.php");

register_action("myplugin/comment/delete",false,$CONFIG->pluginspath . "myplugin/actions/comments/delete.php");

?>

 

1.1 -------> myplugin/actions/comments/add.php

<?php

gatekeeper();

action_gatekeeper();

// Get input

$entity_guid = (int) get_input('entity_guid');

$comment_candid = get_input('candid_comment');

$comment_rate = get_input('rate_comment');

$comment_features = serialize(get_input('features_comment'));

 

// Make sure details aren't empty

if (empty($comment_candid) || empty($comment_rate)) {

register_error(elgg_echo("myplugin:commentblank"));

forward("mod/myplugin/read.php?mypluginpost={$entity_guid}");

//forward("pg/myplugin/{$entity_guid}");

// Start Saving the comment

} else {

// get an entity with the GUID

if ($entity = get_entity($entity_guid)) {

              

       try {

// create a new type of ElggObject for comments   

$myplugincomment = new ElggObject();   

$myplugincomment->subtype = "comment";   

$myplugincomment->owner_guid = $_SESSION['user']->getGUID();   

$myplugincomment->container_guid = $_SESSION['user']->getGUID();

$myplugincomment->access_id = 1; // logged in users   

$myplugincomment->parent_guid = $entity_guid; 

 

$myplugincomment->candid = $comment_candid;

$myplugincomment->rate = $comment_rate;

$myplugincomment->features = $comment_features;

$myplugincomment->save();  

if ($entity->owner_guid != $_SESSION['user']->getGUID())

notify_user($entity->owner_guid, $_SESSION['user']->getGUID(), elgg_echo('generic_comment:email:subject'), 

sprintf(

elgg_echo('generic_comment:email:body'),

$entity->title,

$_SESSION['user']->name,

$comment_text,

$entity->getURL(),

$_SESSION['user']->name,

$_SESSION['user']->getURL()

)

); 

system_message(elgg_echo("generic_comment:posted"));  

         add_to_river('river/object/myplugin/annotate','annotate',$_SESSION['user']->guid, $entity_guid);

       } catch (Exception $e) {

        register_error(elgg_echo("generic_comment:failure"));

}

       

} else {

register_error(elgg_echo("generic_comment:notfound"));

}

forward($entity->getURL());

}

?>

 

1.2 ------> myplugin/actions/comments/delete.php

 

<?php

gatekeeper();

$returnurl = full_url();

$guid = get_input('comment_guid');

$comment = get_entity($guid);

 

// Delete the myplugin post

$rowsaffected = $comment->delete();

if ($rowsaffected > 0) {

// Success message

system_message(elgg_echo("generic_comment:deleted"));

} else {

register_error(elgg_echo("generic_comment:notdeleted"));

}

 

forward($returnurl); 

?>

 

1.3 ------> myplugin/views/default/comments/forms/edit.php

<?php

 

if (isset($vars['entity']) && isloggedin()) {

 

$form_body = "<div class=\"contentWrapper\"><p class='longtext_editarea'><label>".elgg_echo('myplugin:comments:title')."<br /><small>".elgg_echo('myplugin:comments:help') . "</small></label>"; 

 

// candid_comment

$form_body .= "<br/><br/><label><strong>".elgg_echo('Write a comment: ') ."</strong><br />". elgg_view('input/text',array('internalname' => 'candid_comment')) . "</label></p>";

// rate_comment

$form_body .= "<label><strong>".elgg_echo('Rate this: ')."&nbsp;&nbsp; </strong><br />" . elgg_view('input/radio',array('internalname' => 'rate_comment', 'value'=>"2" , 'options' => array(elgg_echo("Poor") => "1", elgg_echo("Ordinary") => "2", elgg_echo("Good") => "3", elgg_echo("Impressive") => "4", elgg_echo("Amazing") => "5"))) . "</label>";

// features_comment

$form_body .= "<label><strong>".elgg_echo('Features: ')."&nbsp;&nbsp; </strong><br />" . elgg_view('input/checkboxes',array('internalname' => 'features_comment' , 'options' => array(elgg_echo("Original") => "Original" , elgg_echo("Smelly") => "Smelly" ))) ."</label>";

 

$form_body .= "<p>" . elgg_view('input/hidden', array('internalname' => 'entity_guid', 'value' => $vars['entity']->getGUID()));

$form_body .= elgg_view('input/submit', array('value' => elgg_echo("save"))) . "</p></div>";

echo elgg_view('input/form', array('body' => $form_body, 'action' => "{$vars['url']}action/myplugin/comment/add"));

   }

    

?>

 

2.0 -------> Get the comments and display them

<?php

// from within whatever page/view you have the user comments displayed on in your plugin

if($comments_on && $vars['entity'] instanceof ElggObject){

$composts = elgg_get_entities_from_metadata(array('metadata_names'=>'parent_guid','metadata_values'=>$vars['entity']->guid, 'type'=>'object', 'subtype'=>'comment'));

foreach($composts as $compost) {

$compostguid = $compost->guid;

$compostcreated = sprintf(elgg_echo("myplugin:strapline"), date("G:H j/m-Y",$vars['entity']->time_created)) ;

$owner = $compost->getOwnerEntity() ;

//set some basic pre-text for presenting the commentary responses.

$bytxt = elgg_echo('by');

$commenttxt = elgg_echo('Comment:');

$ratetxt = elgg_echo('Rating:');

$featurestxt = elgg_echo('Features:');

// $icon = "<p><a href=\"{$compost->getURL()}\"><img src=\"".$CONFIG->wwwroot."mod/myplugin/icon.php?mypluginguid=".$compostguid."&size=small\" heigth=\"40\" width=\"40\" /></a></p>";

$icon = elgg_view("profile/icon",array('entity' => $owner, 'size' => 'small')); 

 

$info = "<p class=\"owner_timestamp\"><small>{$compostcreated} {$bytxt} <a href=\"{$owner->getURL()}\">{$owner->name}</a></small></p>";

$info .= "<p>{$commenttxt} {$compost->candid}</p>";

$info .= "<p>{$ratetxt} {$compost->rate}</p>";

//this will return just a number I think - refer to the comments form.

$info .= "<p>{$featuretxt} {$compost->features}</p>";

//being the features are a checkbox you probably need to unserialize or work to get something more than just an 'array' 

 

2.1 -------> Add a delete button to each comment so the owner of the object can delete rubbish

if ( $compost->canEdit() ) {

$info .= elgg_view("output/confirmlink",

array( 'href' => $vars['url'] . "action/myplugin/comment/delete?comment_guid=" . $compost->getGUID(),

'text' => elgg_echo('delete'),

'confirm' => elgg_echo('deleteconfirm'),

));

 

2.2 -------> Show the comments input form for users to add comments (presented after existing comments are displayed)

// after you've ended the foreach routine at the start of 2.0 and use a new or different css div

 

echo elgg_view("comments/forms/edit",array('entity' => $vars['entity']));

 

  • *sigh* I'm not making any progress;

    anyone interested in being emailed the 'where-I'm-up-to' plugin to look at - please feel free to PM me...

    Cheers,

    Jimbo

  • Hey, James,

    It might be easier to host your plugin on a public source control repository like github.  That way people can see your progress and even contribute if they feel inspired!

  • Yeah I really should check out & use github, among other sites  -- I have had some progress;

    THIS WORKS!!! Although i can't believe how I'm going about getting a proper hold of the entity to delete it. Yikes. Seesh.  I mean seriously, - this is relying on checking if the text (candid) for the comment sent to the action file and the comment found using elgg_get_entities_from_metadata are the same. Makes me cringe, but it works.

    //the object and where the comments are displays features a delete link (button, kinda)

    if ($_SESSION['user']->isadmin()) {

    $info .= elgg_view("output/confirmlink",

    array( 'href' => $vars['url'] . "action/myplugin/comment/delete?comment_guid=" . $compost->guid,

    'text' => elgg_echo('delete'),

        'confirm' => elgg_echo('deleteconfirm'),

    ));

    }

    //delete.php action looks like this...

    gatekeeper();

    $returnurl = full_url();

    $guid = get_input('comment_guid');

     

    $the_comment = get_entity($guid);

    if (empty($the_comment)) {

    register_error(elgg_echo("generic_comment:notdeleted"));

    } else {

     

     

    $comment_delete_guid = $the_comment->guid;

    $comment_delete_parent_guid = $the_comment->parent_guid;

    $comment_delete_candid = $the_comment->candid;

     

    $returned_comments = elgg_get_entities_from_metadata(array('metadata_names'=>'parent_guid','metadata_values'=>$the_comment_parent_guid, 'type'=>'object', 'guid'=>$comment_delete_guid , 'subtype'=>'myplugincomment'));

    if (empty($returned_comments)) {

    echo ("failed to find the comment");

    forward($returnurl);

    }

     

    foreach ($returned_comments as $comment_to_delete) {

    if ($comment_to_delete->candid == $comment_delete_candid) {

    if ($comment_to_delete->guid == $comment_delete_guid) {

    $delete_this = $comment_to_delete;

    }

    }

    }

    $delete_this->delete();

    system_message(elgg_echo("generic_comment:deleted"));

    }

     

     

    // forward($returnurl); // or return to everyone.php ? yet to decide.

     

    TIME TO CRACK OUT THE CHAMPAGNE! ...or COOPERS PALE ALE. !!! :D :D :D

     

  • woah.....I had too much ale last night ;-P