false, 'message' => __( 'API Token and Zone ID are required.', 'speednest' ), ); } $endpoint = self::API_BASE . '/zones/' . sanitize_text_field( $zone_id ); $response = wp_remote_get( $endpoint, array( 'headers' => array( 'Authorization' => 'Bearer ' . $api_token, 'Content-Type' => 'application/json', ), 'timeout' => 10, ) ); if ( is_wp_error( $response ) ) { return array( 'success' => false, 'message' => $response->get_error_message(), ); } $code = wp_remote_retrieve_response_code( $response ); $body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( 200 === $code && ! empty( $body['success'] ) ) { $zone_name = isset( $body['result']['name'] ) ? $body['result']['name'] : ''; return array( 'success' => true, 'message' => sprintf( /* translators: %s: zone name */ __( 'Connected successfully to zone: %s', 'speednest' ), $zone_name ), 'zone' => $body['result'], ); } $error_msg = ''; if ( ! empty( $body['errors'] ) ) { $errors = wp_list_pluck( $body['errors'], 'message' ); $error_msg = implode( ', ', $errors ); } return array( 'success' => false, 'message' => sprintf( /* translators: %1$d: HTTP code, %2$s: error */ __( 'Connection failed (HTTP %1$d): %2$s', 'speednest' ), $code, $error_msg ), ); } /** * Purge everything from Cloudflare. * * @return array */ public function purge_everything() { $purger = new WPSCO_Cache_Purger(); return $purger->purge_cloudflare(); } /** * Purge specific URLs from Cloudflare. * * @param array $urls URLs to purge. * @return array */ public function purge_urls( $urls ) { $api_token = wpsco_get_setting( 'cloudflare_api_token', '' ); $zone_id = wpsco_get_setting( 'cloudflare_zone_id', '' ); if ( empty( $api_token ) || empty( $zone_id ) ) { return array( 'success' => false, 'message' => __( 'Cloudflare not configured.', 'speednest' ), ); } $endpoint = self::API_BASE . '/zones/' . sanitize_text_field( $zone_id ) . '/purge_cache'; // Cloudflare allows max 30 URLs per request. $batches = array_chunk( $urls, 30 ); $success = true; $errors = array(); foreach ( $batches as $batch ) { $response = wp_remote_request( $endpoint, array( 'method' => 'POST', 'headers' => array( 'Authorization' => 'Bearer ' . $api_token, 'Content-Type' => 'application/json', ), 'body' => wp_json_encode( array( 'files' => $batch ) ), 'timeout' => 15, ) ); if ( is_wp_error( $response ) ) { $success = false; $errors[] = $response->get_error_message(); continue; } $body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( empty( $body['success'] ) ) { $success = false; if ( ! empty( $body['errors'] ) ) { $errors = array_merge( $errors, wp_list_pluck( $body['errors'], 'message' ) ); } } } return array( 'success' => $success, 'message' => $success ? sprintf( /* translators: %d: number of URLs */ __( 'Purged %d URLs from Cloudflare.', 'speednest' ), count( $urls ) ) : __( 'Some URLs failed to purge: ', 'speednest' ) . implode( ', ', $errors ), ); } /** * Auto-purge on post update. * * @param int $post_id Post ID. */ public function on_post_update( $post_id ) { if ( wp_is_post_revision( $post_id ) || ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) ) { return; } $url = get_permalink( $post_id ); if ( $url ) { $this->purge_urls( array( $url, home_url( '/' ) ) ); } } /** * Auto-purge on product change (WooCommerce). * * @param object $product WC_Product or similar. */ public function on_product_change( $product ) { if ( is_object( $product ) && method_exists( $product, 'get_id' ) ) { $url = get_permalink( $product->get_id() ); if ( $url ) { $this->purge_urls( array( $url ) ); } } } }