Make WordPress Core

Changeset 61301


Ignore:
Timestamp:
11/25/2025 02:52:16 AM (3 weeks ago)
Author:
ramonopoly
Message:

Global Styles Revisions: Preserve block style variations in global styles revisions

When retrieving global styles revisions through the REST API, any block style variations (e.g., styles.blocks.core/group.variations.my-variation) are being removed during WP_Theme_JSON sanitization.

WP_Theme_JSON will only allow block style variations that are registered.

This means user modifications to any theme block style variations were being stripped from global styles revisions when retrieved via the REST API.

This commit registers theme-defined block style variations in WP_REST_Global_Styles_Revisions_Controller::prepare_item_for_response so that they can be properly parsed by WP_Theme_JSON, and therefore added to the global styles revisions REST API GET response.

Props ramonopoly, aaronrobertshaw, ellatrix.

Fixes #64292.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php

    r61002 r61301  
    313313
    314314        if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) ) {
     315            /*
     316             * Register block style variations from the theme data.
     317             * This is required so the variations pass sanitization of theme.json data.
     318             */
     319            if ( ! empty( $global_styles_config['styles']['blocks'] ) ) {
     320                $variations = WP_Theme_JSON_Resolver::get_style_variations( 'block' );
     321                wp_register_block_style_variations_from_theme_json_partials( $variations );
     322            }
     323
    315324            $theme_json           = new WP_Theme_JSON( $global_styles_config, 'custom' );
    316325            $global_styles_config = $theme_json->get_raw_data();
  • trunk/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php

    r59985 r61301  
    985985
    986986    /**
     987     * Tests that block style variations in revisions are preserved.
     988     *
     989     * @ticket 64292
     990     *
     991     * @covers WP_REST_Global_Styles_Revisions_Controller::prepare_item_for_response
     992     */
     993    public function test_get_item_preserves_block_style_variations() {
     994        wp_set_current_user( self::$admin_id );
     995        switch_theme( 'block-theme-child-with-block-style-variations' );
     996
     997        // Create a global styles post for the theme.
     998        $global_styles_id = wp_insert_post(
     999            array(
     1000                'post_content' => wp_json_encode(
     1001                    array(
     1002                        'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1003                        'isGlobalStylesUserThemeJSON' => true,
     1004                    )
     1005                ),
     1006                'post_status'  => 'publish',
     1007                'post_title'   => 'Custom Styles',
     1008                'post_type'    => 'wp_global_styles',
     1009                'post_name'    => 'wp-global-styles-block-theme-child-with-block-style-variations',
     1010                'tax_input'    => array(
     1011                    'wp_theme' => 'block-theme-child-with-block-style-variations',
     1012                ),
     1013            ),
     1014            true
     1015        );
     1016
     1017        // Update with block style variations to create a revision.
     1018        $config_with_variations = array(
     1019            'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1020            'isGlobalStylesUserThemeJSON' => true,
     1021            'styles'                      => array(
     1022                'blocks' => array(
     1023                    'core/group' => array(
     1024                        'variations' => array(
     1025                            'block-style-variation-a' => array(
     1026                                'color' => array(
     1027                                    'background' => '#123456',
     1028                                    'text'       => '#abcdef',
     1029                                ),
     1030                            ),
     1031                        ),
     1032                    ),
     1033                ),
     1034            ),
     1035        );
     1036
     1037        wp_update_post(
     1038            array(
     1039                'ID'           => $global_styles_id,
     1040                'post_content' => wp_json_encode( $config_with_variations ),
     1041            ),
     1042            true
     1043        );
     1044
     1045        // Get the revision.
     1046        $revisions = wp_get_post_revisions( $global_styles_id );
     1047        $revision  = array_shift( $revisions );
     1048        $request   = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . $global_styles_id . '/revisions/' . $revision->ID );
     1049        $response  = rest_get_server()->dispatch( $request );
     1050        $data      = $response->get_data();
     1051
     1052        $this->assertSame( 200, $response->get_status(), 'Response status should be 200.' );
     1053        $this->assertArrayHasKey( 'styles', $data, 'Response should contain styles.' );
     1054        $this->assertArrayHasKey( 'blocks', $data['styles'], 'Styles should contain blocks.' );
     1055        $this->assertArrayHasKey( 'core/group', $data['styles']['blocks'], 'Blocks should contain core/group.' );
     1056        $this->assertArrayHasKey( 'variations', $data['styles']['blocks']['core/group'], 'core/group should contain variations.' );
     1057        $this->assertArrayHasKey(
     1058            'block-style-variation-a',
     1059            $data['styles']['blocks']['core/group']['variations'],
     1060            'Variations should contain block-style-variation-a.'
     1061        );
     1062
     1063        // Verify the variation styles are preserved.
     1064        $variation = $data['styles']['blocks']['core/group']['variations']['block-style-variation-a'];
     1065        $this->assertSame( '#123456', $variation['color']['background'], 'Variation background color should be preserved.' );
     1066        $this->assertSame( '#abcdef', $variation['color']['text'], 'Variation text color should be preserved.' );
     1067
     1068        // Clean up.
     1069        wp_delete_post( $global_styles_id, true );
     1070    }
     1071
     1072    /**
     1073     * Tests that multiple block style variations are preserved.
     1074     *
     1075     * @ticket 64292
     1076     *
     1077     * @covers WP_REST_Global_Styles_Revisions_Controller::prepare_item_for_response
     1078     */
     1079    public function test_multiple_block_variations_are_preserved() {
     1080        wp_set_current_user( self::$admin_id );
     1081        switch_theme( 'block-theme-child-with-block-style-variations' );
     1082
     1083        // Create a global styles post for the theme.
     1084        $global_styles_id = wp_insert_post(
     1085            array(
     1086                'post_content' => wp_json_encode(
     1087                    array(
     1088                        'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1089                        'isGlobalStylesUserThemeJSON' => true,
     1090                    )
     1091                ),
     1092                'post_status'  => 'publish',
     1093                'post_title'   => 'Custom Styles',
     1094                'post_type'    => 'wp_global_styles',
     1095                'post_name'    => 'wp-global-styles-multiple-variations',
     1096                'tax_input'    => array(
     1097                    'wp_theme' => 'block-theme-child-with-block-style-variations',
     1098                ),
     1099            ),
     1100            true
     1101        );
     1102
     1103        // Update with multiple block style variations to create a revision.
     1104        $config_with_variations = array(
     1105            'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1106            'isGlobalStylesUserThemeJSON' => true,
     1107            'styles'                      => array(
     1108                'blocks' => array(
     1109                    'core/group'   => array(
     1110                        'variations' => array(
     1111                            'block-style-variation-a' => array(
     1112                                'color' => array(
     1113                                    'background' => 'red',
     1114                                ),
     1115                            ),
     1116                        ),
     1117                    ),
     1118                    'core/columns' => array(
     1119                        'variations' => array(
     1120                            'block-style-variation-a' => array(
     1121                                'color' => array(
     1122                                    'background' => 'blue',
     1123                                ),
     1124                            ),
     1125                        ),
     1126                    ),
     1127                ),
     1128            ),
     1129        );
     1130
     1131        wp_update_post(
     1132            array(
     1133                'ID'           => $global_styles_id,
     1134                'post_content' => wp_json_encode( $config_with_variations ),
     1135            ),
     1136            true
     1137        );
     1138
     1139        // Get the revision.
     1140        $revisions = wp_get_post_revisions( $global_styles_id );
     1141        $revision  = array_shift( $revisions );
     1142        $request   = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . $global_styles_id . '/revisions/' . $revision->ID );
     1143        $response  = rest_get_server()->dispatch( $request );
     1144        $data      = $response->get_data();
     1145
     1146        $this->assertSame( 200, $response->get_status(), 'Response status should be 200.' );
     1147
     1148        // Verify both blocks have their variations preserved.
     1149        $this->assertArrayHasKey(
     1150            'block-style-variation-a',
     1151            $data['styles']['blocks']['core/group']['variations'],
     1152            'core/group should have block-style-variation-a.'
     1153        );
     1154        $this->assertArrayHasKey(
     1155            'block-style-variation-a',
     1156            $data['styles']['blocks']['core/columns']['variations'],
     1157            'core/columns should have block-style-variation-a.'
     1158        );
     1159
     1160        // Verify the styles are different for each block.
     1161        $this->assertSame(
     1162            'red',
     1163            $data['styles']['blocks']['core/group']['variations']['block-style-variation-a']['color']['background'],
     1164            'core/group variation should have red background.'
     1165        );
     1166        $this->assertSame(
     1167            'blue',
     1168            $data['styles']['blocks']['core/columns']['variations']['block-style-variation-a']['color']['background'],
     1169            'core/columns variation should have blue background.'
     1170        );
     1171
     1172        // Clean up.
     1173        wp_delete_post( $global_styles_id, true );
     1174    }
     1175
     1176    /**
     1177     * Tests that theme-defined block style variations are registered for revisions.
     1178     *
     1179     * @ticket 64292
     1180     *
     1181     * @covers WP_REST_Global_Styles_Revisions_Controller::prepare_item_for_response
     1182     */
     1183    public function test_theme_variations_are_registered_for_revisions() {
     1184        wp_set_current_user( self::$admin_id );
     1185        switch_theme( 'block-theme-child-with-block-style-variations' );
     1186
     1187        // Verify the theme has a block style variation defined.
     1188        $theme_variations = WP_Theme_JSON_Resolver::get_style_variations( 'block' );
     1189        $this->assertNotEmpty( $theme_variations, 'Theme should have block style variations defined.' );
     1190
     1191        // Create a global styles post for the theme.
     1192        $global_styles_id = wp_insert_post(
     1193            array(
     1194                'post_content' => wp_json_encode(
     1195                    array(
     1196                        'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1197                        'isGlobalStylesUserThemeJSON' => true,
     1198                    )
     1199                ),
     1200                'post_status'  => 'publish',
     1201                'post_title'   => 'Custom Styles',
     1202                'post_type'    => 'wp_global_styles',
     1203                'post_name'    => 'wp-global-styles-theme-variations',
     1204                'tax_input'    => array(
     1205                    'wp_theme' => 'block-theme-child-with-block-style-variations',
     1206                ),
     1207            ),
     1208            true
     1209        );
     1210
     1211        // Update with the theme's block style variation.
     1212        $config_with_theme_variation = array(
     1213            'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1214            'isGlobalStylesUserThemeJSON' => true,
     1215            'styles'                      => array(
     1216                'blocks' => array(
     1217                    'core/group' => array(
     1218                        'variations' => array(
     1219                            'block-style-variation-a' => array(
     1220                                'color' => array(
     1221                                    'background' => 'purple',
     1222                                ),
     1223                            ),
     1224                        ),
     1225                    ),
     1226                ),
     1227            ),
     1228        );
     1229
     1230        wp_update_post(
     1231            array(
     1232                'ID'           => $global_styles_id,
     1233                'post_content' => wp_json_encode( $config_with_theme_variation ),
     1234            ),
     1235            true
     1236        );
     1237
     1238        // Get the revision.
     1239        $revisions = wp_get_post_revisions( $global_styles_id );
     1240        $revision  = array_shift( $revisions );
     1241        $request   = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . $global_styles_id . '/revisions/' . $revision->ID );
     1242        $response  = rest_get_server()->dispatch( $request );
     1243        $data      = $response->get_data();
     1244
     1245        $this->assertSame( 200, $response->get_status(), 'Response status should be 200.' );
     1246
     1247        // Verify the theme variation is preserved in the revision.
     1248        $this->assertArrayHasKey(
     1249            'block-style-variation-a',
     1250            $data['styles']['blocks']['core/group']['variations'],
     1251            'Theme-defined variation should be preserved in revision.'
     1252        );
     1253
     1254        // Clean up.
     1255        wp_delete_post( $global_styles_id, true );
     1256    }
     1257
     1258    /**
     1259     * Tests that block style variations are preserved in the revisions collection endpoint.
     1260     *
     1261     * @ticket 64292
     1262     *
     1263     * @covers WP_REST_Global_Styles_Revisions_Controller::get_items
     1264     * @covers WP_REST_Global_Styles_Revisions_Controller::prepare_item_for_response
     1265     */
     1266    public function test_get_items_preserves_block_style_variations() {
     1267        wp_set_current_user( self::$admin_id );
     1268        switch_theme( 'block-theme-child-with-block-style-variations' );
     1269
     1270        // Create a global styles post for the theme.
     1271        $global_styles_id = wp_insert_post(
     1272            array(
     1273                'post_content' => wp_json_encode(
     1274                    array(
     1275                        'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1276                        'isGlobalStylesUserThemeJSON' => true,
     1277                    )
     1278                ),
     1279                'post_status'  => 'publish',
     1280                'post_title'   => 'Custom Styles',
     1281                'post_type'    => 'wp_global_styles',
     1282                'post_name'    => 'wp-global-styles-variations-collection',
     1283                'tax_input'    => array(
     1284                    'wp_theme' => 'block-theme-child-with-block-style-variations',
     1285                ),
     1286            ),
     1287            true
     1288        );
     1289
     1290        // Create first revision with variations.
     1291        $config_variation_1 = array(
     1292            'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1293            'isGlobalStylesUserThemeJSON' => true,
     1294            'styles'                      => array(
     1295                'blocks' => array(
     1296                    'core/group' => array(
     1297                        'variations' => array(
     1298                            'block-style-variation-a' => array(
     1299                                'color' => array(
     1300                                    'background' => 'green',
     1301                                ),
     1302                            ),
     1303                        ),
     1304                    ),
     1305                ),
     1306            ),
     1307        );
     1308
     1309        wp_update_post(
     1310            array(
     1311                'ID'           => $global_styles_id,
     1312                'post_content' => wp_json_encode( $config_variation_1 ),
     1313            ),
     1314            true
     1315        );
     1316
     1317        // Create second revision with different variation styles.
     1318        $config_variation_2 = array(
     1319            'version'                     => WP_Theme_JSON::LATEST_SCHEMA,
     1320            'isGlobalStylesUserThemeJSON' => true,
     1321            'styles'                      => array(
     1322                'blocks' => array(
     1323                    'core/group' => array(
     1324                        'variations' => array(
     1325                            'block-style-variation-a' => array(
     1326                                'color' => array(
     1327                                    'background' => 'orange',
     1328                                ),
     1329                            ),
     1330                        ),
     1331                    ),
     1332                ),
     1333            ),
     1334        );
     1335
     1336        wp_update_post(
     1337            array(
     1338                'ID'           => $global_styles_id,
     1339                'post_content' => wp_json_encode( $config_variation_2 ),
     1340            ),
     1341            true
     1342        );
     1343
     1344        // Get all revisions.
     1345        $request  = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . $global_styles_id . '/revisions' );
     1346        $response = rest_get_server()->dispatch( $request );
     1347        $data     = $response->get_data();
     1348
     1349        $this->assertSame( 200, $response->get_status(), 'Response status should be 200.' );
     1350        $this->assertCount( 2, $data, 'Should have 2 revisions.' );
     1351
     1352        // Verify first revision (most recent - orange).
     1353        $this->assertArrayHasKey(
     1354            'block-style-variation-a',
     1355            $data[0]['styles']['blocks']['core/group']['variations'],
     1356            'First revision should have block-style-variation-a.'
     1357        );
     1358        $this->assertSame(
     1359            'orange',
     1360            $data[0]['styles']['blocks']['core/group']['variations']['block-style-variation-a']['color']['background'],
     1361            'First revision should have orange background.'
     1362        );
     1363
     1364        // Verify second revision (older - green).
     1365        $this->assertArrayHasKey(
     1366            'block-style-variation-a',
     1367            $data[1]['styles']['blocks']['core/group']['variations'],
     1368            'Second revision should have block-style-variation-a.'
     1369        );
     1370        $this->assertSame(
     1371            'green',
     1372            $data[1]['styles']['blocks']['core/group']['variations']['block-style-variation-a']['color']['background'],
     1373            'Second revision should have green background.'
     1374        );
     1375
     1376        // Clean up.
     1377        wp_delete_post( $global_styles_id, true );
     1378    }
     1379
     1380    /**
    9871381     * @doesNotPerformAssertions
    9881382     */
Note: See TracChangeset for help on using the changeset viewer.