Make WordPress Core

Opened 13 years ago

Last modified 21 months ago

#18630 new feature request

Custom Comment Validation Error

Reported by: bandonrandon's profile bandonrandon Owned by:
Milestone: Awaiting Review Priority: normal
Severity: minor Version: 3.3
Component: Comments Keywords: has-patch
Focuses: Cc:


One of the things that bugs me about WordPress is not being able to customize the wp_die() function that is called on comment form validation. I have seen some people sugget core hacks, eek. I'm hoping that a hook is added to allow overriding of the default wp_die(). Maybe even a new template file wp_error.php that would be called first.

I haven't found a lot of discussion on this in trac just #11286 and #10551

Attachments (2)

18630.diff (4.9 KB) - added by mdgl 9 years ago.
18630.2.diff (4.9 KB) - added by mdgl 9 years ago.

Download all attachments as: .zip

Change History (14)

#1 @nacin
13 years ago

There's likely a ticket or five regarding this, beyond those two.

I don't think overriding the default wp_die() is what should be done here. (And theming it is currently possible.) Rather, the theme should be able to register support for error handling -- add_theme_support('comment-error-handling'). Or perhaps comment_form(), if used, would be enough. (Or require both.) Then we could send stuff back to that page.

Unfortunately we'd probably want to store content in a cookie so we can display it again, rather than lose it, but that's too much data for a cookie. So we might need to change how we POST, and send it to the post instead of wp-comments-post.php. Big changes here.

#2 @jsherk
13 years ago

  • Cc jsherk added

Definitely something needs to be done. Even if you could at least customize the message that appears!

Anyways, here is a modified version of wp-comments-post.php for v3.2.1

It sends the error message back to the comment page you came from as GET data.

You need to place this code in whatever theme file is calling the comment form (for example single.php) but it would be nice if this was incorporated right into the comment form itself. This code will show the error message on the comment page that the error appeared on:

  <?php if ($_GET['comment_error_msg']) { // Display Comment Error Message ?>
    <div class="comment_error_message">Comment <?php echo $_GET['comment_error_msg']; ?></div>
  <?php } ?>

And here is the modified part of the code for wp-comments-post.php (v3.2.1)
Changes start after line 74 where it says $comment_type = ''; :

 * Handles Comment Post to WordPress and prevents duplicate comment posting.
 * @package WordPress

	header('Allow: POST');
	header('HTTP/1.1 405 Method Not Allowed');
	header('Content-Type: text/plain');

/** Sets up the WordPress Environment. */
require( dirname(__FILE__) . '/wp-load.php' );


$comment_post_ID = isset($_POST['comment_post_ID']) ? (int) $_POST['comment_post_ID'] : 0;

$post = get_post($comment_post_ID);

if ( empty($post->comment_status) ) {
	do_action('comment_id_not_found', $comment_post_ID);

// get_post_status() will get the parent status for attachments.
$status = get_post_status($post);

$status_obj = get_post_status_object($status);

if ( !comments_open($comment_post_ID) ) {
	do_action('comment_closed', $comment_post_ID);
	wp_die( __('Sorry, comments are closed for this item.') );
} elseif ( 'trash' == $status ) {
	do_action('comment_on_trash', $comment_post_ID);
} elseif ( !$status_obj->public && !$status_obj->private ) {
	do_action('comment_on_draft', $comment_post_ID);
} elseif ( post_password_required($comment_post_ID) ) {
	do_action('comment_on_password_protected', $comment_post_ID);
} else {
	do_action('pre_comment_on_post', $comment_post_ID);

$comment_author       = ( isset($_POST['author']) )  ? trim(strip_tags($_POST['author'])) : null;
$comment_author_email = ( isset($_POST['email']) )   ? trim($_POST['email']) : null;
$comment_author_url   = ( isset($_POST['url']) )     ? trim($_POST['url']) : null;
$comment_content      = ( isset($_POST['comment']) ) ? trim($_POST['comment']) : null;

// If the user is logged in
$user = wp_get_current_user();
if ( $user->ID ) {
	if ( empty( $user->display_name ) )
	$comment_author       = $wpdb->escape($user->display_name);
	$comment_author_email = $wpdb->escape($user->user_email);
	$comment_author_url   = $wpdb->escape($user->user_url);
	if ( current_user_can('unfiltered_html') ) {
		if ( wp_create_nonce('unfiltered-html-comment_' . $comment_post_ID) != $_POST['_wp_unfiltered_html_comment'] ) {
			kses_remove_filters(); // start with a clean slate
			kses_init_filters(); // set up the filters
} else {
	if ( get_option('comment_registration') || 'private' == $status )
		wp_die( __('Sorry, you must be logged in to post a comment.') );

$comment_type = '';

//MOD Customize comment error message.
//Need to add the following code to your comments.php file wherever you want error message to display:
  <?php if ($_GET['comment_error_msg']) { // Display Comment Error Message ?>
    <div class="comment_error_message">Comment <?php echo $_GET['comment_error_msg']; ?><br>Note: If your comment text disappeared, try clicking your browser BACK button.</div>
  <?php } ?>
$comment_error_true = false; //MOD new code
if ( '' == $comment_content ) {
    $comment_error_msg = __('Error: please type a comment.'); //MOD new code
    $comment_error_true = true; //MOD new code
    //wp_die( __('Error: please type a comment.') ); //original

if ( get_option('require_name_email') && !$user->ID ) {
	if ( 6 > strlen($comment_author_email) || '' == $comment_author ) {
        $comment_error_msg = __('Error: please fill the required fields (name, email).'); //MOD new code
        $comment_error_true = true; //MOD new code
        //wp_die( __('Error: please fill the required fields (name, email).') ); //original
	} elseif ( !is_email($comment_author_email)) {
        $comment_error_msg = __('Error: please enter a valid email address.'); //MOD new code
        $comment_error_true = true; //MOD new code
        //wp_die( __('Error: please enter a valid email address.') ); //original

//MOD Original code is now in the ELSE statement
if (true == $comment_error_true) { //MOD new code

    //Set this to false to use default wp_die page
    $use_comment_custom_error_page = true; //MOD new code

    if ($use_comment_custom_error_page) { //MOD new code
        $location = get_permalink() . '?comment_error_msg=' . urlencode($comment_error_msg); //MOD new code
        if ( !$user->ID ) { //MOD new code
        	$comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000); //MOD new code
        	setcookie('comment_author_' . COOKIEHASH, $comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); //MOD new code
        	setcookie('comment_author_email_' . COOKIEHASH, $comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); //MOD new code
        	setcookie('comment_author_url_' . COOKIEHASH, esc_url($comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); //MOD new code
            //setcookie('comment_content_' . COOKIEHASH, $comment_content, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN); //MOD new code //TO DO: Figure out how to get Comment field to re-appear and not be deleted.
        } //MOD new code
    } else { //MOD new code
        wp_die($comment_error_msg); //MOD new code //This performs the default comment error page action
    } //MOD new code
} else { //MOD new code

    //Original unmodified code STARTS here
    $comment_parent = isset($_POST['comment_parent']) ? absint($_POST['comment_parent']) : 0;
    $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
    $comment_id = wp_new_comment( $commentdata );
    $comment = get_comment($comment_id);
    if ( !$user->ID ) {
    	$comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000);
    	setcookie('comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
    	setcookie('comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
    	setcookie('comment_author_url_' . COOKIEHASH, esc_url($comment->comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
    $location = empty($_POST['redirect_to']) ? get_comment_link($comment_id) : $_POST['redirect_to'] . '#comment-' . $comment_id;
    $location = apply_filters('comment_post_redirect', $location, $comment);
    //Original unmodified code ENDS here

} //MOD new code


#3 @markoheijnen
12 years ago

  • Cc marko@… added

#4 @chriscct7
9 years ago

  • Keywords needs-patch added

9 years ago

#5 @mdgl
9 years ago

  • Keywords has-patch added; needs-patch removed

Patch uploaded that adds an optional parameter to wp_new_comment() enabling callers to receive a WP_Error object return rather than dying. This follows the idiom used on wp_insert_post() and wp_set_comment_status() for example.

The treatment for check_comment_flood_db() uses private global variables and is rather ugly but I cannot think of a cleaner way of maintaining complete backwards compatibility with filter/action order and so on. Suggestions for better solutions are welcome!

With this fix, callers such as wp-comments-post.php, wp-trackback.php, the Ajax admin, XML-RPC and JSON APIs, JetPack and other plugins are now able to add comments safely and perform proper reasonable error handling.

See also #11286, #14452 and #16979.

9 years ago

#6 @mdgl
9 years ago

Patch updated to include slightly more robust error handling (relying function should also reset error indicator).

This ticket was mentioned in Slack in #core-comments by rachelbaker. View the logs.

8 years ago

#12 @SergeyBiryukov
5 years ago

  • Keywords bulk-reopened added

Related: #39732

#13 @earnjam
5 years ago

#40664 was marked as a duplicate.

#14 @desrosj
21 months ago

  • Keywords bulk-reopened removed
  • Milestone set to Awaiting Review
Note: See TracTickets for help on using tickets.