Enhance Your WordPress Comments with a Mention Feature

Doyin Faith Kasumu
Share

Many WordPress sites allow visitors to share comments on blog posts. There are several WordPress plugins that also enable visitors to leave a reply to comments. However, this process can get confusing when more than one author is replied to or referenced in the comment.

In this tutorial, I’ll be covering how to write a handy WordPress plugin that brings a Twitter-like mention feature right into our WordPress site, to allow readers to tag each other in comments.

At the end of this tutorial, I’ll provide a link to download the plugin which also has some additional features and a link to view the plugin on GitHub.

mention feature comments

Coding the Plugin

All WordPress plugins are PHP files located at /wp-content/plugins/ directory. In here, we create a PHP file wp-mention-plugin.php.

Next, we include the plugin header, otherwise WordPress won’t recognize our plugin.

<?php
/**
 * Plugin Name: WP Mention Plugin
 * Plugin URI: https://sitepoint.com
 * Description: Mention both registered and non registered @comment__author in comments
 * Version: 1.0.0
 * Author: Doyin Faith Kasumu
 * Author URI: http://t2techblog.com
 * License: GPL2
 */

Now we create the plugin class as follows:

class wp_mention_plugin {

//codes

All our action and filter hooks will go into the initialize() method, since we’re making this our constructor, the first method called when the class is instantiated.

    public static function initialize() {

        add_filter( 'comment_text', array ( 'wp_mention_plugin', 'wpmp_mod_comment' ) );

        add_action( 'wp_set_comment_status', array ( 'wp_mention_plugin', 'wpmp_approved' ), 10, 2 );

        add_action( 'wp_insert_comment', array ( 'wp_mention_plugin', 'wpmp_no_approve' ), 10, 2 );
    }

Code Explanation

The comment_text filter hook filters the text of comments to be displayed. The wp_set_comment_status action hook is triggered immediately when the status of a comment changes, and the wp_insert_comment action hook is triggered immediately when a comment is submitted.

We will be styling any name with a preceeding ‘@’ symbol without quotes, and this is why we need the comment_text filter hook.

In WordPress sites where comments are held for moderation before being approved, we need the wp_set_comment_status action hook to track newly approved comments for the mentioned authors.

The wp_insert_comment is needed to track comments for the mentioned author, in cases where comments were never held for moderation but automatically approved.

Now let’s create the functions called in our initialize() method. First off, the wpmp_mod_comment()

    public static function wpmp_mod_comment( $comment ) {

        // we set our preferred @mention text color here
        $color_code  = '#00BFFF';

        $pattern     = "/(^|\s)@(\w+)/";
        $replacement = "<span style='color: $color_code;'>$0</span>";
        $mod_comment = preg_replace( $pattern, $replacement, $comment );

        return $mod_comment;
    }

Here, we create a method wpmp_mod_comment() meaning: WP Mention Plugin Modify Comment. The function accepts a single parameter, which is the comment we’re modifying. Don’t worry about this parameter, WordPress handles it.

The $pattern variable creates a simple regular expression pattern, which determines whether @any__comment__author__name is being mentioned in any comments. When things like admin@sitepoint are being included in a comment, they don’t get recorded as a valid mention. Valid mentions will be styled in a deep sky blue color.

If you would like to change the color of @mention text, just change the value of the $color_code variable.

Before we proceed further, let’s create the method that handles the notification email sent to the mentioned comment authors.

    private static function wpmp_send_mail( $comment ) {
        $the_related_post        = $comment->comment_post_ID;
        $the_related_comment     = $comment->comment_ID;
        $the_related_post_url    = get_permalink( $the_related_post );
        $the_related_comment_url = get_comment_link( $the_related_comment );

        // we get the mentions here
        $the_comment = $comment->comment_content;
        $pattern     = "/(^|\s)@(\w+)/";

        // if we find a match of the mention pattern
        if ( preg_match_all( $pattern, $the_comment, $match ) ) {

            // remove all @s from comment author names to effectively
            // generate appropriate email addresses of authors mentioned
            foreach ( $match as $m ) {
                $email_owner_name = preg_replace( '/@/', '', $m );
                $email_owner_name = array_map( 'trim', $email_owner_name );
            }

            /**
             * This part is for For full names, make comment authors replace spaces them  with
             * two underscores. e.g, John Doe would be mentioned as @John__Doe
             *
             * PS: Mentions are case insensitive
             */
            if ( preg_match_all( '/\w+__\w+/', implode( '', $email_owner_name ) ) ) {
                $email_owner_name = str_ireplace( '__', ' ', $email_owner_name );
            }

            // we generate all the mentioned comment author(s) email addresses
            $author_emails = array_map( 'self::wpmp_gen_email', $email_owner_name );

            // ensure at least one valid comment author is mentioned before sending email
            if ( ! is_null( $author_emails ) ) {
                $subj = '[' . get_bloginfo( 'name' ) . '] Someone mentioned you in a comment';

                $email_body = "Hello, someone mentioned you in a comment($the_related_comment_url)".
                              " at MyBlog.com. Here is a link to the related post: $the_related_post_url";

                wp_mail( $author_emails, $subj, $email_body );

            }
        }
    }

Code Explanation

In the above method, we filter the comment to check if anyone is being mentioned. And if true, we remove the preceeding ‘@’ symbol before the comment author name, so that we can generate the comment author info from the database using the name.

At times, comment authors do fill in full names, for example ‘John Doe’, or names with spaces as their comment author name. In cases like this, anyone mentioning them must replace spaces in the name with double underscores. So starting from the line if ( preg_match_all( '/\w+__\w+/', implode( '', $email_owner_name ) ) ) .... we ensure that all double underscores in @mention text gets converted into spaces.

We then generate the mentioned comment author email address using the wpmp_gen_email() method we’ll be creating next. The $email_body variable and the wp_mail() function stores and sends the notification email respectively, with a link to the corresponding comment and post.

NOTE If you noticed in the codes, mentioned comment authors and their email addresses are stored in an array, this is just in case more than one comment author is mentioned.

Remember to change the line MyBlog.com in $email_body to your desired site name.

    public static function wpmp_gen_email( $name ) {
        global $wpdb;

        $name  = sanitize_text_field( $name );
        $query = "SELECT comment_author_email FROM {$wpdb->comments} WHERE comment_author = %s ";

        $prepare_email_address = $wpdb->prepare( $query, $name );
        $email_address         = $wpdb->get_var( $prepare_email_address );

        return $email_address;
    }

Code Explanation

I’ve talked much on this method earlier, it simply generates the mentioned comment author email. The $name string parameter it accepts is the comment author name. Then it gets the mentioned comment author info from the database using the comment author name. To prevent an SQL attack, we use the WordPress prepare() function to ensure queries are safely handled.

Now we create two more methods which track whether a comment is first held for moderation or not, before sending the notification email.

    public static function wpmp_approved( $comment_id, $status ) {
        $comment = get_comment( $comment_id, OBJECT );
        ( $comment && $status == 'approve' ? self::wpmp_send_mail( $comment ) : null );
    }

    public static function wpmp_no_approve( $comment_id, $comment_object ) {
        ( wp_get_comment_status( $comment_id ) == 'approved' ? self::wpmp_send_mail( $comment_object ) : null );
    }

The wpmp_approved() firstly checks if a comment with $comment_id held for moderation is approved, before calling the wpmp_send_mail() method which sends the notification email.

While wpmp_no_approve() calls the wpmp_send_mail() method which sends the email notification immediately when a comment is being automatically approved, without first holding for moderation.

Before the plugin can do what we’ve just coded it to do, we have to instantiate the class wp_mention_plugin we’ve just worked on, and call the initialize() method which registers our needed action and filter hooks.

}

$wp_mention_plugin = new wp_mention_plugin;
$wp_mention_plugin->initialize();

?>

plugin notification feature

Conclusion

In this tutorial, I covered how to create a handy WordPress plugin that brings a Twitter-like mention feature right into our WordPress site.

You can download Atmention in Comment here, a plugin I created that handles the mention feature integration with a few more features. Otherwise you can check out the plugin: WP Mention Plugin code on GitHub.