Checks whether a comment passes internal checks to be allowed to add.
If manual comment moderation is set in the administration, then all checks, regardless of their type and substance, will fail and the function will return false.
If the number of links exceeds the amount in the administration, then the check fails. If any of the parameter contents contain any disallowed words, then the check fails.
If the comment author was approved before, then the comment is automatically approved.
Pingbacks originating from the same site are automatically approved, as the link they report was created by someone who can already publish here.
If all checks pass, the function will return true.
function check_comment( $author, $email, $url, $comment, $user_ip, $user_agent, $comment_type ) {
global $wpdb;
// If manual moderation is enabled, skip all checks and return false.
if ( '1' === get_option( 'comment_moderation' ) ) {
return false;
}
/** This filter is documented in wp-includes/comment-template.php */
$comment = apply_filters( 'comment_text', $comment, null, array() );
// Check for the number of external links if a max allowed number is set.
$max_links = get_option( 'comment_max_links' );
if ( $max_links ) {
$num_links = preg_match_all( '/<a [^>]*href/i', $comment, $out );
/**
* Filters the number of links found in a comment.
*
* @since 3.0.0
* @since 4.7.0 Added the `$comment` parameter.
*
* @param int $num_links The number of links found.
* @param string $url Comment author's URL. Included in allowed links total.
* @param string $comment Content of the comment.
*/
$num_links = apply_filters( 'comment_max_links_url', $num_links, $url, $comment );
/*
* If the number of links in the comment exceeds the allowed amount,
* fail the check by returning false.
*/
if ( $num_links >= $max_links ) {
return false;
}
}
$mod_keys = trim( get_option( 'moderation_keys' ) );
// If moderation 'keys' (keywords) are set, process them.
if ( ! empty( $mod_keys ) ) {
$words = explode( "\n", $mod_keys );
foreach ( (array) $words as $word ) {
$word = trim( $word );
// Skip empty lines.
if ( empty( $word ) ) {
continue;
}
/*
* Do some escaping magic so that '#' (number of) characters in the spam
* words don't break things:
*/
$word = preg_quote( $word, '#' );
/*
* Check the comment fields for moderation keywords. If any are found,
* fail the check for the given field by returning false.
*/
$pattern = "#$word#iu";
if ( preg_match( $pattern, $author ) ) {
return false;
}
if ( preg_match( $pattern, $email ) ) {
return false;
}
if ( preg_match( $pattern, $url ) ) {
return false;
}
if ( preg_match( $pattern, $comment ) ) {
return false;
}
if ( preg_match( $pattern, $user_ip ) ) {
return false;
}
if ( preg_match( $pattern, $user_agent ) ) {
return false;
}
}
}
/*
* Check if the option to approve comments by previously-approved authors is enabled.
*
* If it is enabled, check whether the comment author has a previously-approved comment,
* as well as whether there are any moderation keywords (if set) present in the author
* email address. If both checks pass, return true. Otherwise, return false.
*/
if ( '1' === get_option( 'comment_previously_approved' ) ) {
if ( 'trackback' !== $comment_type && 'pingback' !== $comment_type && '' !== $author && '' !== $email ) {
$comment_user = get_user_by( 'email', wp_unslash( $email ) );
if ( ! empty( $comment_user->ID ) ) {
$ok_to_comment = $wpdb->get_var(
$wpdb->prepare(
"SELECT comment_approved
FROM $wpdb->comments
WHERE user_id = %d
AND comment_approved = '1'
LIMIT 1",
$comment_user->ID
)
);
} else {
// expected_slashed ($author, $email)
$ok_to_comment = $wpdb->get_var(
$wpdb->prepare(
"SELECT comment_approved
FROM $wpdb->comments
WHERE comment_author = %s
AND comment_author_email = %s
AND comment_approved = '1'
LIMIT 1",
$author,
$email
)
);
}
if ( '1' === $ok_to_comment && ( empty( $mod_keys ) || ! str_contains( $email, $mod_keys ) ) ) {
return true;
} else {
return false;
}
} elseif ( 'pingback' === $comment_type ) {
/*
* Only pingbacks are considered. A pingback is verified before it reaches
* this point: the source page is fetched, it must link to the target, and
* the comment is built from that fetched page. A trackback carries no such
* proof. Its source URL, title, and excerpt are unverified request data, so
* a forged trackback naming a local post as its source would be approved.
*/
// url_to_postid() compares hostnames, so it returns 0 for any URL that only appears to be local.
$source_id = url_to_postid( wp_unslash( $url ) );
// Approve pingbacks reporting a link that someone who can already publish here created.
$approve_pingback = $source_id > 0 && 'publish' === get_post_status( $source_id );
/**
* Filters whether a pingback is approved without being held for moderation.
*
* Defaults to true for pingbacks originating from a published post on the same
* site, and false for every other pingback. Trackbacks are never considered,
* as they cannot be verified.
*
* @since 7.1.0
*
* @param bool $approve_pingback Whether to auto-approve the pingback.
* @param int $source_id ID of the post on this site the pingback
* originated from, or 0 if it came from elsewhere.
* @param string $url The URL the pingback was sent from.
*/
return (bool) apply_filters( 'wp_auto_approve_ping', $approve_pingback, $source_id, $url );
} else {
return false;
}
}
return true;
}