diff --git a/wp-includes/block-patterns.php b/wp-includes/block-patterns.php
index 0d539f7a24..38ca373723 100644
--- a/wp-includes/block-patterns.php
+++ b/wp-includes/block-patterns.php
@@ -45,7 +45,11 @@ function _register_core_block_patterns_and_categories() {
}
/**
- * Import patterns from wordpress.org/patterns.
+ * Register Core's official patterns from wordpress.org/patterns.
+ *
+ * @since 5.8.0
+ *
+ * @param WP_Screen $current_screen The screen that the current request was triggered from.
*/
function _load_remote_block_patterns( $current_screen ) {
if ( ! $current_screen->is_block_editor ) {
@@ -64,18 +68,14 @@ function _load_remote_block_patterns( $current_screen ) {
$should_load_remote = apply_filters( 'should_load_remote_block_patterns', true );
if ( $supports_core_patterns && $should_load_remote ) {
- $patterns = get_transient( 'wp_remote_block_patterns' );
- if ( ! $patterns ) {
- $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
- $core_keyword_id = 11; // 11 is the ID for "core".
- $request->set_param( 'keyword', $core_keyword_id );
- $response = rest_do_request( $request );
- if ( $response->is_error() ) {
- return;
- }
- $patterns = $response->get_data();
- set_transient( 'wp_remote_block_patterns', $patterns, HOUR_IN_SECONDS );
+ $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
+ $core_keyword_id = 11; // 11 is the ID for "core".
+ $request->set_param( 'keyword', $core_keyword_id );
+ $response = rest_do_request( $request );
+ if ( $response->is_error() ) {
+ return;
}
+ $patterns = $response->get_data();
foreach ( $patterns as $settings ) {
$pattern_name = 'core/' . sanitize_title( $settings['title'] );
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php
index d758b1346d..046c0a8369 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php
@@ -111,38 +111,73 @@ class WP_REST_Pattern_Directory_Controller extends WP_REST_Controller {
$query_args['search'] = $search_term;
}
- $api_url = add_query_arg(
- array_map( 'rawurlencode', $query_args ),
- 'http://api.wordpress.org/patterns/1.0/'
- );
+ /*
+ * Include a hash of the query args, so that different requests are stored in
+ * separate caches.
+ *
+ * MD5 is chosen for its speed, low-collision rate, universal availability, and to stay
+ * under the character limit for `_site_transient_timeout_{...}` keys.
+ *
+ * @link https://stackoverflow.com/questions/3665247/fastest-hash-for-non-cryptographic-uses
+ */
+ $transient_key = 'wp_remote_block_patterns_' . md5( implode( '-', $query_args ) );
- if ( wp_http_supports( array( 'ssl' ) ) ) {
- $api_url = set_url_scheme( $api_url, 'https' );
- }
+ /*
+ * 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_patterns = get_site_transient( $transient_key );
- $wporg_response = wp_remote_get( $api_url );
- $raw_patterns = json_decode( wp_remote_retrieve_body( $wporg_response ) );
-
- if ( is_wp_error( $wporg_response ) ) {
- $wporg_response->add_data( array( 'status' => 500 ) );
-
- return $wporg_response;
- }
-
- // Make sure w.org returned valid data.
- if ( ! is_array( $raw_patterns ) ) {
- return new WP_Error(
- 'pattern_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.' ),
- __( 'https://wordpress.org/support/forums/' )
- ),
- array(
- 'status' => 500,
- 'response' => wp_remote_retrieve_body( $wporg_response ),
- )
+ if ( ! $raw_patterns ) {
+ $api_url = add_query_arg(
+ array_map( 'rawurlencode', $query_args ),
+ 'http://api.wordpress.org/patterns/1.0/'
);
+
+ 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_patterns = json_decode( wp_remote_retrieve_body( $wporg_response ) );
+
+ if ( is_wp_error( $wporg_response ) ) {
+ $raw_patterns = $wporg_response;
+
+ } elseif ( ! is_array( $raw_patterns ) ) {
+ // HTTP request succeeded, but response data is invalid.
+ $raw_patterns = new WP_Error(
+ 'pattern_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.' ),
+ __( 'https://wordpress.org/support/forums/' )
+ ),
+ array(
+ 'response' => wp_remote_retrieve_body( $wporg_response ),
+ )
+ );
+
+ } else {
+ // Response has valid data.
+ $cache_ttl = HOUR_IN_SECONDS;
+ }
+
+ set_site_transient( $transient_key, $raw_patterns, $cache_ttl );
+ }
+
+ if ( is_wp_error( $raw_patterns ) ) {
+ $raw_patterns->add_data( array( 'status' => 500 ) );
+
+ return $raw_patterns;
}
$response = array();
diff --git a/wp-includes/version.php b/wp-includes/version.php
index e837c7856b..cb519aa436 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -13,7 +13,7 @@
*
* @global string $wp_version
*/
-$wp_version = '5.8-beta2-51207';
+$wp_version = '5.8-beta2-51208';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.