In a previous post I asked how to do this:
I got around to figuring out the programming to do it purely in functions.php
today. As I expected it’s very simple, certainly not the kind of thing you need a separate plugin for. There is an important privacy surprise, so please to read to the end. First we need to add the Akismet field to the comment form:
function akismet_comment_consent( $fields ) {
$fields['akismet']='<p class="comment-form-akismet-consent"><input id="wp-comment-akismet-consent" name="wp-comment-akismet-consent" type="checkbox" value="yes" required="required" /><label for="wp-comment-akismet-consent">I agree to my comment being scanned for spam by Akismet.</label></p>';
return $fields;
}
add_filter( 'comment_form_default_fields', 'akismet_comment_consent' );
This is just a straightforward use of the comment_form_default_fields hook where we are adding to the $fields array. The HTML is structured in exactly the same way as the cookies consent field, with the only difference that I’ve added the required="required"
attribute/value which instructs the client’s browser to require the checkbox is checked before submission.
Next we need to prevent comments being submitted without accepting the checkbox.
function akismet_consent( $commentdata ) {
if ( (!is_user_logged_in())&&('post'===get_post_type($_POST['comment_post_ID']))&&(!isset($_POST['wp-comment-akismet-consent'])) ) {
wp_die( '<strong>' . __( 'ERROR: ' ) . '</strong>' . __( 'Please accept the Akismet checkbox.' ) . '<p><a href="javascript:history.back()">' . __( '« Back' ) . '</a></p>');
}
return $commentdata;
}
add_filter( 'preprocess_comment', 'akismet_consent', -1 );
Here we’re using the preprocess_comment hook. This hook runs before a comment is set, and it’s the same one that Akismet attaches to. The conditions therefore for returning an error is whether this is a comment that has been submitted to a post, from a user that is not logged-in, and who did not accept the Akismet checkbox. Obviously the conditional check for the post type would need to be modified if you’re allowing comments on pages. If the Akismet checkbox value wasn’t set then return an error.
Now the part that surprised me. Even if your comment never gets submitted to your database because of checks you’ve run sever-side, there’s a good chance it is being sent to Akismet first.This is because Akismet sets itself to high priority. To be safe with the consent checkbox, we’ve set our function to an even higher priority. However given this behaviour we’ll also reduce the Akismet priority to below normal so it will trigger after any other functions attached to the preprocess_comment
hook, and in the process also disable Akismet for logged-in users:
function lower_akismet_priority() {
$akismetfilt=remove_filter( 'preprocess_comment', array( 'Akismet', 'auto_check_comment' ), 1 );
if ( ($akismetfilt) && (!is_user_logged_in()) ){
add_filter( 'preprocess_comment', array( 'Akismet', 'auto_check_comment' ), 20 );
}
}
add_action( 'init', 'lower_akismet_priority', 99 );
I’ve just edited this last function, because it dawned on me that PHP isn’t really a low-level programming language and I can’t be sure the IF statement isn’t rewritten when compiled.
There’s no “update_filter()” function, so the filter must be removed first as described here. Of course there’s a chance that lowering the priority will break something, but I can’t imagine what that is so unless I encounter a problem with this approach I will leave it like this.
And we’re done!