diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 07:57:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 07:57:30 +0000 |
commit | fa9a33d818470a5796f0ff8797f98b510ed8de18 (patch) | |
tree | bde6a1eede376f9b5df5898ce812330152984d8e /wp-content/plugins | |
parent | Releasing progress-linux version 6.4.3+dfsg1-1~progress7.99u1. (diff) | |
download | wordpress-fa9a33d818470a5796f0ff8797f98b510ed8de18.tar.xz wordpress-fa9a33d818470a5796f0ff8797f98b510ed8de18.zip |
Merging upstream version 6.5+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'wp-content/plugins')
-rw-r--r-- | wp-content/plugins/akismet/akismet.php | 4 | ||||
-rw-r--r-- | wp-content/plugins/akismet/class.akismet-admin.php | 53 | ||||
-rw-r--r-- | wp-content/plugins/akismet/class.akismet-rest-api.php | 179 | ||||
-rw-r--r-- | wp-content/plugins/akismet/class.akismet.php | 65 | ||||
-rw-r--r-- | wp-content/plugins/akismet/readme.txt | 9 | ||||
-rw-r--r-- | wp-content/plugins/akismet/views/config.php | 68 | ||||
-rw-r--r-- | wp-content/plugins/akismet/views/notice.php | 10 |
7 files changed, 319 insertions, 69 deletions
diff --git a/wp-content/plugins/akismet/akismet.php b/wp-content/plugins/akismet/akismet.php index 9ec3315..b62fddd 100644 --- a/wp-content/plugins/akismet/akismet.php +++ b/wp-content/plugins/akismet/akismet.php @@ -6,7 +6,7 @@ Plugin Name: Akismet Anti-spam: Spam Protection Plugin URI: https://akismet.com/ Description: Used by millions, Akismet is quite possibly the best way in the world to <strong>protect your blog from spam</strong>. Akismet Anti-spam keeps your site protected even while you sleep. To get started: activate the Akismet plugin and then go to your Akismet Settings page to set up your API key. -Version: 5.3.1 +Version: 5.3.2 Requires at least: 5.8 Requires PHP: 5.6.20 Author: Automattic - Anti-spam Team @@ -39,7 +39,7 @@ if ( !function_exists( 'add_action' ) ) { exit; } -define( 'AKISMET_VERSION', '5.3.1' ); +define( 'AKISMET_VERSION', '5.3.2' ); define( 'AKISMET__MINIMUM_WP_VERSION', '5.8' ); define( 'AKISMET__PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'AKISMET_DELETE_LIMIT', 10000 ); diff --git a/wp-content/plugins/akismet/class.akismet-admin.php b/wp-content/plugins/akismet/class.akismet-admin.php index b30813a..dd39104 100644 --- a/wp-content/plugins/akismet/class.akismet-admin.php +++ b/wp-content/plugins/akismet/class.akismet-admin.php @@ -667,6 +667,18 @@ class Akismet_Admin { $message = esc_html( __( 'Akismet was unable to recheck this comment.', 'akismet' ) ); } break; + case 'webhook-spam': + $message = esc_html( __( 'Akismet caught this comment as spam and updated its status via webhook.', 'akismet' ) ); + break; + case 'webhook-ham': + $message = esc_html( __( 'Akismet cleared this comment and updated its status via webhook.', 'akismet' ) ); + break; + case 'webhook-spam-noaction': + $message = esc_html( __( 'Akismet determined this comment was spam during a recheck. It did not update the comment status because it had already been modified by another user or plugin.', 'akismet' ) ); + break; + case 'webhook-ham-noaction': + $message = esc_html( __( 'Akismet cleared this comment during a recheck. It did not update the comment status because it had already been modified by another user or plugin.', 'akismet' ) ); + break; default: if ( preg_match( '/^status-changed/', $row['event'] ) ) { // Half of these used to be saved without the dash after 'status-changed'. @@ -1098,26 +1110,29 @@ class Akismet_Admin { } /* - // To see all variants when testing. - $notices[] = array( 'type' => 'active-notice', 'time_saved' => 'Cleaning up spam takes time. Akismet has saved you 1 minute!' ); - $notices[] = array( 'type' => 'plugin' ); - $notices[] = array( 'type' => 'spam-check', 'link_text' => 'Link text.' ); - $notices[] = array( 'type' => 'notice', 'notice_header' => 'This is the notice header.', 'notice_text' => 'This is the notice text.' ); - $notices[] = array( 'type' => 'missing-functions' ); - $notices[] = array( 'type' => 'servers-be-down' ); - $notices[] = array( 'type' => 'active-dunning' ); - $notices[] = array( 'type' => 'cancelled' ); - $notices[] = array( 'type' => 'suspended' ); - $notices[] = array( 'type' => 'missing' ); - $notices[] = array( 'type' => 'no-sub' ); - $notices[] = array( 'type' => 'new-key-valid' ); - $notices[] = array( 'type' => 'new-key-invalid' ); - $notices[] = array( 'type' => 'existing-key-invalid' ); - $notices[] = array( 'type' => 'new-key-failed' ); - $notices[] = array( 'type' => 'usage-limit', 'api_calls' => '15000', 'usage_limit' => '10000', 'upgrade_plan' => 'Enterprise', 'upgrade_url' => 'https://akismet.com/account/', 'code' => 10502 ); - $notices[] = array( 'type' => 'spam-check-cron-disabled' ); - $notices[] = array( 'type' => 'alert', 'code' => 123 ); + * To see all variants when testing. + * + * You may also want to comment out the akismet_view_arguments filter in Akismet::view() + * to ensure that you can see all of the notices (e.g. suspended, active-notice). */ + // $notices[] = array( 'type' => 'active-notice', 'time_saved' => 'Cleaning up spam takes time. Akismet has saved you 1 minute!' ); + // $notices[] = array( 'type' => 'plugin' ); + // $notices[] = array( 'type' => 'spam-check', 'link_text' => 'Link text.' ); + // $notices[] = array( 'type' => 'notice', 'notice_header' => 'This is the notice header.', 'notice_text' => 'This is the notice text.' ); + // $notices[] = array( 'type' => 'missing-functions' ); + // $notices[] = array( 'type' => 'servers-be-down' ); + // $notices[] = array( 'type' => 'active-dunning' ); + // $notices[] = array( 'type' => 'cancelled' ); + // $notices[] = array( 'type' => 'suspended' ); + // $notices[] = array( 'type' => 'missing' ); + // $notices[] = array( 'type' => 'no-sub' ); + // $notices[] = array( 'type' => 'new-key-valid' ); + // $notices[] = array( 'type' => 'new-key-invalid' ); + // $notices[] = array( 'type' => 'existing-key-invalid' ); + // $notices[] = array( 'type' => 'new-key-failed' ); + // $notices[] = array( 'type' => 'usage-limit', 'api_calls' => '15000', 'usage_limit' => '10000', 'upgrade_plan' => 'Enterprise', 'upgrade_url' => 'https://akismet.com/account/', 'code' => 10502 ); + // $notices[] = array( 'type' => 'spam-check-cron-disabled' ); + // $notices[] = array( 'type' => 'alert', 'code' => 123 ); Akismet::log( compact( 'stat_totals', 'akismet_user' ) ); Akismet::view( 'config', compact( 'api_key', 'akismet_user', 'stat_totals', 'notices' ) ); diff --git a/wp-content/plugins/akismet/class.akismet-rest-api.php b/wp-content/plugins/akismet/class.akismet-rest-api.php index ef09f70..12e86f0 100644 --- a/wp-content/plugins/akismet/class.akismet-rest-api.php +++ b/wp-content/plugins/akismet/class.akismet-rest-api.php @@ -129,6 +129,16 @@ class Akismet_REST_API { ), ) ) ); + + register_rest_route( + 'akismet/v1', + '/webhook', + array( + 'methods' => WP_REST_Server::CREATABLE, + 'callback' => array( 'Akismet_REST_API', 'receive_webhook' ), + 'permission_callback' => array( 'Akismet_REST_API', 'remote_call_permission_callback' ), + ) + ); } /** @@ -370,4 +380,173 @@ class Akismet_REST_API { public static function sanitize_key( $key, $request, $param ) { return trim( $key ); } + + /** + * Process a webhook request from the Akismet servers. + * + * @param WP_REST_Request $request + * @return WP_Error|WP_REST_Response + */ + public static function receive_webhook( $request ) { + Akismet::log( array( 'Webhook request received', $request->get_body() ) ); + + /** + * The request body should look like this: + * array( + * 'key' => '1234567890abcd', + * 'endpoint' => '[comment-check|submit-ham|submit-spam]', + * 'comments' => array( + * array( + * 'guid' => '[...]', + * 'result' => '[true|false]', + * 'comment_author' => '[...]', + * [...] + * ), + * array( + * 'guid' => '[...]', + * [...], + * ), + * [...] + * ) + * ) + * + * Multiple comments can be included in each request, and the only truly required + * field for each is the guid, although it would be friendly to include also + * comment_post_ID, comment_parent, and comment_author_email, if possible to make + * searching easier. + */ + + // The response will include statuses for the result of each comment that was supplied. + $response = array( + 'comments' => array(), + ); + + $endpoint = $request->get_param( 'endpoint' ); + + switch ( $endpoint ) { + case 'comment-check': + $webhook_comments = $request->get_param( 'comments' ); + + if ( ! is_array( $webhook_comments ) ) { + return rest_ensure_response( new WP_Error( 'malformed_request', __( 'The \'comments\' parameter must be an array.', 'akismet' ), array( 'status' => 400 ) ) ); + } + + foreach ( $webhook_comments as $webhook_comment ) { + $guid = $webhook_comment['guid']; + + if ( ! $guid ) { + // Without the GUID, we can't be sure that we're matching the right comment. + // We'll make it a rule that any comment without a GUID is ignored intentionally. + continue; + } + + // Search on the fields that are indexed in the comments table, plus the GUID. + // The GUID is the only thing we really need to search on, but comment_meta + // is not indexed in a useful way if there are many many comments. This + // should help narrow it down first. + $queryable_fields = array( + 'comment_post_ID' => 'post_id', + 'comment_parent' => 'parent', + 'comment_author_email' => 'author_email', + ); + + $query_args = array(); + $query_args['status'] = 'any'; + $query_args['meta_key'] = 'akismet_guid'; + $query_args['meta_value'] = $guid; + + foreach ( $queryable_fields as $queryable_field => $wp_comment_query_field ) { + if ( isset( $webhook_comment[ $queryable_field ] ) ) { + $query_args[ $wp_comment_query_field ] = $webhook_comment[ $queryable_field ]; + } + } + + $comments_query = new WP_Comment_Query( $query_args ); + $comments = $comments_query->comments; + + if ( ! $comments ) { + // Unexpected, although the comment could have been deleted since being submitted. + Akismet::log( 'Webhook failed: no matching comment found.' ); + + $response['comments'][ $guid ] = array( 'status' => 'error', 'message' => __( 'Could not find matching comment.', 'akismet' ) ); + + continue; + } if ( count( $comments ) > 1 ) { + // Two comments shouldn't be able to match the same GUID. + Akismet::log( 'Webhook failed: multiple matching comments found.', $comments ); + + $response['comments'][ $guid ] = array( 'status' => 'error', 'message' => __( 'Multiple comments matched request.', 'akismet' ) ); + + continue; + } else { + // We have one single match, as hoped for. + Akismet::log( 'Found matching comment.', $comments ); + + $current_status = wp_get_comment_status( $comments[0] ); + + $result = $webhook_comment['result']; + + if ( 'true' == $result ) { + Akismet::log( 'Comment should be spam' ); + + // The comment should be classified as spam. + if ( 'spam' != $current_status ) { + // The comment is not classified as spam. If Akismet was the one to act on it, move it to spam. + if ( Akismet::last_comment_status_change_came_from_akismet( $comments[0]->comment_ID ) ) { + Akismet::log( 'Comment is not spam; marking as spam.' ); + + wp_spam_comment( $comments[0] ); + Akismet::update_comment_history( $comments[0]->comment_ID, '', 'webhook-spam' ); + } else { + Akismet::log( 'Comment is not spam, but it has already been manually handled by some other process.' ); + Akismet::update_comment_history( $comments[0]->comment_ID, '', 'webhook-spam-noaction' ); + } + } + } else if ( 'false' == $result ) { + Akismet::log( 'Comment should be ham' ); + + // The comment should be classified as ham. + if ( 'spam' == $current_status ) { + Akismet::log( 'Comment is spam.' ); + + // The comment is classified as spam. If Akismet was the one to label it as spam, unspam it. + if ( Akismet::last_comment_status_change_came_from_akismet( $comments[0]->comment_ID ) ) { + Akismet::log( 'Akismet marked it as spam; unspamming.' ); + + wp_unspam_comment( $comments[0] ); + akismet::update_comment_history( $comments[0]->comment_ID, '', 'webhook-ham' ); + } else { + Akismet::log( 'Comment is not spam, but it has already been manually handled by some other process.' ); + Akismet::update_comment_history( $comments[0]->comment_ID, '', 'webhook-ham-noaction' ); + } + } + } + + $response['comments'][ $guid ] = array( 'status' => 'success' ); + } + } + + break; + case 'submit-ham': + case 'submit-spam': + // Nothing to do for submit-ham or submit-spam. + break; + default: + // Unsupported endpoint. + break; + } + + /** + * Allow plugins to do things with a successfully processed webhook request, like logging. + * + * @since 5.3.2 + * + * @param WP_REST_Request $request The REST request object. + */ + do_action( 'akismet_webhook_received', $request ); + + Akismet::log( 'Done processing webhook.' ); + + return rest_ensure_response( $response ); + } } diff --git a/wp-content/plugins/akismet/class.akismet.php b/wp-content/plugins/akismet/class.akismet.php index 951142e..7a89f61 100644 --- a/wp-content/plugins/akismet/class.akismet.php +++ b/wp-content/plugins/akismet/class.akismet.php @@ -642,7 +642,14 @@ class Akismet { return 0; } - // get the full comment history for a given comment, as an array in reverse chronological order + /** + * Get the full comment history for a given comment, as an array in reverse chronological order. + * Each entry will have an 'event', a 'time', and possible a 'message' member (if the entry is old enough). + * Some entries will also have a 'user' or 'meta' member. + * + * @param int $comment_id The relevant comment ID. + * @return array|bool An array of history events, or false if there is no history. + */ public static function get_comment_history( $comment_id ) { $history = get_comment_meta( $comment_id, 'akismet_history', false ); if ( empty( $history ) || empty( $history[ 0 ] ) ) { @@ -681,6 +688,10 @@ class Akismet { $history[] = array( 'time' => 445856425, 'event' => 'status-spam', 'user' => 'sam' ); $history[] = array( 'time' => 445856426, 'event' => 'status-hold', 'user' => 'sam' ); $history[] = array( 'time' => 445856427, 'event' => 'status-approve', 'user' => 'sam' ); + $history[] = array( 'time' => 445856427, 'event' => 'webhook-spam' ); + $history[] = array( 'time' => 445856427, 'event' => 'webhook-ham' ); + $history[] = array( 'time' => 445856427, 'event' => 'webhook-spam-noaction' ); + $history[] = array( 'time' => 445856427, 'event' => 'webhook-ham-noaction' ); */ usort( $history, array( 'Akismet', '_cmp_time' ) ); @@ -819,6 +830,17 @@ class Akismet { if ( get_comment_meta( $comment->comment_ID, 'akismet_rechecking' ) ) return; + if ( function_exists( 'getallheaders' ) ) { + $request_headers = getallheaders(); + + foreach ( $request_headers as $header => $value ) { + if ( strtolower( $header ) == 'x-akismet-webhook' ) { + // This change is due to a webhook request. + return; + } + } + } + // Assumption alert: // We want to submit comments to Akismet only when a moderator explicitly spams or approves it - not if the status // is changed automatically by another plugin. Unfortunately WordPress doesn't provide an unambiguous way to @@ -1583,7 +1605,7 @@ p { public static function view( $name, array $args = array() ) { $args = apply_filters( 'akismet_view_arguments', $args, $name ); - foreach ( $args AS $key => $val ) { + foreach ( $args as $key => $val ) { $$key = $val; } @@ -1871,4 +1893,43 @@ p { return $return_value; } + + /** + * Was the last entry in the comment history created by Akismet? + * + * @param int $comment_id The ID of the comment. + * @return bool + */ + public static function last_comment_status_change_came_from_akismet( $comment_id ) { + $history = self::get_comment_history( $comment_id ); + + if ( empty( $history ) ) { + return false; + } + + $most_recent_history_event = $history[0]; + + if ( ! isset( $most_recent_history_event['event'] ) ) { + return false; + } + + $akismet_history_events = array( + 'check-error', + 'cron-retry-ham', + 'cron-retry-spam', + 'check-ham', + 'check-spam', + 'recheck-error', + 'recheck-ham', + 'recheck-spam', + 'webhook-ham', + 'webhook-spam', + ); + + if ( in_array( $most_recent_history_event['event'], $akismet_history_events ) ) { + return true; + } + + return false; + } } diff --git a/wp-content/plugins/akismet/readme.txt b/wp-content/plugins/akismet/readme.txt index 2221acf..30d7748 100644 --- a/wp-content/plugins/akismet/readme.txt +++ b/wp-content/plugins/akismet/readme.txt @@ -3,7 +3,7 @@ Contributors: matt, ryan, andy, mdawaffe, tellyworth, josephscott, lessbloat, eo Tags: comments, spam, antispam, anti-spam, contact form, anti spam, comment moderation, comment spam, contact form spam, spam comments Requires at least: 5.8 Tested up to: 6.4 -Stable tag: 5.3.1 +Stable tag: 5.3.2 License: GPLv2 or later The best anti-spam protection to block spam comments and spam in a contact form. The most trusted antispam solution for WordPress and WooCommerce. @@ -32,6 +32,13 @@ Upload the Akismet plugin to your blog, activate it, and then enter your Akismet == Changelog == += 5.3.2 = +*Release Date - 21 March 2024* + +* Improve the empty state shown to new users when no spam has been caught yet. +* Update the message shown to users without a current subscription. +* Add foundations for future webhook support. + = 5.3.1 = *Release Date - 17 January 2024* diff --git a/wp-content/plugins/akismet/views/config.php b/wp-content/plugins/akismet/views/config.php index 77e5914..b9e4457 100644 --- a/wp-content/plugins/akismet/views/config.php +++ b/wp-content/plugins/akismet/views/config.php @@ -30,7 +30,6 @@ $kses_allow_link_href = array( <span><?php esc_html_e( 'Statistics', 'akismet' ); ?></span> </h2> - <?php if ( $stat_totals && isset( $stat_totals['all'] ) && (int) $stat_totals['all']->spam > 0 ) : ?> <div class="akismet-section-header__actions"> <a href="<?php echo esc_url( Akismet_Admin::get_page_url( 'stats' ) ); ?>"> <?php esc_html_e( 'Detailed stats', 'akismet' ); ?> @@ -38,43 +37,36 @@ $kses_allow_link_href = array( </div> </div> <!-- close akismet-section-header --> - <div class="akismet-new-snapshot"> - <?php /* name attribute on iframe is used as a cache-buster here to force Firefox to load the new style charts: https://bugzilla.mozilla.org/show_bug.cgi?id=356558 */ ?> - <div class="akismet-new-snapshot__chart"> - <iframe id="stats-iframe" allowtransparency="true" scrolling="no" frameborder="0" style="width: 100%; height: 220px; overflow: hidden;" src="<?php echo esc_url( sprintf( 'https://tools.akismet.com/1.0/snapshot.php?blog=%s&token=%s&height=200&locale=%s&is_redecorated=1', rawurlencode( get_option( 'home' ) ), rawurlencode( Akismet::get_access_token() ), get_locale() ) ); ?>" name="<?php echo esc_attr( 'snapshot-' . filemtime( __FILE__ ) ); ?>" title="<?php echo esc_attr__( 'Akismet stats' ); ?>"></iframe> - </div> - <ul class="akismet-new-snapshot__list"> - <li class="akismet-new-snapshot__item"> - <h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'Past six months', 'akismet' ); ?></h3> - <span class="akismet-new-snapshot__number"><?php echo number_format( $stat_totals['6-months']->spam ); ?></span> - <span class="akismet-new-snapshot__text"><?php echo esc_html( _n( 'Spam blocked', 'Spam blocked', $stat_totals['6-months']->spam, 'akismet' ) ); ?></span> - </li> - <li class="akismet-new-snapshot__item"> - <h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'All time', 'akismet' ); ?></h3> - <span class="akismet-new-snapshot__number"><?php echo number_format( $stat_totals['all']->spam ); ?></span> - <span class="akismet-new-snapshot__text"><?php echo esc_html( _n( 'Spam blocked', 'Spam blocked', $stat_totals['all']->spam, 'akismet' ) ); ?></span> - </li> - <li class="akismet-new-snapshot__item"> - <h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'Accuracy', 'akismet' ); ?></h3> - <span class="akismet-new-snapshot__number"><?php echo floatval( $stat_totals['all']->accuracy ); ?>%</span> - <span class="akismet-new-snapshot__text"> - <?php - /* translators: %s: number of spam missed by Akismet */ - echo esc_html( sprintf( _n( '%s missed spam', '%s missed spam', $stat_totals['all']->missed_spam, 'akismet' ), number_format( $stat_totals['all']->missed_spam ) ) ) . ', '; - /* translators: %s: number of false positive spam flagged by Akismet */ - echo esc_html( sprintf( _n( '%s false positive', '%s false positives', $stat_totals['all']->false_positives, 'akismet' ), number_format( $stat_totals['all']->false_positives ) ) ); - ?> - </span> - </li> - </ul> - </div> <!-- close akismet-new-snapshot --> - - <?php else : ?> - </div> <!-- close akismet-section-header --> - <div class="inside"> - <p class="akismet-awaiting-stats"><?php esc_html_e( 'Akismet is active and ready to stop spam. Your site’s spam statistics will be displayed here.', 'akismet' ); ?></p> - </div> - <?php endif; ?> + <div class="akismet-new-snapshot"> + <?php /* name attribute on iframe is used as a cache-buster here to force Firefox to load the new style charts: https://bugzilla.mozilla.org/show_bug.cgi?id=356558 */ ?> + <div class="akismet-new-snapshot__chart"> + <iframe id="stats-iframe" allowtransparency="true" scrolling="no" frameborder="0" style="width: 100%; height: 220px; overflow: hidden;" src="<?php echo esc_url( sprintf( 'https://tools.akismet.com/1.0/snapshot.php?blog=%s&token=%s&height=200&locale=%s&is_redecorated=1', rawurlencode( get_option( 'home' ) ), rawurlencode( Akismet::get_access_token() ), get_locale() ) ); ?>" name="<?php echo esc_attr( 'snapshot-' . filemtime( __FILE__ ) ); ?>" title="<?php echo esc_attr__( 'Akismet stats' ); ?>"></iframe> + </div> + <ul class="akismet-new-snapshot__list"> + <li class="akismet-new-snapshot__item"> + <h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'Past six months', 'akismet' ); ?></h3> + <span class="akismet-new-snapshot__number"><?php echo number_format( $stat_totals['6-months']->spam ); ?></span> + <span class="akismet-new-snapshot__text"><?php echo esc_html( _n( 'Spam blocked', 'Spam blocked', $stat_totals['6-months']->spam, 'akismet' ) ); ?></span> + </li> + <li class="akismet-new-snapshot__item"> + <h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'All time', 'akismet' ); ?></h3> + <span class="akismet-new-snapshot__number"><?php echo number_format( $stat_totals['all']->spam ); ?></span> + <span class="akismet-new-snapshot__text"><?php echo esc_html( _n( 'Spam blocked', 'Spam blocked', $stat_totals['all']->spam, 'akismet' ) ); ?></span> + </li> + <li class="akismet-new-snapshot__item"> + <h3 class="akismet-new-snapshot__header"><?php esc_html_e( 'Accuracy', 'akismet' ); ?></h3> + <span class="akismet-new-snapshot__number"><?php echo floatval( $stat_totals['all']->accuracy ); ?>%</span> + <span class="akismet-new-snapshot__text"> + <?php + /* translators: %s: number of spam missed by Akismet */ + echo esc_html( sprintf( _n( '%s missed spam', '%s missed spam', $stat_totals['all']->missed_spam, 'akismet' ), number_format( $stat_totals['all']->missed_spam ) ) ) . ', '; + /* translators: %s: number of false positive spam flagged by Akismet */ + echo esc_html( sprintf( _n( '%s false positive', '%s false positives', $stat_totals['all']->false_positives, 'akismet' ), number_format( $stat_totals['all']->false_positives ) ) ); + ?> + </span> + </li> + </ul> + </div> <!-- close akismet-new-snapshot --> </div> <!-- close akismet-card --> diff --git a/wp-content/plugins/akismet/views/notice.php b/wp-content/plugins/akismet/views/notice.php index 8bacc54..466a322 100644 --- a/wp-content/plugins/akismet/views/notice.php +++ b/wp-content/plugins/akismet/views/notice.php @@ -152,15 +152,11 @@ $kses_allow_strong = array( 'strong' => true ); <?php elseif ( $type === 'no-sub' ) : ?> <div class="akismet-alert is-bad"> <h3 class="akismet-alert__heading"><?php esc_html_e( 'You don’t have an Akismet plan.', 'akismet' ); ?></h3> + <p><?php echo esc_html__( 'Your API key must have an Akismet plan before it can protect your site from spam.', 'akismet' ); ?></p> <p> <?php - /* translators: the placeholder is a clickable URL to the Akismet account upgrade page. */ - echo wp_kses( sprintf( __( 'In 2012, Akismet began using subscription plans for all accounts (even free ones). A plan has not been assigned to your account, and we’d appreciate it if you’d <a href="%s" target="_blank">sign into your account</a> and choose one.', 'akismet' ), esc_url( 'https://akismet.com/pricing' ) ), $kses_allow_link ); - ?> - <br /><br /> - <?php - /* translators: The placeholder is a URL to the Akismet contact form. */ - echo wp_kses( sprintf( __( 'Please <a href="%s" target="_blank">contact our support team</a> with any questions.', 'akismet' ), esc_url( 'https://akismet.com/contact/' ) ), $kses_allow_link ); + /* translators: the placeholder is the URL to the Akismet pricing page. */ + echo wp_kses( sprintf( __( 'Please <a href="%s" target="_blank">choose a plan</a> to get started with Akismet.', 'akismet' ), esc_url( 'https://akismet.com/pricing' ) ), $kses_allow_link ); ?> </p> </div> |