Skip to content

Commit

Permalink
Move Pattern Directory categories endpoint to compat/6.3 (#47486)
Browse files Browse the repository at this point in the history
  • Loading branch information
ntsekouras authored Jan 27, 2023
1 parent 1d8651a commit 4782195
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.', '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
*
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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
Expand Down
9 changes: 0 additions & 9 deletions lib/compat/wordpress-6.2/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php
/**
* REST API: Gutenberg_REST_Pattern_Directory_Controller_6_3 class
*
* @package Gutenberg
* @subpackage REST_API
*/

/**
* Controller which provides REST endpoint for block patterns from wordpress.org/patterns.
*/
class Gutenberg_REST_Pattern_Directory_Controller_6_3 extends Gutenberg_REST_Pattern_Directory_Controller_6_2 {
/**
* Registers the necessary REST API routes.
*
* @since 5.8.0
* @since 6.3.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.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&#8217;s configuration. If you continue to have problems, please try the <a href="%s">support forums</a>.', '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 );
}
}
15 changes: 15 additions & 0 deletions lib/compat/wordpress-6.3/rest-api.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
/**
* Overrides Core's wp-includes/rest-api.php and registers the new endpoint for WP 6.3.
*
* @package gutenberg
*/

/**
* Registers the block pattern directory.
*/
function gutenberg_register_rest_pattern_directory() {
$pattern_directory_controller = new Gutenberg_REST_Pattern_Directory_Controller_6_3();
$pattern_directory_controller->register_routes();
}
add_action( 'rest_api_init', 'gutenberg_register_rest_pattern_directory' );
4 changes: 4 additions & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit 4782195

Please sign in to comment.