Ronald Huereca Description: Allows you and your users to edit their comments inline. Admin and editors can edit all comments. Special Thanks: An extra special thanks goes out to Vivien from Inspiration Bit (http://www.inspirationbit.com). Without her, this plugin release wouldn't have been possible. Brett Terpstra from Circle Six Design (http://blog.circlesixdesign.com) helped fix a rather major bug as well during testing. Thank you Brett. Copyright 2007 Ronald Huereca (email : ron alfy [a t ] g m ail DOT com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ if (function_exists('wp_enqueue_script')) { wp_enqueue_script('ajax_edit_comments', get_bloginfo('wpurl') . '/wp-content/plugins/wp-ajax-edit-comments/js-includes/wp-ajax-edit-comments.js.php', array('jquery'), '1.0'); } class WPrapAjaxEditComments { var $commentClassName = "editComment"; //Do not edit this name var $commentAuthorName = "editAuthor"; //Do not edit this name var $skipDiv = false; var $minutes = 30; var $admin = "true"; var $cookieName = "WPrapAjaxEditCommentId";//Do not edit this name var $optionsName = "WPAjaxEditComments"; //Do not edit this name var $userOptionsName = "WPAjaxEditAuthorUserOptions"; var $adminOptions = false; var $userOptions = false; //Do not edit this name var $isAdminPage = "false"; //constructor function WPrapAjaxEditComments() { } //Run when the plugin is first activated function init() { $this->getAdminOptions(); } //Returns an array of admin options function getAdminOptions() { if ($this->adminOptions == false) { $optionsName = $this->optionsName; $adminOptions = array( 'allow_editing' => 'true', 'minutes' => '30', 'edit_text' => 'You may click on your name and/or comment to edit.', 'show_timer' => 'true' ); $options = get_option($optionsName); if (!empty($options)) { foreach ($options as $key => $option) $adminOptions[$key] = $option; } update_option($optionsName, $adminOptions); $this->adminOptions = $adminOptions; } return $this->adminOptions; } //Returns an array of user options function getUserOptions() { global $user_email; if ($this->userOptions == false) { if (empty($user_email)) {get_currentuserinfo();} if (empty($user_email)) { return ''; } $optionsName = $this->userOptionsName; $defaults = array('author_editing' => 'true', 'comment_editing' => 'true', 'admin_editing' => 'false', 'inline_editing' => 'false', 'show_links' => 'false' ); $userOptions = get_option($optionsName); if (!isset($userOptions)) { $userOptions = array(); } //See if an older version doesn't match the new defaults if (empty($userOptions[$user_email])) { $userOptions[$user_email] = $defaults; update_option(optionsName, $userOptions); } else { foreach ($userOptions[$user_email] as $key => $option) $defaults[$key] = $option; $userOptions[$user_email] = $defaults; //update_option(optionsName, $userOptions); } $this->userOptions = $userOptions; } return $this->userOptions; } //Adds a paragraph to the beginning of the text //Takes in the text, a comment ID, and a post ID function addEditParagraph($text, $id, $postId) { if (!$this->canEditPostsPage($postId)) { //todo - Add an option so admin can disable this $text = "

" . $text; return $text; } return $text; } //Add in place holders for the Edit, Delete, Spam, Disapprove buttons - Skip out if in the admin panel function addApprovalParagraph($text, $commentId, $postId) { if (empty($commentId) || empty($postId) || is_admin()) { return $text; } global $user_email; if (empty($user_email)) { get_currentuserinfo(); } if (empty($user_email)) { return $text; } $author_options = $this->getUserOptions(); //Get the author options if (!empty($author_options[$user_email])) { if ($author_options[$user_email]['show_links'] == "true") { return $text; } } $links = ''; if (current_user_can('edit_post', $postId)) $links .= 'Edit | Delete | Spam'; if (strlen($links) > 0) $text = $text . ''; return $text; } //Returns true or false depending if the admin can inline edit function canInlineEdit() { global $user_email; if (empty($user_email)) { get_currentuserinfo(); } if (empty($user_email)) { return "true"; } //not logged in so they don't have a choice $author_options = $this->getUserOptions(); //Get the author options if (!empty($author_options[$user_email])) { if ($author_options[$user_email]['inline_editing'] == "true") { return "false"; } } return "true"; } //Adds a div to the comment text with a class name so that the AJAX can change the text to a textbox function addCommentDiv($text) { global $comment; $className = "post"; if (is_admin()) { $className = "admin"; } if (empty($comment)) { return $text; } if (!$this->canEdit($comment->comment_ID, $comment->comment_post_ID) || !$this->canEditComment()) { return $text; } //Skip this if admin $text = $this->addEditParagraph($text, $comment->comment_ID, $comment->comment_post_ID); if ($this->skipDiv) { return $text; } //Regular expression to check if there is a div already added $pattern = '/div class=\"' . $this->commentClassName . '\"/i'; //If there is not a div already, add it in if (!preg_match($pattern, $text)) { $text = '
' . $text . '
'; } $text = $this->addApprovalParagraph($text, $comment->comment_ID, $comment->comment_post_ID); return $text; } //End function addCommentDiv() function addAuthorSpan($text) { global $comment; $className = "post"; if (is_admin()) { $className = "admin"; } if (!$this->canEdit($comment->comment_ID, $comment->comment_post_ID) || !$this->canEditAuthor()) { return $text; } //Regular expression to check if there is a div already added $pattern = '/span class=\"' . $this->commentAuthorName . '\"/i'; //If there is not a div already, add it in if (!preg_match($pattern, $text)) { $text = '' . $text . ''; } return $text; } //End function addAuthorDiv() //Prints out the admin page function printAdminPage() { $WPAjaxEditComments = $this->getAdminOptions(); if (!empty($savedOptions)) { $WPAjaxEditComments = $savedOptions; } if (isset($_POST['update_wp_ajaxEditCommentSettings'])) { $error = false; $updated = false; //Validate the comment time entered if (isset($_POST['wpAJAXCommentTime'])) { $commentTimeErrorMessage = ''; $commentClass = 'error'; if (!preg_match('/^\d+$/i', $_POST['wpAJAXCommentTime'])) { $commentTimeErrorMessage = "Comment time must be a numerical value"; $error = true; } elseif($_POST['wpAJAXCommentTime'] < 1) { $commentTimeErrorMessage = "Comment time must be greater than one minute."; $error = true; } else { $WPAjaxEditComments['minutes'] = $_POST['wpAJAXCommentTime']; $updated = true; } if (!empty($commentTimeErrorMessage)) { ?>
">

optionsName, $WPAjaxEditComments); $this->adminOptions = $WPAjaxEditComments; ?>

Settings successfully updated.

">

WP AJAX Edit Comment


" id="edit_text"/>

Allow Anyone to Edit Their Own Comments?

Selecting "No" will turn off comment editing for everyone except admin types who have post and page editing permissions.

    

Show a Countdown Timer?

Selecting "No" will turn off the countdown timer for non-admin commentators.

    

getUserOptions(); //Save the updated options to the database if (isset($_POST['wpAJAXAuthor']) && isset($_POST['wpAJAXComment']) && isset($_POST['wpAJAXAdminEdits'])&& isset($_POST['wpAJAXInlineEdits'])&& isset($_POST['wpAJAXLinks'])) { if (isset($user_email)) { $author_options[$user_email]['author_editing'] = $_POST['wpAJAXAuthor']; $author_options[$user_email]['comment_editing'] = $_POST['wpAJAXComment']; $author_options[$user_email]['admin_editing'] = $_POST['wpAJAXAdminEdits']; $author_options[$user_email]['inline_editing'] = $_POST['wpAJAXInlineEdits']; $author_options[$user_email]['show_links'] = $_POST['wpAJAXLinks']; ?>

Settings successfully updated.

userOptionsName, $author_options); $this->userOptions = $author_options; } } //Get the author options if (!empty($author_options[$user_email])) { $author = $author_options[$user_email]['author_editing']; $comment = $author_options[$user_email]['comment_editing']; $adminEdits = $author_options[$user_email]['admin_editing']; $inlineEdits = $author_options[$user_email]['inline_editing']; $showLinks = $author_options[$user_email]['show_links']; } ?>
">

WP AJAX Edit Comment - Individual User Options

Turn On Name Editing?

Selecting "Yes" will enable your ability to edit the author details.

    

Turn On Comment Editing?

Selecting "Yes" will enable your ability to edit a user's comment.

    

Turn Off Comment Editing in Admin Panel?

Selecting "Yes" will disable comment editing in the Admin Comments Panel.

    

Turn Off Inline Editing?

Selecting "Yes" will disable the "edit in place" type comment editing in a post. This only affects the comment and not the author editing. The admin panel is unaffected by this option.

    

Turn Off Comment Post Links?

Selecting "Yes" will disable the links that show up underneath a comment. These links allow you to edit, delete, or mark a comment as spam.

    

JS(); } }//End function addHeaderJS function addAdminHeaderJS() { global $user_email; if (empty($user_email)) { get_currentuserinfo(); } if (empty($user_email)) { return; } $author_options = $this->getUserOptions(); //Get the author options if (!empty($author_options[$user_email])) { if ($author_options[$user_email]['admin_editing'] == "true") { return; } } $this->JS(); } function JS() { echo "\n"; } //Returns a comment for editing in a textbox //Takes in a comment id function getComment($id) { global $wpdb; if (!$this->canEdit($id, $post->ID)) { return 0; } //mysql_query("SET NAMES 'utf8'", $conn); $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments WHERE comment_ID = ".$id); if (!$comment) { return 0; } //Get the comment ready for the textbox $content = apply_filters('comment_edit_save', $comment->comment_content); return $content; }//End function getComment function deleteComment($id) { $comment = get_comment($id); if (!$comment) { return false; } if ( current_user_can( 'edit_post', $comment->comment_post_ID) ) { if (!wp_delete_comment($id)) { return true; } } else { return false; } return true; } function spamComment($id) { $comment = get_comment($id); if (!$comment) { return false; } if ( current_user_can( 'edit_post', $comment->comment_post_ID) ) { if (!wp_set_comment_status($id, 'spam')) { return false; } } else { return false; } return true; } function disapproveComment($id) { global $post; if (empty($post)) { return; } if ( current_user_can( 'edit_post', $post->ID ) && current_user_can( 'moderate_comments' ) ) if (!wp_set_comment_status( $id, 'hold' )) { return false; } else return false; return true; } //Strips the ID to just numbers function getCommentID($id) { preg_match('/([0-9]+)$/i', $id, $matches); if (is_numeric($matches[1])) { return $matches[1]; } else { return 0; } } //End function getCommentID //Returns the text such as "You may click on author/comment to edit" function getEditText() { $options = $this->getAdminOptions(); return apply_filters('the_title',$options['edit_text']); } //Returns how much time is left to edit on a comment in a comma deliminated variable //Returns $minutes,$seconds //Takes in a comment ID //One concern here is if the admin increases the time in the admin panel - The user will be under the impression that there is more time to edit than there really is. This is a minor and rare bug, so I chose to leave it alone. function getTimeLeft($id) { global $wpdb; if (empty($id)) { return "0,0"; } $adminEdit = $this->getAdminOptions(); $adminMinutes = $adminEdit['minutes']; $query = "SELECT UNIX_TIMESTAMP(comment_date) time FROM $wpdb->comments where comment_ID = $id"; //Get the IP, Date, and Timestamp $comment = $wpdb->get_row($query, ARRAY_A); $timestamp = $comment['time']; //Check to see if there's a valid cookie //Get the time elapsed since making the comment $time = time()-$timestamp; $timeLeft = ($adminMinutes * 60) - $time; //seconds if ($timeLeft <= 0) { return "0,0"; } $minutesPassed = floor($timeLeft/60); $seconds = $timeLeft - ($minutesPassed*60); return "$minutesPassed,$seconds"; }//end function getTimeLeft //Saves the author to the database /*id = The comment id url = The author's url name = The author's name*/ function saveAuthor($id, $url, $name) { global $wpdb; if (!$this->canEdit($id, $post->ID)) { return 0; } if (!isset($name)) { return 0; } if (trim($name) == '') { return 0; } $url = urldecode($url); $name = urldecode($name); $url = trim(apply_filters('comment_url', $url)); $saveUrl = apply_filters('pre_comment_author_url', $url); $name = apply_filters('comment_author', $name); $saveName = apply_filters('pre_commment_author_name', $name); if(!$wpdb->query("UPDATE $wpdb->comments SET comment_author = '{$saveName}', comment_author_url = '{$saveUrl}' WHERE comment_ID = $id")) { return 0; } $url = stripslashes($url); $name = stripslashes($name); $returnText = ''; if (!empty($url)) { $returnText = '' . $name . ''; } else { $returnText = $name; } //For WP Cache if (function_exists("wp_cache_get_postid_from_comment")) { wp_cache_get_postid_from_comment($id); } return $returnText; } //End function saveAuthor //Saves the edited comment to the database function saveComment($id, $content) { global $wpdb, $post; if (trim($content) == '') { return 0; } if (!$this->canEdit($id, $post->ID)) { return 0; } $content = urldecode($content); $content = apply_filters('comment_save_pre', $content); $saveContent = apply_filters('pre_comment_content', $content); if(!$wpdb->query("UPDATE $wpdb->comments SET comment_content = '{$saveContent}' WHERE comment_ID = $id")) { return 0; } $this->skipDiv = true; $content = apply_filters('comment_text', $content); $content = $this->addEditParagraph($content, $id, $post->ID); $this->skipDiv = false; //For WP Cache if (function_exists("wp_cache_get_postid_from_comment")) { wp_cache_get_postid_from_comment($id); } return stripslashes($content); } //end function saveComment //Determines if a comment can be edited or not based on the ID and time elapsed //$id = The comment id //$postId = The post id for the comment //Returns true if the comment can be edited, false if not function canEdit($id, $postId) { global $wpdb; if (empty($id)) { return false; } //Return true if the user can edit the comment if ($this->canEditPostsPage($postId)) { return true; } //Checks to see if the admin has allowed comment editing $adminEdit = $this->getAdminOptions(); $adminEdit = $adminEdit['allow_editing']; if (empty($adminEdit)) { $adminEdit = $this->admin; } if ($adminEdit != 'true') { return false; } $query = "SELECT UNIX_TIMESTAMP(comment_date) time, comment_author_IP, comment_date_gmt FROM $wpdb->comments where comment_ID = $id"; //Get the IP, Date, and Timestamp $comment = $wpdb->get_row($query, ARRAY_A); $hash = md5($comment['comment_author_IP'] . $comment['comment_date_gmt']); $timestamp = $comment['time']; //Check to see if there's a valid cookie if (isset($_COOKIE[$this->cookieName . $id . $hash])) { //Get the time elapsed since making the comment $time = time()-$timestamp; $minutesPassed = round(((($time%604800)%86400)%3600)/60); //Get the time the admin has set for minutes $minutes = $this->getAdminOptions(); $minutes = $minutes['minutes']; if (!is_numeric($minutes)) { $minutes = $this->minutes; } if ($minutes < 1) { $minutes = $this->minutes; } //Compare the minutes passed to the admin minutes if ($minutesPassed) { if ($minutesPassed > $minutes) { return false; } } return true; } return false; }//end function canEdit //Returns true if a person can edit a post/page //Returns false otherwise //Called by canEdit() and setCommentCookie function canEditPostsPage($postId) { //Stolen, err, borrowed from edit_comment_link() if (!current_user_can('edit_page', $postId)) {return false; } if (!current_user_can('edit_post', $postId)) {return false; } return true; }//end function canEditPostsPage //Returns true unless the user has disabled author editing function canEditAuthor() { global $user_email; if (empty($user_email)) { get_currentuserinfo(); } if (empty($user_email)) { return true; } $author_options = $this->getUserOptions(); //Get the author options if (!empty($author_options[$user_email])) { if ($author_options[$user_email]['author_editing'] == "false") { return false; } } return true; } //end function canEditAuthor //Returns true unless the user has disabled comment editing function canEditComment() { global $user_email; if (empty($user_email)) { get_currentuserinfo(); } if (empty($user_email)) { return true; } $author_options = $this->getUserOptions(); //Get the author options if (!empty($author_options[$user_email])) { if ($author_options[$user_email]['comment_editing'] == "false") { return false; } } return true; } //Sets a comment cookie for the commentator (treat as a private function) function setCommentCookie($commentId) { global $comment, $wpdb; //Return if setting the cookie is unnecessary if ($this->canEditPostsPage($post->ID)) { return $commentId; } //Get the IP, Date, and Timestamp if (empty($comment)) { $comment = $wpdb->get_row("SELECT * FROM $wpdb->comments where comment_ID = $commentId", ARRAY_A); } $hash = md5($comment['comment_author_IP'] . $comment['comment_date_gmt']); //Get the time the admin has set for minutes $minutes = $this->getAdminOptions(); $minutes = $minutes['minutes']; if (!is_numeric($minutes)) { $minutes = $this->minutes; } if ($minutes < 1) { $minutes = $this->minutes; } //Set the cookie $cookieName = $this->cookieName . $commentId . $hash; $value = $cookieName; $expire = time()+60*$minutes; if (!isset($_COOKIE[$cookieName])) { setcookie($cookieName, $value, $expire, COOKIEPATH, COOKIE_DOMAIN); } return $commentId; } //end function setCommentCookie }//End Class WPrapAjaxEditComments if (class_exists("WPrapAjaxEditComments")) { $rap_ajaxComment = new WPrapAjaxEditComments(); } //Initialize the admin panel function WPrapAjaxEditComments_ap() { global $rap_ajaxComment; if (!isset($rap_ajaxComment)) { return; } if (function_exists('add_options_page')) { add_options_page('AJAX Edit Comments', 'AJAX Edit Comments', 9, basename(__FILE__), array(&$rap_ajaxComment, 'printAdminPage')); } if (function_exists('add_submenu_page')) { add_submenu_page('profile.php', "AJAX Edit Comments Options","AJAX Edit Comments", 9, basename(__FILE__), array(&$rap_ajaxComment, 'printAuthorPage')); } } //Template tag WPrapAjaxEditComments_CanEdit //Returns true if a user can edit - False if they can't - Must be run within the loop //Also returns false if people are admins function WPrapAjaxEditComments_CanEdit() { global $comment, $rap_ajaxComment; //If we're not in the loop, return false if (!isset($comment) || !isset($rap_ajaxComment)) { return false; } //If admin, return false if ($rap_ajaxComment->canEditPostsPage($comment->comment_post_ID)) { return false; } //Find out if the user can edit if ($rap_ajaxComment->canEdit($comment->comment_ID, $comment->comment_post_ID)) { return true; } return false; } //Yay, actions. if (isset($rap_ajaxComment)) { add_action('admin_menu', 'WPrapAjaxEditComments_ap'); add_action('admin_head', array(&$rap_ajaxComment, 'addAdminHeaderJS')); add_action('wp_head', array(&$rap_ajaxComment, 'addHeaderJS')); add_action('comment_post', array(&$rap_ajaxComment, 'setCommentCookie')); add_action('activate_wp-ajax-edit-comments/wp-ajax-edit-comments.php', array(&$rap_ajaxComment, 'init')); //Yay, filters. add_filter('comment_text', array(&$rap_ajaxComment, 'addCommentDiv'), '1000'); //Low priority so other HTML can be added first add_filter('get_comment_author_link', array(&$rap_ajaxComment, 'addAuthorSpan'), '1000'); //Low priority so other HTML can be added first } ?>