diff --git a/lib/compat/wordpress-6.2/class-gutenberg-rest-pattern-directory-controller-6-2.php b/lib/compat/wordpress-6.2/class-gutenberg-rest-pattern-directory-controller-6-2.php index e96ee976748ff..7043140c23fcf 100644 --- a/lib/compat/wordpress-6.2/class-gutenberg-rest-pattern-directory-controller-6-2.php +++ b/lib/compat/wordpress-6.2/class-gutenberg-rest-pattern-directory-controller-6-2.php @@ -10,127 +10,6 @@ * Controller which provides REST endpoint for block patterns from wordpress.org/patterns. */ class Gutenberg_REST_Pattern_Directory_Controller_6_2 extends WP_REST_Pattern_Directory_Controller { - /** - * Registers the necessary REST API routes. - * - * @since 5.8.0 - * @since 6.2.0 Added pattern directory categories endpoint. - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->rest_base . '/categories', - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_pattern_categories' ), - 'permission_callback' => array( $this, 'get_items_permissions_check' ), - ), - ) - ); - - parent::register_routes(); - } - - /** - * Retrieve block patterns categories. - * - * @since 6.2.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_pattern_categories( $request ) { - $query_args = array( 'locale' => get_user_locale() ); - $transient_key = 'wp_remote_block_pattern_categories_' . md5( serialize( $query_args ) ); - - /** - * Use network-wide transient to improve performance. The locale is the only site - * configuration that affects the response, and it's included in the transient key. - */ - $raw_pattern_categories = get_site_transient( $transient_key ); - - if ( ! $raw_pattern_categories ) { - $api_url = 'http://api.wordpress.org/patterns/1.0/?categories&' . build_query( $query_args ); - if ( wp_http_supports( array( 'ssl' ) ) ) { - $api_url = set_url_scheme( $api_url, 'https' ); - } - - /** - * Default to a short TTL, to mitigate cache stampedes on high-traffic sites. - * This assumes that most errors will be short-lived, e.g., packet loss that causes the - * first request to fail, but a follow-up one will succeed. The value should be high - * enough to avoid stampedes, but low enough to not interfere with users manually - * re-trying a failed request. - */ - $cache_ttl = 5; - $wporg_response = wp_remote_get( $api_url ); - $raw_pattern_categories = json_decode( wp_remote_retrieve_body( $wporg_response ) ); - if ( is_wp_error( $wporg_response ) ) { - $raw_pattern_categories = $wporg_response; - - } elseif ( ! is_array( $raw_pattern_categories ) ) { - // HTTP request succeeded, but response data is invalid. - $raw_pattern_categories = new WP_Error( - 'pattern_directory_api_failed', - sprintf( - /* translators: %s: Support forums URL. */ - __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.', 'gutenberg' ), - __( 'https://wordpress.org/support/forums/', 'gutenberg' ) - ), - array( - 'response' => wp_remote_retrieve_body( $wporg_response ), - ) - ); - - } else { - // Response has valid data. - $cache_ttl = HOUR_IN_SECONDS; - } - - set_site_transient( $transient_key, $raw_pattern_categories, $cache_ttl ); - } - - if ( is_wp_error( $raw_pattern_categories ) ) { - $raw_pattern_categories->add_data( array( 'status' => 500 ) ); - - return $raw_pattern_categories; - } - - $response = array(); - - if ( $raw_pattern_categories ) { - foreach ( $raw_pattern_categories as $category ) { - $response[] = $this->prepare_response_for_collection( - $this->prepare_pattern_category_for_response( $category, $request ) - ); - } - } - - return new WP_REST_Response( $response ); - } - - /** - * Prepare a raw block pattern category before it gets output in a REST API response. - * - * @since 6.2.0 - * - * @param object $item Raw pattern category from api.wordpress.org, before any changes. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response - */ - public function prepare_pattern_category_for_response( $item, $request ) { - $raw_pattern_category = array( - 'id' => absint( $item->id ), - 'name' => sanitize_text_field( $item->name ), - 'slug' => sanitize_title_with_dashes( $item->slug ), - ); - - $prepared_pattern_category = $this->add_additional_fields_to_object( $raw_pattern_category, $request ); - - return new WP_REST_Response( $prepared_pattern_category ); - } - /** * Search and retrieve block patterns metadata * @@ -174,7 +53,7 @@ public function get_items( $request ) { $transient_key = $this->get_transient_key( $query_args ); - /** + /* * Use network-wide transient to improve performance. The locale is the only site * configuration that affects the response, and it's included in the transient key. */ @@ -186,7 +65,7 @@ public function get_items( $request ) { $api_url = set_url_scheme( $api_url, 'https' ); } - /** + /* * Default to a short TTL, to mitigate cache stampedes on high-traffic sites. * This assumes that most errors will be short-lived, e.g., packet loss that causes the * first request to fail, but a follow-up one will succeed. The value should be high diff --git a/lib/compat/wordpress-6.2/rest-api.php b/lib/compat/wordpress-6.2/rest-api.php index 6161885d020d7..86e7031cb794f 100644 --- a/lib/compat/wordpress-6.2/rest-api.php +++ b/lib/compat/wordpress-6.2/rest-api.php @@ -14,15 +14,6 @@ function gutenberg_register_rest_block_pattern_categories() { } add_action( 'rest_api_init', 'gutenberg_register_rest_block_pattern_categories' ); -/** - * Registers the block pattern directory. - */ -function gutenberg_register_rest_pattern_directory() { - $pattern_directory_controller = new Gutenberg_REST_Pattern_Directory_Controller_6_2(); - $pattern_directory_controller->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_rest_pattern_directory' ); - /** * Registers the block patterns REST API routes. */ diff --git a/lib/compat/wordpress-6.3/class-gutenberg-rest-pattern-directory-controller-6-3.php b/lib/compat/wordpress-6.3/class-gutenberg-rest-pattern-directory-controller-6-3.php new file mode 100644 index 0000000000000..1d1ba16571bc4 --- /dev/null +++ b/lib/compat/wordpress-6.3/class-gutenberg-rest-pattern-directory-controller-6-3.php @@ -0,0 +1,133 @@ +namespace, + '/' . $this->rest_base . '/categories', + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_pattern_categories' ), + 'permission_callback' => array( $this, 'get_items_permissions_check' ), + ), + ) + ); + + parent::register_routes(); + } + + /** + * Retrieve block patterns categories. + * + * @since 6.3.0 + * + * @param WP_REST_Request $request Full details about the request. + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function get_pattern_categories( $request ) { + $query_args = array( 'locale' => get_user_locale() ); + $transient_key = 'wp_remote_block_pattern_categories_' . md5( serialize( $query_args ) ); + + /** + * Use network-wide transient to improve performance. The locale is the only site + * configuration that affects the response, and it's included in the transient key. + */ + $raw_pattern_categories = get_site_transient( $transient_key ); + + if ( ! $raw_pattern_categories ) { + $api_url = 'http://api.wordpress.org/patterns/1.0/?categories&' . build_query( $query_args ); + if ( wp_http_supports( array( 'ssl' ) ) ) { + $api_url = set_url_scheme( $api_url, 'https' ); + } + + /** + * Default to a short TTL, to mitigate cache stampedes on high-traffic sites. + * This assumes that most errors will be short-lived, e.g., packet loss that causes the + * first request to fail, but a follow-up one will succeed. The value should be high + * enough to avoid stampedes, but low enough to not interfere with users manually + * re-trying a failed request. + */ + $cache_ttl = 5; + $wporg_response = wp_remote_get( $api_url ); + $raw_pattern_categories = json_decode( wp_remote_retrieve_body( $wporg_response ) ); + if ( is_wp_error( $wporg_response ) ) { + $raw_pattern_categories = $wporg_response; + + } elseif ( ! is_array( $raw_pattern_categories ) ) { + // HTTP request succeeded, but response data is invalid. + $raw_pattern_categories = new WP_Error( + 'pattern_directory_api_failed', + sprintf( + /* translators: %s: Support forums URL. */ + __( 'An unexpected error occurred. Something may be wrong with WordPress.org or this server’s configuration. If you continue to have problems, please try the support forums.', 'gutenberg' ), + __( 'https://wordpress.org/support/forums/', 'gutenberg' ) + ), + array( + 'response' => wp_remote_retrieve_body( $wporg_response ), + ) + ); + + } else { + // Response has valid data. + $cache_ttl = HOUR_IN_SECONDS; + } + + set_site_transient( $transient_key, $raw_pattern_categories, $cache_ttl ); + } + + if ( is_wp_error( $raw_pattern_categories ) ) { + $raw_pattern_categories->add_data( array( 'status' => 500 ) ); + + return $raw_pattern_categories; + } + + $response = array(); + + if ( $raw_pattern_categories ) { + foreach ( $raw_pattern_categories as $category ) { + $response[] = $this->prepare_response_for_collection( + $this->prepare_pattern_category_for_response( $category, $request ) + ); + } + } + + return new WP_REST_Response( $response ); + } + + /** + * Prepare a raw block pattern category before it gets output in a REST API response. + * + * @since 6.3.0 + * + * @param object $item Raw pattern category from api.wordpress.org, before any changes. + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response + */ + public function prepare_pattern_category_for_response( $item, $request ) { + $raw_pattern_category = array( + 'id' => absint( $item->id ), + 'name' => sanitize_text_field( $item->name ), + 'slug' => sanitize_title_with_dashes( $item->slug ), + ); + + $prepared_pattern_category = $this->add_additional_fields_to_object( $raw_pattern_category, $request ); + + return new WP_REST_Response( $prepared_pattern_category ); + } +} diff --git a/lib/compat/wordpress-6.3/rest-api.php b/lib/compat/wordpress-6.3/rest-api.php new file mode 100644 index 0000000000000..55a45df07d593 --- /dev/null +++ b/lib/compat/wordpress-6.3/rest-api.php @@ -0,0 +1,15 @@ +register_routes(); +} +add_action( 'rest_api_init', 'gutenberg_register_rest_pattern_directory' ); diff --git a/lib/load.php b/lib/load.php index e400d2f8211b3..5a58d40d63d6b 100644 --- a/lib/load.php +++ b/lib/load.php @@ -48,6 +48,10 @@ function gutenberg_is_experiment_enabled( $name ) { require_once __DIR__ . '/compat/wordpress-6.2/block-patterns.php'; require_once __DIR__ . '/compat/wordpress-6.2/class-gutenberg-rest-global-styles-controller-6-2.php'; + // WordPress 6.3 compat. + require_once __DIR__ . '/compat/wordpress-6.3/class-gutenberg-rest-pattern-directory-controller-6-3.php'; + require_once __DIR__ . '/compat/wordpress-6.3/rest-api.php'; + // Experimental. if ( ! class_exists( 'WP_Rest_Customizer_Nonces' ) ) { require_once __DIR__ . '/experimental/class-wp-rest-customizer-nonces.php'; diff --git a/phpunit/class-wp-rest-pattern-directory-controller-test.php b/phpunit/class-wp-rest-pattern-directory-controller-test.php index c05e6b4be114f..12ed9ca9152d0 100644 --- a/phpunit/class-wp-rest-pattern-directory-controller-test.php +++ b/phpunit/class-wp-rest-pattern-directory-controller-test.php @@ -53,7 +53,7 @@ public static function wpSetUpBeforeClass( $factory ) { self::$http_request_urls = array(); - static::$controller = new Gutenberg_REST_Pattern_Directory_Controller_6_2(); + static::$controller = new Gutenberg_REST_Pattern_Directory_Controller_6_3(); } public static function wpTearDownAfterClass() {