Exclude internal links from comment moderation?

The first option on Settings – Discussion – Comment Moderation is:

Hold a comment in the queue if it contains “1” or more links. (A common characteristic of comment spam is a large number of hyperlinks.)

That is useful but it would be much better for me and my visitors if it ignored internal links. Many times users reference other articles of the site and that is a good thing. But they get caught on moderation queue which is annoying for both users and the admin.

So is there a way to filter this settings to whitelist domains? Like the domain where wordpress is being hosted.

1 Answer
1

The comment_max_links_url filter

We can count the number of internal links in the comment’s content and subtract that from the total number of links found there ($num_links), with the help of the following filter inside the check_comment() core function:

/**
 * 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 );

The core only counts the number of <a> tags, containing the href attribute, with:

$num_links = preg_match_all( '/<a [^>]*href/i', $comment, $out );

Demo plugin – Allow links from the home url host

Here’s an example, to allow any internal links in the comment’s content:

/**
 * Allow any internal links from the home url host, in the comment's content
 *
 * @see http://wordpress.stackexchange.com/a/257917/26350
 */

add_filter( 'comment_max_links_url', function( $num_links, $url, $comment )
{
    // Allowed hosts
    $allowed_host = wp_parse_url( home_url(), PHP_URL_HOST );

    // Get all links
    $all_links = preg_match_all( 
        '/<a [^>]*href=["\']([^"\']+)/i', 
        $comment, 
        $links 
    );

    // No links
    if( empty( $links[1] ) || ! is_array( $links[1] ) )
        return $num_links;

    // Count links that are from our home url domain
    $internal_links = array_reduce( 
        $links[1], 
        function( $internal, $link ) use ( $allowed_host )
        {   
            if( $allowed_host === wp_parse_url( $link, PHP_URL_HOST ) )
                $internal += 1;

            return $internal;
         },
         0 
    );

    return ( $num_links - $internal_links );
}, 10, 3 );

Demo plugin – Allow links from multiple hosts

Here’s an example with multiple allowed hosts:

/**
 * Allow any internal links, from multiple allowed hosts, in the comment's content
 *
 * @see http://wordpress.stackexchange.com/a/257917/26350
 */

add_filter( 'comment_max_links_url', function( $num_links, $url, $comment )
{
    // Allowed hosts
    $allowed_hosts = [ 'foo.tld', 'bar.tld' ]; // <-- Adjust to your needs!

    // Get all links
    $all_links = preg_match_all( 
        '/<a [^>]*href=["\']([^"\']+)/i', 
        $comment, 
        $links 
    );

    // No links
    if( empty( $links[1] ) || ! is_array( $links[1] ) )
        return $num_links;

    // Count links that are from our allowed hosts
    $internal_links = array_reduce( 
        $links[1], 
        function( $internal, $link ) use ( $allowed_hosts )
        {
            if( in_array( wp_parse_url( $link, PHP_URL_HOST ), $allowed_hosts, true ) )
                $internal += 1;

            return $internal;
         },
         0 
    );

    return ( $num_links - $internal_links );
}, 10, 3 );

We used array_reduce() and wp_parse_url() to help with the counting of the internal links or links from allowed hosts, in the above plugins.

Please test it further and adjust to your needs!

Leave a Comment