From 00afe5917bca3d5b52bdfd6e5b5c703f73920452 Mon Sep 17 00:00:00 2001 From: Ian Dunn Date: Tue, 18 Jan 2022 16:32:01 -0800 Subject: [PATCH] Header/Footer: Add `global-header-footer/v1/styles` route for Profiles. Profiles can't access the styles directly because it's on the BuddyPress network rather than the w.org one. See #81 --- .../blocks/global-header-footer/blocks.php | 104 +++++++++++++++++- .../global-header-footer/classic-header.php | 4 +- 2 files changed, 103 insertions(+), 5 deletions(-) diff --git a/mu-plugins/blocks/global-header-footer/blocks.php b/mu-plugins/blocks/global-header-footer/blocks.php index 50e3f0eeb..0ed4f6c04 100644 --- a/mu-plugins/blocks/global-header-footer/blocks.php +++ b/mu-plugins/blocks/global-header-footer/blocks.php @@ -112,6 +112,21 @@ function register_routes() { ), ) ); + + // Requesting this on another network would create an infinite loop. + if ( is_wporg_network() ) { + register_rest_route( + 'global-header-footer/v1', + 'styles', + array( + array( + 'methods' => WP_REST_Server::READABLE, + 'callback' => __NAMESPACE__ . '\rest_render_global_styles', + 'permission_callback' => '__return_true', + ), + ) + ); + } } /** @@ -719,6 +734,35 @@ function render_global_footer() { return $markup; } +/** + * Check if the current site is part of the w.org network. + * + * These blocks are used on some sites (like profiles.w.org) that are running WP, but in a different network. + * In those sites, some things need to behave differently (e.g., because `switch_to_blog()` wouldn't work). + */ +function is_wporg_network() { + return 0 === strpos( $_SERVER['SCRIPT_FILENAME'], WPORGPATH ); +} + +/** + * Render the global styles via a REST request. + * + * @return string + */ +function rest_render_global_styles( $request ) { + // Serve the request as CSS. + add_filter( 'rest_pre_serve_request', function( $served, $result ) { + header( 'Content-Type: text/css' ); + header( 'X-Robots-Tag: noindex, follow' ); + + echo $result->get_data(); + + return true; + }, 10, 2 ); + + return get_global_styles(); +} + /** * Output just the variables generated by `theme.json` from the News site. * @@ -727,20 +771,74 @@ function render_global_footer() { * * @see `wp_get_global_stylesheet()` */ -function render_global_styles() { +function get_global_styles() { + /* + * The block is used on some sites (like profiles.w.org) that are running WP, but in a different + * network. On those sites, things like `switch_to_blog()` won't work, so they need to use the API. + */ + if ( ! is_wporg_network() ) { + return fetch_global_styles(); + } + // Switch to `w.org/news-test` to generate correct theme properties. switch_to_blog( 706 ); // TODO change this to `w.org/news` when the redesign launches. // Clear the static `$theme` property, which is set by the current (classic theme) site. WP_Theme_JSON_Resolver::clean_cached_data(); - echo wp_get_global_stylesheet( [ 'variables' ] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + $styles = wp_get_global_stylesheet( [ 'variables' ] ); // Also set the block-gap style, which isn't technically a theme variable. - echo 'body { --wp--style--block-gap: 24px; }'; + $styles .= 'body { --wp--style--block-gap: 24px; }'; // Restore to current site. restore_current_blog(); WP_Theme_JSON_Resolver::clean_cached_data(); + + return $styles; +} + +/** + * Fetch the global styles via the API endpoint + * + * @see `get_global_styles()` for background. + */ +function fetch_global_styles() { + $cache_key = 'global_header_styles'; + $styles = get_transient( $cache_key ); + + if ( ! $styles ) { + $styles = ''; + $request_args = array(); + + // Route request to sandbox when testing. + if ( defined( 'WPORG_SANDBOXED' ) && WPORG_SANDBOXED ) { + $hostname = '127.0.0.1'; + $request_args['headers']['host'] = 'wordpress.org'; + + /* + * It's expected that the sandbox hostname won't be valid. This is safe because we're only connecting + * to `127.0.0.1`. + */ + $request_args['sslverify'] = false; + + } else { + $hostname = 'wordpress.org'; + } + + $response = wp_remote_get( "https://$hostname/wp-json/global-header-footer/v1/styles", $request_args ); + $response_code = wp_remote_retrieve_response_code( $response ); + + if ( is_wp_error( $response ) || 200 !== $response_code ) { + trigger_error( "Fetching global styles failed.", E_USER_WARNING ); + + } else { + $styles = wp_remote_retrieve_body( $response ); + + set_transient( $cache_key, $styles, HOUR_IN_SECONDS ); + } + } + + return $styles; } /** diff --git a/mu-plugins/blocks/global-header-footer/classic-header.php b/mu-plugins/blocks/global-header-footer/classic-header.php index b18d64d49..cf4962335 100644 --- a/mu-plugins/blocks/global-header-footer/classic-header.php +++ b/mu-plugins/blocks/global-header-footer/classic-header.php @@ -2,7 +2,7 @@ namespace WordPressdotorg\MU_Plugins\Global_Header_Footer\Header; -use function WordPressdotorg\MU_Plugins\Global_Header_Footer\render_global_styles; +use function WordPressdotorg\MU_Plugins\Global_Header_Footer\{ get_global_styles }; defined( 'WPINC' ) || die(); @@ -23,7 +23,7 @@ output first, so they can be overridden if needed. -->