true, 'to_date' => $from_date, 'limit' => 1000, ); $deadline = microtime( true ) + 20; do { $deleted = Database::delete_counts( $args ); } while ( $deleted > 0 && microtime( true ) < $deadline ); // Prune visits log rows older than the retention period. $log_table = Database::get_log_table(); $deadline_log = microtime( true ) + 20; do { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared $deleted_log = $wpdb->query( $wpdb->prepare( "DELETE FROM {$log_table} WHERE visited_at < %s LIMIT 1000", $from_date_log ) ); } while ( $deleted_log > 0 && microtime( true ) < $deadline_log ); } /** * Function to enable run or actions. * * @since 3.0.0 * @param int $hour Hour. * @param int $min Minute. * @param string $recurrence Frequency. */ public static function enable_run( $hour, $min, $recurrence ) { // Invoke WordPress internal cron. if ( ! wp_next_scheduled( 'tptn_cron_hook' ) ) { wp_schedule_event( mktime( $hour, $min, 0 ), $recurrence, 'tptn_cron_hook' ); } else { wp_clear_scheduled_hook( 'tptn_cron_hook' ); wp_schedule_event( mktime( $hour, $min, 0 ), $recurrence, 'tptn_cron_hook' ); } } /** * Function to disable daily run or actions. * * @since 3.0.0 */ public static function disable_run() { if ( wp_next_scheduled( 'tptn_cron_hook' ) ) { wp_clear_scheduled_hook( 'tptn_cron_hook' ); } } /** * Drain the visits log into the count tables and prune orphaned log rows. * * @since 4.3.0 */ public function run_aggregation() { Database::aggregate_visit_log(); } /** * Schedule the aggregation cron to run at the configured interval. * * @since 4.3.0 */ public static function enable_aggregation_run() { /** * Override the aggregation cron schedule. Must be a registered WP-Cron recurrence * (e.g. 'one_minute', 'two_minutes', 'three_minutes', 'five_minutes'). * * @since 4.3.0 * * @param string $interval Schedule name. Default 'two_minutes'. */ $interval = (string) apply_filters( 'tptn_aggregation_cron_interval', 'two_minutes' ); if ( ! wp_next_scheduled( 'tptn_aggregation_cron_hook' ) ) { wp_schedule_event( time(), $interval, 'tptn_aggregation_cron_hook' ); } } /** * Remove the aggregation cron. * * @since 4.3.0 */ public static function disable_aggregation_run() { wp_clear_scheduled_hook( 'tptn_aggregation_cron_hook' ); } /** * Check that the aggregation cron is scheduled at the correct interval; reschedule if missing or changed. * * @since 4.3.0 */ public function check_aggregation_cron() { /** This filter is documented in includes/admin/class-cron.php */ $interval = (string) apply_filters( 'tptn_aggregation_cron_interval', 'two_minutes' ); $timestamp = wp_next_scheduled( 'tptn_aggregation_cron_hook' ); if ( ! $timestamp ) { self::enable_aggregation_run(); $this->aggregation_cron_was_missing = true; return; } $crons = _get_cron_array(); $args_key = md5( serialize( array() ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize $current = isset( $crons[ $timestamp ]['tptn_aggregation_cron_hook'][ $args_key ]['schedule'] ) ? $crons[ $timestamp ]['tptn_aggregation_cron_hook'][ $args_key ]['schedule'] : ''; if ( $current !== $interval ) { wp_clear_scheduled_hook( 'tptn_aggregation_cron_hook' ); self::enable_aggregation_run(); $this->aggregation_cron_interval_changed = true; } } /** * Show an admin notice when the aggregation cron was missing or rescheduled due to an interval change. * * @since 4.3.0 */ public function aggregation_cron_missing_notice() { if ( $this->aggregation_cron_interval_changed ) { ?>

aggregation_cron_was_missing ) { ?>

' . esc_html( $hook ) . '', esc_html( $error['message'] ), esc_html( human_time_diff( $error['time'] ) ) ); ?>

$result->get_error_code(), 'message' => $result->get_error_message(), 'time' => time(), ), WEEK_IN_SECONDS ); } /** * Retrieve the last recorded cron scheduling error for a hook, if any. * * @since 4.4.0 * * @param string $hook Hook name. * @return array{code: string, message: string, time: int}|false Error data, or false if none recorded. */ public static function get_reschedule_error( $hook ) { $error = get_transient( self::RESCHEDULE_ERROR_TRANSIENT_PREFIX . $hook ); return is_array( $error ) ? $error : false; } /** * Clear the recorded cron scheduling errors for all tracked hooks. * * @since 4.4.0 */ public static function clear_reschedule_errors() { foreach ( self::TRACKED_HOOKS as $hook ) { delete_transient( self::RESCHEDULE_ERROR_TRANSIENT_PREFIX . $hook ); } } }