> $schedules */ public static function schedules( array $schedules ): array { $schedules['airanksuite_five_minutes'] = array( 'interval' => 5 * MINUTE_IN_SECONDS, 'display' => 'Every five minutes (AI Rank Suite jobs)', ); // No 'weekly' here: WordPress has had its own since 5.4 and it wins over // anything this filter returns. The copy that used to sit here did one // thing only — it translated its label while modules were scheduling // events on plugins_loaded, before init, which WordPress reports as // loading the text domain too early. return $schedules; } /** * Schedule a recurring event, but not before init. * * wp_schedule_event() asks every plugin for its cron schedules, and a * plugin that translates a schedule label in that filter (WooCommerce * does) then loads its text domain during our plugins_loaded boot. Since * WordPress 6.7 that is reported as a notice against the plugin that made * the call. So the call waits for init when it has not happened yet. * wp_next_scheduled() is asked inside the deferred callback, at the * moment the event would be written, so two requests cannot both add one. * * @param string $hook Event hook. * @param string $recurrence Schedule name. * @param int $first_at Unix timestamp of the first run. */ public static function ensure( string $hook, string $recurrence, int $first_at ): void { $schedule = static function () use ( $hook, $recurrence, $first_at ): void { if ( ! wp_next_scheduled( $hook ) ) { wp_schedule_event( $first_at, $recurrence, $hook ); } }; if ( did_action( 'init' ) ) { $schedule(); return; } add_action( 'init', $schedule, 20 ); } /** Remove every event owned by the plugin. */ public static function clear(): void { foreach ( self::hooks() as $hook ) { wp_clear_scheduled_hook( $hook ); } } /** @return array */ private static function hooks(): array { return array( 'airanksuite_backlinks_verify', 'airanksuite_job_rank_snapshot', 'airanksuite_job_score_snapshot', 'airanksuite_ai_visibility_check', 'airanksuite_ai_visibility_batch', 'airanksuite_job_audit_alerts', 'airanksuite_job_email_report', 'airanksuite_autopilot_batch', 'airanksuite_local_listing_refresh', 'airanksuite_job_retention', 'airanksuite_job_resume', 'airanksuite_migrate_tick', 'airanksuite_graph_tick', 'airanksuite_linkscan_tick', ); } }