s = AccessIQ_Settings::instance(); add_action( 'accessiq_scheduled_scan', [ $this, 'run_scheduled_scan' ] ); add_action( 'accessiq_cleanup_old_data', [ $this, 'cleanup_old_data' ] ); add_action( 'accessiq_settings_saved', [ $this, 'reschedule' ] ); add_filter( 'cron_schedules', [ $this, 'add_schedules' ] ); $this->maybe_schedule(); } public function add_schedules( $schedules ) { $schedules['accessiq_weekly'] = [ 'interval' => WEEK_IN_SECONDS, 'display' => 'Weekly' ]; $schedules['accessiq_monthly'] = [ 'interval' => MONTH_IN_SECONDS, 'display' => 'Monthly' ]; return $schedules; } public function maybe_schedule() { if ( ! $this->s->get( 'schedule_enabled' ) ) return; if ( ! wp_next_scheduled( 'accessiq_scheduled_scan' ) ) { $freq = 'accessiq_' . $this->s->get( 'schedule_freq', 'weekly' ); wp_schedule_event( time(), $freq, 'accessiq_scheduled_scan' ); } if ( ! wp_next_scheduled( 'accessiq_cleanup_old_data' ) ) { wp_schedule_event( time(), 'daily', 'accessiq_cleanup_old_data' ); } } public function reschedule() { wp_clear_scheduled_hook( 'accessiq_scheduled_scan' ); wp_clear_scheduled_hook( 'accessiq_cleanup_old_data' ); $this->maybe_schedule(); } /** * Run scheduled scan: trigger server-side scans for up to 10 published pages. */ public function run_scheduled_scan() { $pages = get_posts( array( 'post_type' => array( 'page', 'post' ), 'posts_per_page' => 10, 'post_status' => 'publish', ) ); $nonce = wp_create_nonce( 'accessiq_nonce' ); $count = 0; foreach ( $pages as $page ) { $url = get_permalink( $page->ID ); if ( ! $url ) { continue; } // Fire-and-forget — 5s timeout, non-blocking. wp_remote_post( admin_url( 'admin-ajax.php' ), array( 'timeout' => 5, 'blocking' => false, 'body' => array( 'action' => 'accessiq_scheduled_scan_page', 'nonce' => $nonce, 'url' => $url, ), ) ); ++$count; } // Send notification email. $email = $this->s->get( 'notify_email', get_option( 'admin_email' ) ); if ( $email ) { wp_mail( $email, __( 'AccessIQ — Scheduled Scan Triggered', 'accessiq' ), /* translators: 1: number of pages, 2: site URL */ sprintf( __( 'A scheduled accessibility scan has been triggered for %1$d pages on %2$s.', 'accessiq' ), $count, home_url() ) ); } } /** * Delete analytics rows older than the configured retention period. * Runs daily via cron. */ public function cleanup_old_data() { global $wpdb; $days = absint( get_option( 'accessiq_analytics_data_retention', 90 ) ); if ( $days < 7 ) { $days = 7; // safety minimum } $cutoff = gmdate( 'Y-m-d H:i:s', strtotime( '-' . $days . ' days', current_time( 'timestamp' ) ) ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query( $wpdb->prepare( 'DELETE FROM `' . esc_sql( $wpdb->prefix . 'accessiq_clicks' ) . '` WHERE created_at < %s', $cutoff ) ); $wpdb->query( $wpdb->prepare( 'DELETE FROM `' . esc_sql( $wpdb->prefix . 'accessiq_sessions' ) . '` WHERE created_at < %s', $cutoff ) ); $wpdb->query( $wpdb->prepare( 'DELETE FROM `' . esc_sql( $wpdb->prefix . 'accessiq_page_views' ) . '` WHERE created_at < %s', $cutoff ) ); // phpcs:enable } }