schedule_cornerstone_cronjob(); } /** * * @since 3.12.0 */ public static function deactivate() { wp_unschedule_hook( 'jetpack_boost_preload_cornerstone' ); } /** * Schedule the cronjob to preload the cache for Cornerstone Pages. * * @since 3.12.0 * @return void */ public function schedule_cornerstone_cronjob() { if ( ! wp_next_scheduled( 'jetpack_boost_preload_cornerstone' ) ) { wp_schedule_event( time(), 'twicehourly', 'jetpack_boost_preload_cornerstone' ); } } /** * Schedule Preload for all Cornerstone Pages. * * This method is triggered when the Cornerstone Pages list is updated, * ensuring all Cornerstone Pages have their cache rebuilt. * * @since 3.12.0 * @return void */ public function schedule_cornerstone() { wp_schedule_single_event( time(), 'jetpack_boost_preload_cornerstone' ); } /** * Schedule a rebuild for the given URLs. * * @since 3.12.0 * @param array $urls The URLs of the Cornerstone Pages to rebuild. * @return void */ public function schedule( array $urls ) { Logger::debug( sprintf( 'Scheduling preload for %d pages', count( $urls ) ) ); wp_schedule_single_event( time(), 'jetpack_boost_preload', array( $urls ) ); } /** * Rebuild the cache for all Cornerstone Pages. * * @since 3.12.0 * @return void */ public function preload_cornerstone() { $urls = Cornerstone_Utils::get_list(); $this->preload( $urls ); } /** * Rebuild the cache for the given URLs. * * @since 3.12.0 * @param array $urls The URLs of the pages to preload. * @return void */ public function preload( array $urls ) { Logger::debug( sprintf( 'Preload started for %d pages', count( $urls ) ) ); // Pause the hook here to avoid an infinite loop of: invalidation → preload → invalidation. remove_action( 'jetpack_boost_invalidate_cache_success', array( $this, 'handle_cache_invalidation' ) ); $boost_cache = new Boost_Cache(); foreach ( $urls as $url ) { $boost_cache->invalidate_cache_for_url( $url, Filesystem_Utils::REBUILD_FILES ); $this->request_page( $url ); } add_action( 'jetpack_boost_invalidate_cache_success', array( $this, 'handle_cache_invalidation' ), 10, 2 ); Logger::debug( sprintf( 'Preload completed for %d pages', count( $urls ) ) ); } /** * Requests the pages scheduled for preload. * * @since 3.11.0 * @param array $posts The posts to preload. * @return void */ public function request_pages( $posts ) { if ( empty( $posts ) ) { return; } foreach ( $posts as $url ) { $this->request_page( $url ); } } /** * Make an HTTP request to the specified URL to generate a fresh cache entry. * * @since 3.11.0 * @param string $page The URL of the page to preload. * @return void */ private function request_page( string $page ) { // Add a cache-busting header to ensure our response is fresh. $args = array( 'headers' => array( 'Cache-Control' => 'no-cache, no-store, must-revalidate, max-age=0', 'Pragma' => 'no-cache', 'Expires' => '0', ), ); $response = wp_remote_get( $page, $args ); if ( is_wp_error( $response ) ) { Logger::debug( 'Error preloading page: ' . $response->get_error_message() ); return; } $status_code = wp_remote_retrieve_response_code( $response ); if ( $status_code !== 200 ) { Logger::debug( sprintf( 'Error preloading page %s: HTTP status code %d', $page, $status_code ) ); } } /** * Handle post updates to check if the post is a cornerstone page and schedule preload if needed. * * @since 3.11.0 * @param int $post_id The ID of the post being updated. * @return void */ public function handle_post_update( int $post_id ) { if ( Cornerstone_Utils::is_cornerstone_page( $post_id ) ) { $this->schedule( array( get_permalink( $post_id ) ) ); } } /** * Handle cache invalidation events to schedule preloading for affected pages. * * If cache for Cornerstone Pages is invalidated, this method schedules those pages * for preloading to ensure they have fresh cache. * * @since 3.11.0 * @param string $path The path that was invalidated. * @param string $type The type of invalidation that occurred (e.g., Filesystem_Utils::DELETE_ALL). * @return void */ public function handle_cache_invalidation( string $path, string $type ) { if ( $type === Filesystem_Utils::DELETE_ALL ) { // If the cache is invalidated for all files, schedule preload for all Cornerstone Pages. $this->schedule_cornerstone(); return; } // Otherwise identify if a Cornerstone Page cache file is being deleted and schedule preload that page if it is. $cornerstone_pages = Cornerstone_Utils::get_list(); $cornerstone_pages = array_map( 'untrailingslashit', $cornerstone_pages ); // If the $path is in the Cornerstone Page list, add it to the preload list. if ( in_array( untrailingslashit( $path ), $cornerstone_pages, true ) ) { $this->schedule( array( $path ) ); } } public static function get_parent_features(): array { return array( Page_Cache::class, ); } }