Skip to content

Commit

Permalink
Pattern Directory: Merge Core locale, caching updates (#33052)
Browse files Browse the repository at this point in the history
* Pattern Directory: Send locale, version with remote pattern requests.

This information is needed by the w.org API for translation and caching.

Merges https://core.trac.wordpress.org/changeset/51206
See https://core.trac.wordpress.org/ticket/53435

Co-authored-by: Dion Hulse <[email protected]>
Co-authored-by: Kelly Dwan <[email protected]>
Co-authored-by: tellyworth <[email protected]>

* Pattern Directory: Move caching to endpoint for unique responses.

Now that the pattern API request includes the locale and version, the cache key needs to contain a hash of the query args.

Merges https://core.trac.wordpress.org/changeset/51208
See https://core.trac.wordpress.org/ticket/53435

Co-authored-by: Dominik Schilling <[email protected]>
Co-authored-by: Dion Hulse <[email protected]>
Co-authored-by: Timothy Jacobs <[email protected]>

* Pattern Directory: Enable PHPUnit tests.

The tests were failing in `wp-env` because the latest Core updates had not been backported, so they were disabled in #32228. Now that the updates are backported, the tests pass again.

* Pattern Directory: Add Core's `should_load_remote_block_patterns` filter.

The filter was added to Core during the process of syncing it with Gutenberg, but wasn't backported to Gutenberg until now.

See https://core.trac.wordpress.org/ticket/53246

Co-authored-by: Kelly Dwan <[email protected]>

Co-authored-by: Dion Hulse <[email protected]>
Co-authored-by: Kelly Dwan <[email protected]>
Co-authored-by: tellyworth <[email protected]>
Co-authored-by: Dominik Schilling <[email protected]>
Co-authored-by: Timothy Jacobs <[email protected]>
  • Loading branch information
6 people authored Jul 13, 2021
1 parent f463c8f commit 2e872ff
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 84 deletions.
26 changes: 18 additions & 8 deletions lib/block-patterns.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,26 @@ function remove_core_patterns() {
}

/**
* Import patterns from wordpress.org/patterns.
* Register Core's official patterns from wordpress.org/patterns.
*
* @since 5.8.0
*/
function load_remote_patterns() {
// This is the core function that provides the same feature.
if ( function_exists( '_load_remote_block_patterns' ) ) {
return;
}
$patterns = get_transient( 'gutenberg_remote_block_patterns' );
if ( ! $patterns ) {

/**
* Filter to disable remote block patterns.
*
* @since 5.8.0
*
* @param bool $should_load_remote
*/
$should_load_remote = apply_filters( 'should_load_remote_block_patterns', true );

if ( $should_load_remote ) {
$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 );
Expand All @@ -217,12 +228,11 @@ function load_remote_patterns() {
return;
}
$patterns = $response->get_data();
set_transient( 'gutenberg_remote_block_patterns', $patterns, HOUR_IN_SECONDS );
}

foreach ( $patterns as $settings ) {
$pattern_name = 'core/' . sanitize_title( $settings['title'] );
register_block_pattern( $pattern_name, (array) $settings );
foreach ( $patterns as $settings ) {
$pattern_name = 'core/' . sanitize_title( $settings['title'] );
register_block_pattern( $pattern_name, (array) $settings );
}
}
}

Expand Down
104 changes: 77 additions & 27 deletions lib/class-wp-rest-pattern-directory-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,22 @@ public function get_items_permissions_check( $request ) { // phpcs:ignore Variab
* @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
*/
public function get_items( $request ) {
$query_args = array();
/*
* Include an unmodified `$wp_version`, so the API can craft a response that's tailored to
* it. Some plugins modify the version in a misguided attempt to improve security by
* obscuring the version, which can cause invalid requests.
*/
require ABSPATH . WPINC . '/version.php';
require_once ABSPATH . 'wp-admin/includes/plugin.php';

$gutenberg_data = get_plugin_data( dirname( __DIR__ ) . '/gutenberg.php', false );

$query_args = array(
'locale' => get_user_locale(),
'wp-version' => $wp_version, // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- it's defined in `version.php` above.
'gutenberg-version' => $gutenberg_data['Version'],
);

$category_id = $request['category'];
$keyword_id = $request['keyword'];
$search_term = $request['search'];
Expand All @@ -102,38 +117,73 @@ public function get_items( $request ) {
$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 ( ! $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&#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 ),
)
);

if ( is_wp_error( $wporg_response ) ) {
$wporg_response->add_data( array( 'status' => 500 ) );
} else {
// Response has valid data.
$cache_ttl = HOUR_IN_SECONDS;
}

return $wporg_response;
set_site_transient( $transient_key, $raw_patterns, $cache_ttl );
}

// 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&#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(
'status' => 500,
'response' => wp_remote_retrieve_body( $wporg_response ),
)
);
if ( is_wp_error( $raw_patterns ) ) {
$raw_patterns->add_data( array( 'status' => 500 ) );

return $raw_patterns;
}

$response = array();
Expand Down
Loading

0 comments on commit 2e872ff

Please sign in to comment.