diff --git a/src/wp-admin/includes/dashboard.php b/src/wp-admin/includes/dashboard.php index aad170c97c..833a617bc7 100644 --- a/src/wp-admin/includes/dashboard.php +++ b/src/wp-admin/includes/dashboard.php @@ -1987,21 +1987,32 @@ function wp_dashboard_empty() {} * Displays a welcome panel to introduce users to WordPress. * * @since 3.3.0 + * @since 5.9.0 Send users to the Site Editor if the current theme is block-based. */ function wp_welcome_panel() { + $customize_url = null; + $can_edit_theme_options = current_user_can( 'edit_theme_options' ); + $can_customize = current_user_can( 'customize' ); + $is_block_based_theme = wp_is_block_template_theme(); + + if ( $is_block_based_theme && $can_edit_theme_options ) { + $customize_url = esc_url( admin_url( 'site-editor.php' ) ); + } elseif ( ! $is_block_based_theme && $can_customize ) { + $customize_url = wp_customize_url(); + } ?>

- +

- + true ) ) ) > 1 ) ) : ?> - +

is_block_based(); + + if ( $is_block_based_theme && $can_edit_theme_options ) { + $customize_action = esc_url( admin_url( 'site-editor.php' ) ); + } elseif ( ! $is_block_based_theme && $can_customize && $can_edit_theme_options ) { $customize_action = esc_url( add_query_arg( array( diff --git a/src/wp-admin/theme-editor.php b/src/wp-admin/theme-editor.php index 644084318b..7db3e84a8e 100644 --- a/src/wp-admin/theme-editor.php +++ b/src/wp-admin/theme-editor.php @@ -196,7 +196,7 @@ if ( $file_description !== $file_show ) {

- +

diff --git a/src/wp-includes/class-wp-theme.php b/src/wp-includes/class-wp-theme.php index 2e4512d033..66df8a6b67 100644 --- a/src/wp-includes/class-wp-theme.php +++ b/src/wp-includes/class-wp-theme.php @@ -1460,6 +1460,64 @@ final class WP_Theme implements ArrayAccess { return false; } + /** + * Returns whether this theme is a block-based theme or not. + * + * @since 5.9.0 + * + * @return bool + */ + public function is_block_based() { + $paths_to_index_block_template = array( + $this->get_file_path( '/block-templates/index.html' ), + $this->get_file_path( '/templates/index.html' ), + ); + + foreach ( $paths_to_index_block_template as $path_to_index_block_template ) { + if ( is_file( $path_to_index_block_template ) && is_readable( $path_to_index_block_template ) ) { + return true; + } + } + + return false; + } + + /** + * Retrieves the path of a file in the theme. + * + * Searches in the stylesheet directory before the template directory so themes + * which inherit from a parent theme can just override one file. + * + * @since 5.9.0 + * + * @param string $file Optional. File to search for in the stylesheet directory. + * @return string The path of the file. + */ + public function get_file_path( $file = '' ) { + $file = ltrim( $file, '/' ); + + $stylesheet_directory = $this->get_stylesheet_directory(); + $template_directory = $this->get_template_directory(); + + if ( empty( $file ) ) { + $path = $stylesheet_directory; + } elseif ( file_exists( $stylesheet_directory . '/' . $file ) ) { + $path = $stylesheet_directory . '/' . $file; + } else { + $path = $template_directory . '/' . $file; + } + + /** + * Filters the path to a file in the theme. + * + * @since 5.9.0 + * + * @param string $path The file path. + * @param string $file The requested file to search for. + */ + return apply_filters( 'theme_file_path', $path, $file ); + } + /** * Determines the latest WordPress default theme that is installed. * diff --git a/tests/phpunit/data/themedir1/test-block-child-theme/page-home.php b/tests/phpunit/data/themedir1/test-block-child-theme/page-home.php new file mode 100644 index 0000000000..86efe80db6 --- /dev/null +++ b/tests/phpunit/data/themedir1/test-block-child-theme/page-home.php @@ -0,0 +1,3 @@ + +

Page (ID 1) Template

+ \ No newline at end of file diff --git a/tests/phpunit/data/themedir1/test-block-theme/index.php b/tests/phpunit/data/themedir1/test-block-theme/index.php new file mode 100644 index 0000000000..634710b208 --- /dev/null +++ b/tests/phpunit/data/themedir1/test-block-theme/index.php @@ -0,0 +1,2 @@ + +

Index Template

+ \ No newline at end of file diff --git a/tests/phpunit/data/themedir1/test-block-theme/templates/page-home.html b/tests/phpunit/data/themedir1/test-block-theme/templates/page-home.html new file mode 100644 index 0000000000..6be0c70fb2 --- /dev/null +++ b/tests/phpunit/data/themedir1/test-block-theme/templates/page-home.html @@ -0,0 +1,3 @@ + +

Page (Home) Template

+ \ No newline at end of file diff --git a/tests/phpunit/data/themedir1/test-block-theme/templates/page.html b/tests/phpunit/data/themedir1/test-block-theme/templates/page.html new file mode 100644 index 0000000000..61c493e1bd --- /dev/null +++ b/tests/phpunit/data/themedir1/test-block-theme/templates/page.html @@ -0,0 +1,3 @@ + +

Page Template

+ \ No newline at end of file diff --git a/tests/phpunit/tests/theme/themeDir.php b/tests/phpunit/tests/theme/themeDir.php index 9311f6643a..5255037866 100644 --- a/tests/phpunit/tests/theme/themeDir.php +++ b/tests/phpunit/tests/theme/themeDir.php @@ -163,6 +163,8 @@ class Tests_Theme_ThemeDir extends WP_UnitTestCase { 'REST Theme', 'Block Theme', 'Block Theme Child Theme', + 'Test Block Theme', + 'Test Block Child Theme', ); sort( $theme_names ); diff --git a/tests/phpunit/tests/theme/wpTheme.php b/tests/phpunit/tests/theme/wpTheme.php index a85bcc89aa..8ea7001520 100644 --- a/tests/phpunit/tests/theme/wpTheme.php +++ b/tests/phpunit/tests/theme/wpTheme.php @@ -246,4 +246,117 @@ class Tests_Theme_wpTheme extends WP_UnitTestCase { $this->assertSameSetsWithIndex( $allowed_themes, $new_allowed_themes ); } + + /** + * @dataProvider data_is_block_based + * @ticket 54460 + * + * @covers WP_Theme::is_block_based + * + * @param string $theme_dir Directory of the theme to test. + * @param bool $expected Expected result. + */ + public function test_is_block_based( $theme_dir, $expected ) { + $theme = new WP_Theme( $theme_dir, $this->theme_root ); + $actual = $theme->is_block_based(); + + if ( $expected ) { + $this->assertTrue( $actual ); + } else { + $this->assertFalse( $actual ); + } + } + + /** + * Data provider. + * + * @return array + */ + public function data_is_block_based() { + return array( + 'default - non-block theme' => array( + 'theme_dir' => 'default', + 'expected' => false, + ), + 'parent block theme' => array( + 'theme_dir' => 'test-block-theme', + 'expected' => true, + ), + 'child block theme' => array( + 'theme_dir' => 'test-block-child-theme', + 'expected' => true, + ), + ); + } + + /** + * @dataProvider data_get_file_path + * @ticket 54460 + * + * @covers WP_Theme::get_file_path + * + * @param string $theme_dir Directory of the theme to test. + * @param string $file Given file name to test. + * @param string $expected Expected file path. + */ + public function test_get_file_path( $theme_dir, $file, $expected ) { + $theme = new WP_Theme( $theme_dir, $this->theme_root ); + + $this->assertStringEndsWith( $expected, $theme->get_file_path( $file ) ); + } + + /** + * Data provider. + * + * @return array + */ + public function data_get_file_path() { + return array( + 'no theme: no file given' => array( + 'theme_dir' => 'nonexistent', + 'file' => '', + 'expected' => '/nonexistent', + ), + 'parent theme: no file given' => array( + 'theme_dir' => 'test-block-theme', + 'file' => '', + 'expected' => '/test-block-theme', + ), + 'child theme: no file given' => array( + 'theme_dir' => 'test-block-child-theme', + 'file' => '', + 'expected' => '/test-block-child-theme', + ), + 'nonexistent theme: file given' => array( + 'theme_dir' => 'nonexistent', + 'file' => '/templates/page.html', + 'expected' => '/nonexistent/templates/page.html', + ), + 'parent theme: file exists' => array( + 'theme_dir' => 'test-block-theme', + 'file' => '/templates/page-home.html', + 'expected' => '/test-block-theme/templates/page-home.html', + ), + 'parent theme: file does not exist' => array( + 'theme_dir' => 'test-block-theme', + 'file' => '/templates/nonexistent.html', + 'expected' => '/test-block-theme/templates/nonexistent.html', + ), + 'child theme: file exists' => array( + 'theme_dir' => 'test-block-child-theme', + 'file' => '/templates/page-1.html', + 'expected' => '/test-block-child-theme/templates/page-1.html', + ), + 'child theme: file does not exist' => array( + 'theme_dir' => 'test-block-child-theme', + 'file' => '/templates/nonexistent.html', + 'expected' => '/test-block-theme/templates/nonexistent.html', + ), + 'child theme: file exists in parent, not in child' => array( + 'theme_dir' => 'test-block-child-theme', + 'file' => '/templates/page.html', + 'expected' => '/test-block-theme/templates/page.html', + ), + ); + } }