wp_handle_comment_submission()
概述
wp_handle_comment_submission() 是 WordPress 中处理评论提交的核心函数,通常通过评论表单调用。它接收未转义的数据,执行一系列验证和过滤,最终调用 wp_new_comment() 保存评论,并返回 WP_Comment 对象或 WP_Error 错误。
关键要点
- 函数接收 $comment_data 数组参数,包含 comment_post_ID、author、email、url、comment、comment_parent 和 _wp_unfiltered_html_comment 等字段。
- 处理逻辑包括数据清理、父评论验证、文章状态检查(如评论关闭、草稿、私有、密码保护等)、用户身份验证和权限处理。
- 支持 Hook 机制,如 apply_filters('allow_empty_comment') 和多个 do_action 钩子(如 comment_closed、pre_comment_on_post),允许开发者自定义行为。
- 返回类型为 WP_Comment(成功时)或 WP_Error(失败时),错误情况包括回复未批准评论、文章不存在、评论关闭等。
- 与 wp_new_comment() 不同,此函数期望未转义的数据,内部会使用 wp_slash() 处理。
代码示例
function wp_handle_comment_submission( $comment_data ) {
$comment_post_id = 0;
$comment_author = '';
$comment_author_email = '';
$comment_author_url = '';
$comment_content = '';
$comment_parent = 0;
$user_id = 0;
if ( isset( $comment_data['comment_post_ID'] ) ) {
$comment_post_id = (int) $comment_data['comment_post_ID'];
}
// ... 更多处理逻辑
$commentdata = array(
'comment_post_ID' => $comment_post_id,
);
$commentdata += compact(
'comment_author',
'comment_author_email',
'comment_author_url',
'comment_content',
'comment_type',
'comment_parent',
'user_id'
);
$comment_id = wp_new_comment( wp_slash( $commentdata ), true );
if ( is_wp_error( $comment_id ) ) {
return $comment_id;
}
return get_comment( $comment_id );
}注意事项
- 确保传入的 $comment_data 数据未转义,否则可能导致处理错误。
- 函数内部会触发多个 Hook,开发者可以利用这些钩子扩展或修改评论提交流程。
- 错误处理应检查返回的 WP_Error 对象,以提供用户友好的反馈。
Handles the submission of a comment, usually posted to wp-comments-post.php via a comment form.
Description
This function expects unslashed data, as opposed to functions such as wp_new_comment() which expect slashed data.
Parameters
$comment_dataarrayrequired-
Comment data.
comment_post_IDstring|intThe ID of the post that relates to the comment.authorstringThe name of the comment author.emailstringThe comment author email address.urlstringThe comment author URL.commentstringThe content of the comment.comment_parentstring|intThe ID of this comment’s parent, if any. Default 0._wp_unfiltered_html_commentstringThe nonce value for allowing unfiltered HTML.
Source
function wp_handle_comment_submission( $comment_data ) {
$comment_post_id = 0;
$comment_author = '';
$comment_author_email = '';
$comment_author_url = '';
$comment_content = '';
$comment_parent = 0;
$user_id = 0;
if ( isset( $comment_data['comment_post_ID'] ) ) {
$comment_post_id = (int) $comment_data['comment_post_ID'];
}
if ( isset( $comment_data['author'] ) && is_string( $comment_data['author'] ) ) {
$comment_author = trim( strip_tags( $comment_data['author'] ) );
}
if ( isset( $comment_data['email'] ) && is_string( $comment_data['email'] ) ) {
$comment_author_email = trim( $comment_data['email'] );
}
if ( isset( $comment_data['url'] ) && is_string( $comment_data['url'] ) ) {
$comment_author_url = trim( $comment_data['url'] );
}
if ( isset( $comment_data['comment'] ) && is_string( $comment_data['comment'] ) ) {
$comment_content = trim( $comment_data['comment'] );
}
if ( isset( $comment_data['comment_parent'] ) ) {
$comment_parent = absint( $comment_data['comment_parent'] );
$comment_parent_object = get_comment( $comment_parent );
if (
0 !== $comment_parent &&
(
! $comment_parent_object instanceof WP_Comment ||
0 === (int) $comment_parent_object->comment_approved
)
) {
/**
* Fires when a comment reply is attempted to an unapproved comment.
*
* @since 6.2.0
*
* @param int $comment_post_id Post ID.
* @param int $comment_parent Parent comment ID.
*/
do_action( 'comment_reply_to_unapproved_comment', $comment_post_id, $comment_parent );
return new WP_Error( 'comment_reply_to_unapproved_comment', __( 'Sorry, replies to unapproved comments are not allowed.' ), 403 );
}
}
$post = get_post( $comment_post_id );
if ( empty( $post->comment_status ) ) {
/**
* Fires when a comment is attempted on a post that does not exist.
*
* @since 1.5.0
*
* @param int $comment_post_id Post ID.
*/
do_action( 'comment_id_not_found', $comment_post_id );
return new WP_Error( 'comment_id_not_found' );
}
// get_post_status() will get the parent status for attachments.
$status = get_post_status( $post );
if ( ( 'private' === $status ) && ! current_user_can( 'read_post', $comment_post_id ) ) {
return new WP_Error( 'comment_id_not_found' );
}
$status_obj = get_post_status_object( $status );
if ( ! comments_open( $comment_post_id ) ) {
/**
* Fires when a comment is attempted on a post that has comments closed.
*
* @since 1.5.0
*
* @param int $comment_post_id Post ID.
*/
do_action( 'comment_closed', $comment_post_id );
return new WP_Error( 'comment_closed', __( 'Sorry, comments are closed for this item.' ), 403 );
} elseif ( 'trash' === $status ) {
/**
* Fires when a comment is attempted on a trashed post.
*
* @since 2.9.0
*
* @param int $comment_post_id Post ID.
*/
do_action( 'comment_on_trash', $comment_post_id );
return new WP_Error( 'comment_on_trash' );
} elseif ( ! $status_obj->public && ! $status_obj->private ) {
/**
* Fires when a comment is attempted on a post in draft mode.
*
* @since 1.5.1
*
* @param int $comment_post_id Post ID.
*/
do_action( 'comment_on_draft', $comment_post_id );
if ( current_user_can( 'read_post', $comment_post_id ) ) {
return new WP_Error( 'comment_on_draft', __( 'Sorry, comments are not allowed for this item.' ), 403 );
} else {
return new WP_Error( 'comment_on_draft' );
}
} elseif ( post_password_required( $comment_post_id ) ) {
/**
* Fires when a comment is attempted on a password-protected post.
*
* @since 2.9.0
*
* @param int $comment_post_id Post ID.
*/
do_action( 'comment_on_password_protected', $comment_post_id );
return new WP_Error( 'comment_on_password_protected' );
} else {
/**
* Fires before a comment is posted.
*
* @since 2.8.0
*
* @param int $comment_post_id Post ID.
*/
do_action( 'pre_comment_on_post', $comment_post_id );
}
// If the user is logged in.
$user = wp_get_current_user();
if ( $user->exists() ) {
if ( empty( $user->display_name ) ) {
$user->display_name = $user->user_login;
}
$comment_author = $user->display_name;
$comment_author_email = $user->user_email;
$comment_author_url = $user->user_url;
$user_id = $user->ID;
if ( current_user_can( 'unfiltered_html' ) ) {
if ( ! isset( $comment_data['_wp_unfiltered_html_comment'] )
|| ! wp_verify_nonce( $comment_data['_wp_unfiltered_html_comment'], 'unfiltered-html-comment_' . $comment_post_id )
) {
kses_remove_filters(); // Start with a clean slate.
kses_init_filters(); // Set up the filters.
remove_filter( 'pre_comment_content', 'wp_filter_post_kses' );
add_filter( 'pre_comment_content', 'wp_filter_kses' );
}
}
} else {
if ( get_option( 'comment_registration' ) ) {
return new WP_Error( 'not_logged_in', __( 'Sorry, you must be logged in to comment.' ), 403 );
}
}
$comment_type = 'comment';
if ( get_option( 'require_name_email' ) && ! $user->exists() ) {
if ( '' === $comment_author_email || '' === $comment_author ) {
return new WP_Error( 'require_name_email', __( '<strong>Error:</strong> Please fill the required fields.' ), 200 );
} elseif ( ! is_email( $comment_author_email ) ) {
return new WP_Error( 'require_valid_email', __( '<strong>Error:</strong> Please enter a valid email address.' ), 200 );
}
}
$commentdata = array(
'comment_post_ID' => $comment_post_id,
);
$commentdata += compact(
'comment_author',
'comment_author_email',
'comment_author_url',
'comment_content',
'comment_type',
'comment_parent',
'user_id'
);
/**
* Filters whether an empty comment should be allowed.
*
* @since 5.1.0
*
* @param bool $allow_empty_comment Whether to allow empty comments. Default false.
* @param array $commentdata Array of comment data to be sent to wp_insert_comment().
*/
$allow_empty_comment = apply_filters( 'allow_empty_comment', false, $commentdata );
if ( '' === $comment_content && ! $allow_empty_comment ) {
return new WP_Error( 'require_valid_comment', __( '<strong>Error:</strong> Please type your comment text.' ), 200 );
}
$check_max_lengths = wp_check_comment_data_max_lengths( $commentdata );
if ( is_wp_error( $check_max_lengths ) ) {
return $check_max_lengths;
}
$comment_id = wp_new_comment( wp_slash( $commentdata ), true );
if ( is_wp_error( $comment_id ) ) {
return $comment_id;
}
if ( ! $comment_id ) {
return new WP_Error( 'comment_save_error', __( '<strong>Error:</strong> The comment could not be saved. Please try again later.' ), 500 );
}
return get_comment( $comment_id );
}
Hooks
- apply_filters( ‘allow_empty_comment’, bool $allow_empty_comment, array $commentdata )
-
Filters whether an empty comment should be allowed.
- do_action( ‘comment_closed’, int $comment_post_id )
-
Fires when a comment is attempted on a post that has comments closed.
- do_action( ‘comment_id_not_found’, int $comment_post_id )
-
Fires when a comment is attempted on a post that does not exist.
- do_action( ‘comment_on_draft’, int $comment_post_id )
-
Fires when a comment is attempted on a post in draft mode.
- do_action( ‘comment_on_password_protected’, int $comment_post_id )
-
Fires when a comment is attempted on a password-protected post.
- do_action( ‘comment_on_trash’, int $comment_post_id )
-
Fires when a comment is attempted on a trashed post.
- do_action( ‘comment_reply_to_unapproved_comment’, int $comment_post_id, int $comment_parent )
-
Fires when a comment reply is attempted to an unapproved comment.
- do_action( ‘pre_comment_on_post’, int $comment_post_id )
-
Fires before a comment is posted.
Changelog
| Version | Description |
|---|---|
| 4.4.0 | Introduced. |