Themes: Accept valid block themes.

Updates theme validation to accept block themes. This replaces the requirement for an `index.php` with a requirement for either an `index.php`, `/templates/index.html` or the deprecated `/block-templates/index.html`.

Validation is updated for theme uploads, within `WP_Theme::__construct` and `validate_current_theme()`. 

A block theme using the deprecated file structure is now included in the unit tests.

Props peterwilsoncc, sergeybiryukov, hellofromtonya, costdev, azaozz, gziolo, FlorianBrinkmann, Boniu91, aristath, poena, audrasjb.
Fixes #55754.


git-svn-id: https://develop.svn.wordpress.org/trunk@53416 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Peter Wilson 2022-05-20 00:47:45 +00:00
parent 96d6eae601
commit 72bc35114b
13 changed files with 166 additions and 19 deletions

View File

@ -566,15 +566,28 @@ class Theme_Upgrader extends WP_Upgrader {
);
}
// If it's not a child theme, it must have at least an index.php to be legit.
if ( empty( $info['Template'] ) && ! file_exists( $working_directory . 'index.php' ) ) {
/*
* Parent themes must contain an index file:
* - classic themes require /index.php
* - block themes require /templates/index.html or block-templates/index.html (deprecated 5.9.0).
*/
if (
empty( $info['Template'] ) &&
! file_exists( $working_directory . 'index.php' ) &&
! file_exists( $working_directory . 'templates/index.html' ) &&
! file_exists( $working_directory . 'block-templates/index.html' )
) {
return new WP_Error(
'incompatible_archive_theme_no_index',
$this->strings['incompatible_archive'],
sprintf(
/* translators: %s: index.php */
__( 'The theme is missing the %s file.' ),
'<code>index.php</code>'
/* translators: 1: templates/index.html, 2: index.php, 3: Documentation URL, 4: Template, 5: style.css */
__( 'Template is missing. Standalone themes need to have a %1$s or %2$s template file. <a href="%3$s">Child themes</a> need to have a %4$s header in the %5$s stylesheet.' ),
'<code>templates/index.html</code>',
'<code>index.php</code>',
__( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ),
'<code>Template</code>',
'<code>style.css</code>'
)
);
}

View File

@ -341,7 +341,9 @@ final class WP_Theme implements ArrayAccess {
$this->template = $this->stylesheet;
$theme_path = $this->theme_root . '/' . $this->stylesheet;
if ( ! file_exists( $theme_path . '/templates/index.html' )
if (
! file_exists( $theme_path . '/templates/index.html' )
&& ! file_exists( $theme_path . '/block-templates/index.html' ) // Deprecated path support since 5.9.0.
&& ! file_exists( $theme_path . '/index.php' )
) {
$error_message = sprintf(

View File

@ -861,7 +861,9 @@ function validate_current_theme() {
return true;
}
if ( ! file_exists( get_template_directory() . '/templates/index.html' )
if (
! file_exists( get_template_directory() . '/templates/index.html' )
&& ! file_exists( get_template_directory() . '/block-templates/index.html' ) // Deprecated path support since 5.9.0.
&& ! file_exists( get_template_directory() . '/index.php' )
) {
// Invalid.

View File

@ -0,0 +1,3 @@
<!-- wp:paragraph -->
<p>Index Template</p>
<!-- /wp:paragraph -->

View File

@ -0,0 +1,3 @@
<!-- wp:paragraph -->
<p>Page (Home) Template</p>
<!-- /wp:paragraph -->

View File

@ -0,0 +1,3 @@
<!-- wp:paragraph -->
<p>Page Template</p>
<!-- /wp:paragraph -->

View File

@ -0,0 +1,3 @@
<!-- wp:paragraph -->
<p>Small Header Template Part</p>
<!-- /wp:paragraph -->

View File

@ -0,0 +1,7 @@
/*
Theme Name: Block Theme Deprecated Path
Theme URI: https://wordpress.org/
Description: For testing purposes only.
Version: 1.0.0
Text Domain: block-theme-deprecated-path
*/

View File

@ -0,0 +1,23 @@
{
"version": 2,
"settings": {
"color": {
"palette": [
{
"slug": "foreground",
"color": "#3F67C6",
"name": "Foreground"
}
]
}
},
"styles": {
"blocks": {
"core/post-title": {
"typography": {
"fontWeight": "700"
}
}
}
}
}

View File

@ -0,0 +1,71 @@
{
"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-home",
"title": "Homepage template"
}
],
"templateParts": [
{
"name": "small-header",
"title": "Small Header",
"area": "header"
}
]
}

View File

@ -288,6 +288,16 @@ class Tests_REST_WpRestTemplatesController extends WP_Test_REST_Controller_Testc
'post_excerpt' => 'Description of page home template.',
),
),
'template: parent theme deprecated path' => array(
'theme_dir' => 'themedir1/block-theme-deprecated-path',
'template' => 'page-home',
'args' => array(
'post_name' => 'page-home',
'post_title' => 'Home Page Template',
'post_content' => file_get_contents( $theme_root_dir . 'block-theme-deprecated-path/block-templates/page-home.html' ),
'post_excerpt' => 'Description of page home template.',
),
),
'template: child theme' => array(
'theme_dir' => 'themedir1/block-theme-child',
'template' => 'page-1',

View File

@ -165,14 +165,12 @@ class Tests_Theme_ThemeDir extends WP_UnitTestCase {
'Block Theme Child Theme',
'Block Theme [0.4.0]',
'Block Theme [1.0.0] in subdirectory',
'Block Theme Deprecated Path',
'Webfonts theme',
'Empty `fontFace` in theme.json - no webfonts defined',
);
sort( $theme_names );
sort( $expected );
$this->assertSame( $expected, $theme_names );
$this->assertSameSets( $expected, $theme_names );
}
/**

View File

@ -309,6 +309,10 @@ class Tests_Theme_wpTheme extends WP_UnitTestCase {
'theme_dir' => 'block-theme-child',
'expected' => true,
),
'deprecated block theme' => array(
'theme_dir' => 'block-theme-deprecated-path',
'expected' => true,
),
);
}
@ -335,42 +339,47 @@ class Tests_Theme_wpTheme extends WP_UnitTestCase {
*/
public function data_get_file_path() {
return array(
'no theme: no file given' => array(
'no theme: no file given' => array(
'theme_dir' => 'nonexistent',
'file' => '',
'expected' => '/nonexistent',
),
'parent theme: no file given' => array(
'parent theme: no file given' => array(
'theme_dir' => 'block-theme',
'file' => '',
'expected' => '/block-theme',
),
'child theme: no file given' => array(
'child theme: no file given' => array(
'theme_dir' => 'block-theme-child',
'file' => '',
'expected' => '/block-theme-child',
),
'nonexistent theme: file given' => array(
'nonexistent theme: file given' => array(
'theme_dir' => 'nonexistent',
'file' => '/templates/page.html',
'expected' => '/nonexistent/templates/page.html',
),
'parent theme: file exists' => array(
'parent theme: file exists' => array(
'theme_dir' => 'block-theme',
'file' => '/templates/page-home.html',
'expected' => '/block-theme/templates/page-home.html',
),
'parent theme: file does not exist' => array(
'parent theme: deprecated file exists' => array(
'theme_dir' => 'block-theme-deprecated-path',
'file' => '/block-templates/page-home.html',
'expected' => '/block-theme-deprecated-path/block-templates/page-home.html',
),
'parent theme: file does not exist' => array(
'theme_dir' => 'block-theme',
'file' => '/templates/nonexistent.html',
'expected' => '/block-theme/templates/nonexistent.html',
),
'child theme: file exists' => array(
'child theme: file exists' => array(
'theme_dir' => 'block-theme-child',
'file' => '/templates/page-1.html',
'expected' => '/block-theme-child/templates/page-1.html',
),
'child theme: file does not exist' => array(
'child theme: file does not exist' => array(
'theme_dir' => 'block-theme-child',
'file' => '/templates/nonexistent.html',
'expected' => '/block-theme/templates/nonexistent.html',