diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php index 49e5c8d829..df8a3dcd6d 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php @@ -105,7 +105,7 @@ class WP_REST_Templates_Controller extends WP_REST_Controller { // Excludes invalid directory name characters: `/:<>*?"|`. '([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)', // Matches the template name. - '[\/\w-]+' + '[\/\w%-]+' ), array( 'args' => array( @@ -834,7 +834,7 @@ class WP_REST_Templates_Controller extends WP_REST_Controller { 'context' => array( 'embed', 'view', 'edit' ), 'required' => true, 'minLength' => 1, - 'pattern' => '[a-zA-Z0-9_\-]+', + 'pattern' => '[a-zA-Z0-9_\%-]+', ), 'theme' => array( 'description' => __( 'Theme identifier for the template.' ), diff --git a/tests/phpunit/data/themedir1/block-theme-non-latin/index.php b/tests/phpunit/data/themedir1/block-theme-non-latin/index.php new file mode 100644 index 0000000000..589adcefcd --- /dev/null +++ b/tests/phpunit/data/themedir1/block-theme-non-latin/index.php @@ -0,0 +1,4 @@ + +

Small Header Template Part

+ \ No newline at end of file diff --git a/tests/phpunit/data/themedir1/block-theme-non-latin/parts/small-header-测试.html b/tests/phpunit/data/themedir1/block-theme-non-latin/parts/small-header-测试.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/phpunit/data/themedir1/block-theme-non-latin/style.css b/tests/phpunit/data/themedir1/block-theme-non-latin/style.css new file mode 100644 index 0000000000..4de5f009a5 --- /dev/null +++ b/tests/phpunit/data/themedir1/block-theme-non-latin/style.css @@ -0,0 +1,7 @@ +/* +Theme Name: Block Theme Non Latin +Theme URI: https://wordpress.org/ +Description: Has different characters in theme directory name for testing purposes. +Version: 0.0.1 +Text Domain: block-theme +*/ diff --git a/tests/phpunit/data/themedir1/block-theme-non-latin/templates/page-τεστ.html b/tests/phpunit/data/themedir1/block-theme-non-latin/templates/page-τεστ.html new file mode 100644 index 0000000000..ff8979cb4f --- /dev/null +++ b/tests/phpunit/data/themedir1/block-theme-non-latin/templates/page-τεστ.html @@ -0,0 +1,3 @@ + +

(τεστ) Page Template

+ diff --git a/tests/phpunit/data/themedir1/block-theme-non-latin/templates/page-测试.html b/tests/phpunit/data/themedir1/block-theme-non-latin/templates/page-测试.html new file mode 100644 index 0000000000..1aca9fe8ab --- /dev/null +++ b/tests/phpunit/data/themedir1/block-theme-non-latin/templates/page-测试.html @@ -0,0 +1,3 @@ + +

(测试) Page Template

+ diff --git a/tests/phpunit/data/themedir1/block-theme-non-latin/theme.json b/tests/phpunit/data/themedir1/block-theme-non-latin/theme.json new file mode 100644 index 0000000000..f0c59a63ab --- /dev/null +++ b/tests/phpunit/data/themedir1/block-theme-non-latin/theme.json @@ -0,0 +1,80 @@ +{ + "version": 1, + "settings": { + "color": { + "palette": [ + { + "slug": "light", + "name": "Light", + "color": "#f5f7f9" + }, + { + "slug": "dark", + "name": "Dark", + "color": "#000" + } + ], + "gradients": [ + { + "name": "Custom gradient", + "gradient": "linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%)", + "slug": "custom-gradient" + } + ], + "custom": false, + "customGradient": false + }, + "typography": { + "fontSizes": [ + { + "name": "Custom", + "slug": "custom", + "size": "100px" + } + ], + "customFontSize": false, + "customLineHeight": true + }, + "spacing": { + "units": [ + "rem" + ], + "customPadding": true + }, + "blocks": { + "core/paragraph": { + "color": { + "palette": [ + { + "slug": "light", + "name": "Light", + "color": "#f5f7f9" + } + ] + } + } + } + }, + "customTemplates": [ + { + "name": "page-τεστ", + "title": "Homepage template" + }, + { + "name": "page-测试", + "title": "Homepage template" + } + ], + "templateParts": [ + { + "name": "small-header-τεστ", + "title": "Small Header", + "area": "header" + }, + { + "name": "small-header-测试", + "title": "Small Header", + "area": "header" + }, + ] +} diff --git a/tests/phpunit/tests/rest-api/rest-schema-setup.php b/tests/phpunit/tests/rest-api/rest-schema-setup.php index 9347f33256..7b8544d5e2 100644 --- a/tests/phpunit/tests/rest-api/rest-schema-setup.php +++ b/tests/phpunit/tests/rest-api/rest-schema-setup.php @@ -146,14 +146,14 @@ class WP_Test_REST_Schema_Initialization extends WP_Test_REST_TestCase { '/wp/v2/settings', '/wp/v2/template-parts', '/wp/v2/template-parts/(?P[\d]+)/autosaves', - '/wp/v2/template-parts/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w-]+)', + '/wp/v2/template-parts/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w%-]+)', '/wp/v2/template-parts/(?P[\d]+)/autosaves/(?P[\d]+)', '/wp/v2/template-parts/(?P[\d]+)/revisions', '/wp/v2/template-parts/(?P[\d]+)/revisions/(?P[\d]+)', '/wp/v2/template-parts/lookup', '/wp/v2/templates', '/wp/v2/templates/(?P[\d]+)/autosaves', - '/wp/v2/templates/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w-]+)', + '/wp/v2/templates/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w%-]+)', '/wp/v2/templates/(?P[\d]+)/autosaves/(?P[\d]+)', '/wp/v2/templates/(?P[\d]+)/revisions', '/wp/v2/templates/(?P[\d]+)/revisions/(?P[\d]+)', diff --git a/tests/phpunit/tests/rest-api/wpRestTemplatesController.php b/tests/phpunit/tests/rest-api/wpRestTemplatesController.php index fa790b66d1..718cd2f286 100644 --- a/tests/phpunit/tests/rest-api/wpRestTemplatesController.php +++ b/tests/phpunit/tests/rest-api/wpRestTemplatesController.php @@ -66,7 +66,7 @@ class Tests_REST_WpRestTemplatesController extends WP_Test_REST_Controller_Testc 'Templates route does not exist' ); $this->assertArrayHasKey( - '/wp/v2/templates/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w-]+)', + '/wp/v2/templates/(?P([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)[\/\w%-]+)', $routes, 'Single template based on the given ID route does not exist' ); @@ -294,6 +294,46 @@ class Tests_REST_WpRestTemplatesController extends WP_Test_REST_Controller_Testc 'post_excerpt' => 'Description of page home template.', ), ), + 'template parts: parent theme with non latin characters' => array( + 'theme_dir' => 'themedir1/block-theme-non-latin', + 'template' => 'small-header-%cf%84%ce%b5%cf%83%cf%84', + 'args' => array( + 'post_name' => 'small-header-τεστ', + 'post_title' => 'Small Header τεστ Template', + 'post_content' => file_get_contents( $theme_root_dir . '/block-theme-non-latin/parts/small-header-τεστ.html' ), + 'post_excerpt' => 'Description of small header τεστ template.', + ), + ), + 'template: parent theme with non latin name' => array( + 'theme_dir' => 'themedir1/block-theme-non-latin', + 'template' => 'page-%cf%84%ce%b5%cf%83%cf%84', + 'args' => array( + 'post_name' => 'page-τεστ', + 'post_title' => 'τεστ Page Template', + 'post_content' => file_get_contents( $theme_root_dir . 'block-theme-non-latin/templates/page-τεστ.html' ), + 'post_excerpt' => 'Description of page τεστ template.', + ), + ), + 'template parts: parent theme with chinese characters' => array( + 'theme_dir' => 'themedir1/block-theme-non-latin', + 'template' => 'small-header-%e6%b5%8b%e8%af%95', + 'args' => array( + 'post_name' => 'small-header-测试', + 'post_title' => 'Small Header 测试 Template', + 'post_content' => file_get_contents( $theme_root_dir . '/block-theme-non-latin/parts/small-header-测试.html' ), + 'post_excerpt' => 'Description of small header 测试 template.', + ), + ), + 'template: parent theme with non latin name using chinese characters' => array( + 'theme_dir' => 'themedir1/block-theme-non-latin', + 'template' => 'page-%e6%b5%8b%e8%af%95', + 'args' => array( + 'post_name' => 'page-测试', + 'post_title' => '测试 Page Template', + 'post_content' => file_get_contents( $theme_root_dir . 'block-theme-non-latin/templates/page-测试.html' ), + 'post_excerpt' => 'Description of page 测试 template.', + ), + ), 'template: parent theme deprecated path' => array( 'theme_dir' => 'themedir1/block-theme-deprecated-path', 'template' => 'page-home', diff --git a/tests/phpunit/tests/theme/themeDir.php b/tests/phpunit/tests/theme/themeDir.php index e093da6dda..ea721e5a44 100644 --- a/tests/phpunit/tests/theme/themeDir.php +++ b/tests/phpunit/tests/theme/themeDir.php @@ -181,6 +181,7 @@ class Tests_Theme_ThemeDir extends WP_UnitTestCase { 'Block Theme Child with no theme.json', 'Block Theme Child Theme With Fluid Typography', 'Block Theme Child Theme With Fluid Typography Config', + 'Block Theme Non Latin', 'Block Theme [0.4.0]', 'Block Theme [1.0.0] in subdirectory', 'Block Theme Deprecated Path', diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 6ee471a87b..d64b68fa40 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -5105,7 +5105,7 @@ mockedApiResponse.Schema = { "description": "Unique slug identifying the template.", "type": "string", "minLength": 1, - "pattern": "[a-zA-Z0-9_\\-]+", + "pattern": "[a-zA-Z0-9_\\%-]+", "required": true }, "theme": { @@ -5247,7 +5247,7 @@ mockedApiResponse.Schema = { ] } }, - "/wp/v2/templates/(?P([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w-]+)": { + "/wp/v2/templates/(?P([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w%-]+)": { "namespace": "wp/v2", "methods": [ "GET", @@ -5296,7 +5296,7 @@ mockedApiResponse.Schema = { "description": "Unique slug identifying the template.", "type": "string", "minLength": 1, - "pattern": "[a-zA-Z0-9_\\-]+", + "pattern": "[a-zA-Z0-9_\\%-]+", "required": false }, "theme": { @@ -5610,7 +5610,7 @@ mockedApiResponse.Schema = { "description": "Unique slug identifying the template.", "type": "string", "minLength": 1, - "pattern": "[a-zA-Z0-9_\\-]+", + "pattern": "[a-zA-Z0-9_\\%-]+", "required": false }, "theme": { @@ -5789,7 +5789,7 @@ mockedApiResponse.Schema = { "description": "Unique slug identifying the template.", "type": "string", "minLength": 1, - "pattern": "[a-zA-Z0-9_\\-]+", + "pattern": "[a-zA-Z0-9_\\%-]+", "required": true }, "theme": { @@ -5936,7 +5936,7 @@ mockedApiResponse.Schema = { ] } }, - "/wp/v2/template-parts/(?P([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w-]+)": { + "/wp/v2/template-parts/(?P([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w%-]+)": { "namespace": "wp/v2", "methods": [ "GET", @@ -5985,7 +5985,7 @@ mockedApiResponse.Schema = { "description": "Unique slug identifying the template.", "type": "string", "minLength": 1, - "pattern": "[a-zA-Z0-9_\\-]+", + "pattern": "[a-zA-Z0-9_\\%-]+", "required": false }, "theme": { @@ -6304,7 +6304,7 @@ mockedApiResponse.Schema = { "description": "Unique slug identifying the template.", "type": "string", "minLength": 1, - "pattern": "[a-zA-Z0-9_\\-]+", + "pattern": "[a-zA-Z0-9_\\%-]+", "required": false }, "theme": {