Skip to:
Content

bbPress.org

Changeset 7204


Ignore:
Timestamp:
09/21/2021 12:06:37 AM (4 weeks ago)
Author:
johnjamesjacoby
Message:

Akismet: introduce a few clean-up action hook methods.

  • delete_old_spam() - deletes old spam topics & replies from the queue after 15 days.
  • delete_old_spam_meta() - deletes _bbp_akismet_as_submitted entries after 15 days.
  • delete_orphaned_spam_meta() - deletes post meta that no longer have corresponding posts in the database.

Props stephdau, johnjamesjacoby.

In trunk, for 2.7.0.

Fixes #3395.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/includes/extend/akismet.php

    r7197 r7204  
    6868        // Update post meta
    6969        add_action( 'wp_insert_post', array( $this, 'update_post_meta' ), 10, 2 );
     70
     71        // Cleanup
     72        add_action( 'akismet_scheduled_delete', array( $this, 'delete_old_spam' ) );
     73        add_action( 'akismet_scheduled_delete', array( $this, 'delete_old_spam_meta' ) );
     74        add_action( 'akismet_scheduled_delete', array( $this, 'delete_orphaned_spam_meta' ) );
    7075
    7176        // Admin
     
    955960        <?php
    956961    }
     962
     963    /**
     964     * Deletes old spam topics & replies from the queue after 15 days
     965     * (determined by `_bbp_akismet_delete_spam_interval` filter).
     966     *
     967     * @since 2.6.7 bbPress (r7203)
     968     *
     969     * @global wpdb $wpdb
     970     */
     971    public function delete_old_spam() {
     972        global $wpdb;
     973
     974        /**
     975         * Determines how many posts will be deleted in each batch.
     976         *
     977         * @param int The default as defined by AKISMET_DELETE_LIMIT (also used
     978         *            in Akismet WordPress plugin).
     979         */
     980        $delete_limit = (int) apply_filters( '_bbp_akismet_delete_spam_limit',
     981            defined( 'AKISMET_DELETE_LIMIT' )
     982                ? AKISMET_DELETE_LIMIT
     983                : 10000
     984        );
     985
     986        // Validate the deletion limit
     987        $delete_limit = max( 1, intval( $delete_limit ) );
     988
     989        /**
     990         * Determines how many days a piece of spam will be left in the Spam
     991         * queue before being deleted.
     992         *
     993         * @param int The default number of days.
     994         */
     995        $delete_interval = (int) apply_filters( '_bbp_akismet_delete_spam_interval', 15 );
     996
     997        // Validate the deletion interval
     998        $delete_interval = max( 1, intval( $delete_interval ) );
     999
     1000        // Setup the query
     1001        $sql = "SELECT id FROM {$wpdb->posts} WHERE post_type IN ('topic', 'reply') AND post_status = 'spam' AND DATE_SUB(NOW(), INTERVAL %d DAY) > post_date_gmt LIMIT %d";
     1002
     1003        // Query loop of topic & reply IDs
     1004        while ( $spam_ids = $wpdb->get_col( $wpdb->prepare( $sql, $delete_interval, $delete_limit ) ) ) {
     1005
     1006            // Exit loop if no spam IDs
     1007            if ( empty( $spam_ids ) ) {
     1008                break;
     1009            }
     1010
     1011            // Reset queries
     1012            $wpdb->queries = array();
     1013
     1014            // Loop through each of the topic/reply IDs
     1015            foreach ( $spam_ids as $spam_id ) {
     1016
     1017                /**
     1018                 * Perform a single action on the single topic/reply ID for
     1019                 * simpler batch processing.
     1020                 *
     1021                 * Maybe we should run the bbp_delete_topic or bbp_delete_reply
     1022                 * actions here, too?
     1023                 *
     1024                 * @param string The current function.
     1025                 * @param int    The current topic/reply ID.
     1026                 */
     1027                do_action( '_bbp_akismet_batch_delete', __FUNCTION__, $spam_id );
     1028            }
     1029
     1030            // Prepared as strings since id is an unsigned BIGINT, and using %
     1031            // will constrain the value to the maximum signed BIGINT.
     1032            $format_string = implode( ", ", array_fill( 0, count( $spam_ids ), '%s' ) );
     1033
     1034            // Run the delete queries
     1035            $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->posts} WHERE post_id IN ( " . $format_string . " )", $spam_ids ) );
     1036            $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE post_id IN ( " . $format_string . " )", $spam_ids ) );
     1037
     1038            // Clean the post cache for these topics & replies
     1039            clean_post_cache( $spam_ids );
     1040
     1041            /**
     1042             * Single action that encompasses all topic/reply IDs after the
     1043             * delete queries have been run.
     1044             *
     1045             * @param int   Count of topic/reply IDs
     1046             * @param array Array of topic/reply IDs
     1047             */
     1048            do_action( '_bbp_akismet_delete_spam_count', count( $spam_ids ), $spam_ids );
     1049        }
     1050
     1051        /**
     1052         * Determines whether tables should be optimized.
     1053         *
     1054         * @param int Random number between 1 and 5000.
     1055         */
     1056        $optimize = (int) apply_filters( '_bbp_akismet_optimize_tables', mt_rand( 1, 5000 ), array( $wpdb->posts, $wpdb->postmeta ) );
     1057
     1058        // Lucky number 11
     1059        if ( 11 === $optimize ) {
     1060            $wpdb->query( "OPTIMIZE TABLE {$wpdb->posts}" );
     1061            $wpdb->query( "OPTIMIZE TABLE {$wpdb->postmeta}" );
     1062        }
     1063    }
     1064
     1065    /**
     1066     * Deletes `_bbp_akismet_as_submitted` meta keys after 15 days, since they
     1067     * are large and not useful in the long term.
     1068     *
     1069     * @since 2.6.7 bbPress (r7203)
     1070     *
     1071     * @global wpdb $wpdb
     1072     */
     1073    public function delete_old_spam_meta() {
     1074        global $wpdb;
     1075
     1076        /**
     1077         * Determines how many days a piece of spam will be left in the Spam
     1078         * queue before being deleted.
     1079         *
     1080         * @param int The default number of days.
     1081         */
     1082        $interval = (int) apply_filters( '_bbp_akismet_delete_spam_meta_interval', 15 );
     1083
     1084        // Validate the deletion interval
     1085        $interval = max( 1, intval( $interval ) );
     1086
     1087        // Setup the query
     1088        $sql = "SELECT m.post_id FROM {$wpdb->postmeta} as m INNER JOIN {$wpdb->posts} as p ON m.post_id = p.id WHERE m.meta_key = '_bbp_akismet_as_submitted' AND DATE_SUB(NOW(), INTERVAL %d DAY) > p.post_date_gmt LIMIT 10000";
     1089
     1090        // Query loop of topic & reply IDs
     1091        while ( $spam_ids = $wpdb->get_col( $wpdb->prepare( $sql, $interval ) ) ) {
     1092
     1093            // Exit loop if no spam IDs
     1094            if ( empty( $spam_ids ) ) {
     1095                break;
     1096            }
     1097
     1098            // Reset queries
     1099            $wpdb->queries = array();
     1100
     1101            // Loop through each of the topic/reply IDs
     1102            foreach ( $spam_ids as $spam_id ) {
     1103
     1104                // Delete the as_submitted meta data
     1105                delete_post_meta( $spam_id, '_bbp_akismet_as_submitted' );
     1106
     1107                /**
     1108                 * Perform a single action on the single topic/reply ID for
     1109                 * simpler batch processing.
     1110                 *
     1111                 * @param string The current function.
     1112                 * @param int    The current topic/reply ID.
     1113                 */
     1114                do_action( '_bbp_akismet_batch_delete', __FUNCTION__, $spam_id );
     1115            }
     1116
     1117            /**
     1118             * Single action that encompasses all topic/reply IDs after the
     1119             * delete queries have been run.
     1120             *
     1121             * @param int   Count of topic/reply IDs
     1122             * @param array Array of topic/reply IDs
     1123             */
     1124            do_action( '_bbp_akismet_delete_spam_meta_count', count( $spam_ids ), $spam_ids );
     1125        }
     1126
     1127        // Maybe optimize
     1128        $this->maybe_optimize_postmeta();
     1129    }
     1130
     1131    /**
     1132     * Clears post meta that no longer has corresponding posts in the database.
     1133     *
     1134     * @since 2.6.7 bbPress (r7203)
     1135     *
     1136     * @global wpdb $wpdb
     1137     */
     1138    public function delete_orphaned_spam_meta() {
     1139        global $wpdb;
     1140
     1141        $last_meta_id = 0;
     1142
     1143        // Start time (float)
     1144        $start_time = isset( $_SERVER['REQUEST_TIME_FLOAT'] )
     1145            ? (float) $_SERVER['REQUEST_TIME_FLOAT']
     1146            : microtime( true );
     1147
     1148        // Maximum time
     1149        $max_exec_time = (float) max( ini_get( 'max_execution_time' ) - 5, 3 );
     1150
     1151        // Setup the query
     1152        $sql = "SELECT m.meta_id, m.post_id, m.meta_key FROM {$wpdb->postmeta} as m LEFT JOIN {$wpdb->posts} as p ON m.post_id = p.id WHERE p.id IS NULL AND m.meta_id > %d ORDER BY m.meta_id LIMIT 1000";
     1153
     1154        // Query loop of topic & reply IDs
     1155        while ( $spam_meta_results = $wpdb->get_results( $wpdb->prepare( $sql, $last_meta_id ) ) ) {
     1156
     1157            // Exit loop if no spam IDs
     1158            if ( empty( $spam_meta_results ) ) {
     1159                break;
     1160            }
     1161
     1162            // Reset queries
     1163            $wpdb->queries = array();
     1164
     1165            // Reset deleted meta count
     1166            $spam_meta_deleted = array();
     1167
     1168            // Loop through each of the metas
     1169            foreach ( $spam_meta_results as $spam_meta ) {
     1170
     1171                // Skip if not an Akismet key
     1172                if ( 'akismet_' !== substr( $spam_meta->meta_key, 0, 8 ) ) {
     1173                    continue;
     1174                }
     1175
     1176                // Delete the meta
     1177                delete_post_meta( $spam_meta->post_id, $spam_meta->meta_key );
     1178
     1179                /**
     1180                 * Perform a single action on the single topic/reply ID for
     1181                 * simpler batch processing.
     1182                 *
     1183                 * @param string The current function.
     1184                 * @param int    The current topic/reply ID.
     1185                 */
     1186                do_action( '_bbp_akismet_batch_delete', __FUNCTION__, $spam_meta );
     1187
     1188                // Stash the meta ID being deleted
     1189                $spam_meta_deleted[] = $last_meta_id = $spam_meta->meta_id;
     1190            }
     1191
     1192            /**
     1193             * Single action that encompasses all topic/reply IDs after the
     1194             * delete queries have been run.
     1195             *
     1196             * @param int   Count of spam meta IDs
     1197             * @param array Array of spam meta IDs
     1198             */
     1199            do_action( '_bbp_akismet_delete_spam_meta_count', count( $spam_meta_deleted ), $spam_meta_deleted );
     1200
     1201            // Break if getting close to max_execution_time.
     1202            if ( ( microtime( true ) - $start_time ) > $max_exec_time ) {
     1203                break;
     1204            }
     1205        }
     1206
     1207        // Maybe optimize
     1208        $this->maybe_optimize_postmeta();
     1209    }
     1210
     1211    /**
     1212     * Maybe OPTIMIZE the _postmeta database table.
     1213     *
     1214     * @since 2.7.0 bbPress (r7203)
     1215     *
     1216     * @global wpdb $wpdb
     1217     */
     1218    private function maybe_optimize_postmeta() {
     1219        global $wpdb;
     1220
     1221        /**
     1222         * Determines whether tables should be optimized.
     1223         *
     1224         * @param int Random number between 1 and 5000.
     1225         */
     1226        $optimize = (int) apply_filters( '_bbp_akismet_optimize_table', mt_rand( 1, 5000 ), $wpdb->postmeta );
     1227
     1228        // Lucky number 11
     1229        if ( 11 === $optimize ) {
     1230            $wpdb->query( "OPTIMIZE TABLE {$wpdb->postmeta}" );
     1231        }
     1232    }
    9571233}
    9581234endif;
Note: See TracChangeset for help on using the changeset viewer.