Skip to content

Commit

Permalink
Working on revisions
Browse files Browse the repository at this point in the history
Backend resolution of theme file URIs for global styles revisions

Ensuring links are preserved when updating global styles.
  • Loading branch information
ramonjd committed May 10, 2024
1 parent e1c3969 commit a3bda72
Show file tree
Hide file tree
Showing 16 changed files with 258 additions and 94 deletions.
28 changes: 17 additions & 11 deletions lib/class-wp-rest-global-styles-controller-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,10 @@ public function prepare_item_for_response( $post, $request ) { // phpcs:ignore V
$raw_config = json_decode( $post->post_content, true );
$is_global_styles_user_theme_json = isset( $raw_config['isGlobalStylesUserThemeJSON'] ) && true === $raw_config['isGlobalStylesUserThemeJSON'];
$config = array();
$theme_json = array();
if ( $is_global_styles_user_theme_json ) {
$config = ( new WP_Theme_JSON_Gutenberg( $raw_config, 'custom' ) )->get_raw_data();
$theme_json = new WP_Theme_JSON_Gutenberg( $raw_config, 'custom' );
$config = $theme_json->get_raw_data();
}

// Base fields for every post.
Expand Down Expand Up @@ -409,6 +411,13 @@ public function prepare_item_for_response( $post, $request ) { // phpcs:ignore V

if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
$links = $this->prepare_links( $post->ID );
// Only return resolved URIs for get requests to user theme JSON.
if ( $is_global_styles_user_theme_json ) {
$resolved_theme_uris = WP_Theme_JSON_Resolver_Gutenberg::get_resolved_theme_uris( $theme_json );
if ( ! empty( $resolved_theme_uris ) ) {
$links['theme_file_uris'] = $resolved_theme_uris;
}
}
$response->add_links( $links );
if ( ! empty( $links['self']['href'] ) ) {
$actions = $this->get_available_actions();
Expand Down Expand Up @@ -607,34 +616,31 @@ public function get_theme_item( $request ) {
);
}

$theme = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( 'theme' );
$data = array();
$fields = $this->get_fields_for_response( $request );
$resolved_theme_uris = array();
$theme = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( 'theme' );
$data = array();
$fields = $this->get_fields_for_response( $request );

if ( rest_is_field_included( 'settings', $fields ) ) {
$data['settings'] = $theme->get_settings();
}

if ( rest_is_field_included( 'styles', $fields ) ) {
$raw_data = $theme->get_raw_data();
$data['styles'] = isset( $raw_data['styles'] ) ? $raw_data['styles'] : array();
$resolved_theme_uris = WP_Theme_JSON_Resolver_Gutenberg::get_resolved_theme_uris( $theme );
$raw_data = $theme->get_raw_data();
$data['styles'] = isset( $raw_data['styles'] ) ? $raw_data['styles'] : array();
}

$context = ! empty( $request['context'] ) ? $request['context'] : 'view';

Check warning on line 632 in lib/class-wp-rest-global-styles-controller-gutenberg.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space
$data = $this->add_additional_fields_to_object( $data, $request );

Check warning on line 633 in lib/class-wp-rest-global-styles-controller-gutenberg.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Equals sign not aligned with surrounding assignments; expected 5 spaces but found 4 spaces
$data = $this->filter_response_by_context( $data, $context );

Check warning on line 634 in lib/class-wp-rest-global-styles-controller-gutenberg.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Equals sign not aligned with surrounding assignments; expected 5 spaces but found 4 spaces

$response = rest_ensure_response( $data );

if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
$links = array(
$links = array(
'self' => array(
'href' => rest_url( sprintf( '%s/%s/themes/%s', $this->namespace, $this->rest_base, $request['stylesheet'] ) ),
),
);

$resolved_theme_uris = WP_Theme_JSON_Resolver_Gutenberg::get_resolved_theme_uris( $theme );
if ( ! empty( $resolved_theme_uris ) ) {
$links['theme_file_uris'] = $resolved_theme_uris;
}
Expand Down
18 changes: 8 additions & 10 deletions lib/class-wp-theme-json-resolver-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -777,21 +777,19 @@ public static function get_style_variations() {
* @return array An array of resolved paths.
*/
public static function get_resolved_theme_uris( $theme_json ) {
if ( ! $theme_json instanceof WP_Theme_JSON_Gutenberg ) {
return $theme_json;
$resolved_theme_uris = array();

if ( ! $theme_json instanceof WP_Theme_JSON_Gutenberg || empty( $theme_json ) ) {
return $resolved_theme_uris;
}

$theme_json_data = $theme_json->get_raw_data();
$resolved_theme_uris = array();
$theme_json_data = $theme_json->get_raw_data();

/*
* Styles backgrounds.
* Where a URL is not absolute (has no host fragment), it is assumed to be relative to the theme directory.
* Blocks, elements, and block variations are not yet supported.
*/
// Top level styles.
if (
isset( $theme_json_data['styles']['background']['backgroundImage']['url'] ) &&
is_string( $theme_json_data['styles']['background']['backgroundImage']['url'] ) &&
// Where a URL is not absolute (has no host fragment), it is assumed to be relative to the theme directory.
! isset( wp_parse_url( $theme_json_data['styles']['background']['backgroundImage']['url'] )['host'] ) ) {
$resolved_theme_uris[] = array(
'file' => $theme_json_data['styles']['background']['backgroundImage']['url'],
Expand All @@ -805,7 +803,7 @@ public static function get_resolved_theme_uris( $theme_json ) {
// @TODO used in gutenberg_get_global_stylesheet to ensure global stylesheet URIs are resolved.
// Try to harmonize with the above function
public static function resolve_theme_file_uris( $theme_json ) {
if ( ! $theme_json instanceof WP_Theme_JSON_Gutenberg ) {
if ( ! $theme_json instanceof WP_Theme_JSON_Gutenberg || empty( $theme_json ) ) {
return $theme_json;
}

Expand Down
10 changes: 0 additions & 10 deletions lib/compat/wordpress-6.5/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,6 @@
die( 'Silence is golden.' );
}

/**
* Registers the Global Styles Revisions REST API routes.
*/
function gutenberg_register_global_styles_revisions_endpoints() {
$global_styles_revisions_controller = new Gutenberg_REST_Global_Styles_Revisions_Controller_6_5();
$global_styles_revisions_controller->register_routes();
}

add_action( 'rest_api_init', 'gutenberg_register_global_styles_revisions_endpoints' );

/**
* Registers additional fields for wp_template and wp_template_part rest api.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
/**
* REST API: Gutenberg_REST_Global_Styles_Revisions_Controller class, inspired by WP_REST_Revisions_Controller.
*
* @package WordPress
* @subpackage REST_API
* @since 6.3.0
*/

/**
* Core class used to access global styles revisions via the REST API.
*
* @since 6.3.0
*
* @see WP_REST_Controller
*/
class Gutenberg_REST_Global_Styles_Revisions_Controller_6_6 extends Gutenberg_REST_Global_Styles_Revisions_Controller_6_5 {
/**
* Prepares the revision for the REST response.
*
* @since 6.3.0
* @since 6.6.0 Added resolved URI links to the response.
*
* @param WP_Post $post Post revision object.
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response|WP_Error Response object.
*/
public function prepare_item_for_response( $post, $request ) {
$parent = $this->get_parent( $request['parent'] );
$global_styles_config = $this->get_decoded_global_styles_json( $post->post_content );

if ( is_wp_error( $global_styles_config ) ) {
return $global_styles_config;
}

$fields = $this->get_fields_for_response( $request );
$data = array();
$theme_json = array();

if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) ) {
$theme_json = new WP_Theme_JSON_Gutenberg( $global_styles_config, 'custom' );
$global_styles_config = ( $theme_json )->get_raw_data();

if ( rest_is_field_included( 'settings', $fields ) ) {
$data['settings'] = ! empty( $global_styles_config['settings'] ) ? $global_styles_config['settings'] : new stdClass();
}
if ( rest_is_field_included( 'styles', $fields ) ) {
$data['styles'] = ! empty( $global_styles_config['styles'] ) ? $global_styles_config['styles'] : new stdClass();
}
}

if ( rest_is_field_included( 'author', $fields ) ) {
$data['author'] = (int) $post->post_author;
}

if ( rest_is_field_included( 'date', $fields ) ) {
$data['date'] = $this->prepare_date_response( $post->post_date_gmt, $post->post_date );
}

if ( rest_is_field_included( 'date_gmt', $fields ) ) {
$data['date_gmt'] = $this->prepare_date_response( $post->post_date_gmt );
}

if ( rest_is_field_included( 'id', $fields ) ) {
$data['id'] = (int) $post->ID;
}

if ( rest_is_field_included( 'modified', $fields ) ) {
$data['modified'] = $this->prepare_date_response( $post->post_modified_gmt, $post->post_modified );
}

if ( rest_is_field_included( 'modified_gmt', $fields ) ) {
$data['modified_gmt'] = $this->prepare_date_response( $post->post_modified_gmt );
}

if ( rest_is_field_included( 'parent', $fields ) ) {
$data['parent'] = (int) $parent->ID;
}

$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
$data = $this->add_additional_fields_to_object( $data, $request );
$data = $this->filter_response_by_context( $data, $context );

$response = rest_ensure_response( $data );

// Add resolved URIs to the response.
$links = array();
$resolved_theme_uris = WP_Theme_JSON_Resolver_Gutenberg::get_resolved_theme_uris( $theme_json );
if ( ! empty( $resolved_theme_uris ) ) {
$links['theme_file_uris'] = $resolved_theme_uris;
}
$response->add_links( $links );

return $response;
}
}
11 changes: 11 additions & 0 deletions lib/compat/wordpress-6.6/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,14 @@ function gutenberg_add_class_list_to_public_post_types() {
}
}
add_action( 'rest_api_init', 'gutenberg_add_class_list_to_public_post_types' );


/**
* Registers the Global Styles Revisions REST API routes.
*/
function gutenberg_register_global_styles_revisions_endpoints() {
$global_styles_revisions_controller = new Gutenberg_REST_Global_Styles_Revisions_Controller_6_6();
$global_styles_revisions_controller->register_routes();
}

add_action( 'rest_api_init', 'gutenberg_register_global_styles_revisions_endpoints' );
7 changes: 5 additions & 2 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ function gutenberg_is_experiment_enabled( $name ) {
require_once __DIR__ . '/compat/wordpress-6.5/class-gutenberg-rest-global-styles-revisions-controller-6-5.php';
require_once __DIR__ . '/compat/wordpress-6.5/rest-api.php';

// WordPress 6.6 compat.
require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-global-styles-revisions-controller-6-6.php';
require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php';
require __DIR__ . '/compat/wordpress-6.6/rest-api.php';

// Plugin specific code.
require_once __DIR__ . '/class-wp-rest-global-styles-controller-gutenberg.php';
require_once __DIR__ . '/rest-api.php';
Expand Down Expand Up @@ -130,8 +135,6 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-6.6/block-bindings/pattern-overrides.php';
require __DIR__ . '/compat/wordpress-6.6/block-template-utils.php';
require __DIR__ . '/compat/wordpress-6.6/option.php';
require __DIR__ . '/compat/wordpress-6.6/class-gutenberg-rest-templates-controller-6-6.php';
require __DIR__ . '/compat/wordpress-6.6/rest-api.php';
require __DIR__ . '/compat/wordpress-6.6/post.php';

// Experimental features.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { TOOLSPANEL_DROPDOWNMENU_PROPS } from './utils';
import { setImmutably } from '../../utils/object';
import MediaReplaceFlow from '../media-replace-flow';
import { store as blockEditorStore } from '../../store';
import { getThemeFileURI } from './set-theme-file-uris';

const IMAGE_BACKGROUND_TYPE = 'image';
const DEFAULT_CONTROLS = {
Expand Down Expand Up @@ -191,6 +192,7 @@ function BackgroundImageToolsPanelItem( {
onChange,
style,
inheritedValue,
themeFileURIs,
} ) {
const mediaUpload = useSelect(
( select ) => select( blockEditorStore ).getSettings().mediaUpload,
Expand Down Expand Up @@ -301,7 +303,7 @@ function BackgroundImageToolsPanelItem( {
<InspectorImagePreview
label={ title }
filename={ title || __( 'Untitled' ) }
url={ url }
url={ getThemeFileURI( url, themeFileURIs ) }
/>
}
variant="secondary"
Expand Down Expand Up @@ -340,6 +342,7 @@ function BackgroundSizeToolsPanelItem( {
style,
inheritedValue,
defaultValues,
themeFileURIs,
} ) {
const sizeValue =
style?.background?.backgroundSize ||
Expand Down Expand Up @@ -468,7 +471,7 @@ function BackgroundSizeToolsPanelItem( {
<FocalPointPicker
__next40pxDefaultSize
label={ __( 'Position' ) }
url={ imageValue }
url={ getThemeFileURI( imageValue, themeFileURIs ) }
value={ backgroundPositionToCoords( positionValue ) }
onChange={ updateBackgroundPosition }
/>
Expand Down Expand Up @@ -553,6 +556,7 @@ export default function BackgroundPanel( {
defaultControls = DEFAULT_CONTROLS,
defaultValues = {},
headerLabel = __( 'Background image' ),
themeFileURIs,
} ) {
const resetAllFilter = useCallback( ( previousValue ) => {
return {
Expand All @@ -577,6 +581,7 @@ export default function BackgroundPanel( {
isShownByDefault={ defaultControls.backgroundImage }
style={ value }
inheritedValue={ inheritedValue }
themeFileURIs={ themeFileURIs }
/>
{ shouldShowBackgroundSizeControls && (
<BackgroundSizeToolsPanelItem
Expand All @@ -586,6 +591,7 @@ export default function BackgroundPanel( {
style={ value }
inheritedValue={ inheritedValue }
defaultValues={ defaultValues }
themeFileURIs={ themeFileURIs }
/>
) }
</Wrapper>
Expand Down
9 changes: 6 additions & 3 deletions packages/block-editor/src/components/global-styles/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,23 +178,26 @@ export function useGlobalStyle(
)
);
};

let rawResult, result;
// @TODO _links isn't a great name. styleMeta? themeMeta?
let rawResult, result, _links;
switch ( source ) {
case 'all':
rawResult = getValueFromObjectPath( mergedConfig, finalPath );
_links = mergedConfig?._links;
result = shouldDecodeEncode
? getValueFromVariable( mergedConfig, blockName, rawResult )
: rawResult;
break;
case 'user':
rawResult = getValueFromObjectPath( userConfig, finalPath );
_links = userConfig?._links;
result = shouldDecodeEncode
? getValueFromVariable( mergedConfig, blockName, rawResult )
: rawResult;
break;
case 'base':
rawResult = getValueFromObjectPath( baseConfig, finalPath );
_links = baseConfig?._links;
result = shouldDecodeEncode
? getValueFromVariable( baseConfig, blockName, rawResult )
: rawResult;
Expand All @@ -203,7 +206,7 @@ export function useGlobalStyle(
throw 'Unsupported source';
}

return [ result, setStyle ];
return [ result, setStyle, _links ];
}

/**
Expand Down

0 comments on commit a3bda72

Please sign in to comment.