From a86323931f219a5b73fc84f4623aaf3bdf881eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Fri, 5 Feb 2021 11:51:12 +0100 Subject: [PATCH] Load page templates via theme.json abstractions (#28700) --- lib/class-wp-theme-json-resolver.php | 38 ++++++++++++++++-------- lib/class-wp-theme-json.php | 18 +++++++++-- lib/full-site-editing/page-templates.php | 15 ++++------ lib/load.php | 8 +++-- phpunit/class-wp-theme-json-test.php | 23 ++++++++++++++ 5 files changed, 75 insertions(+), 27 deletions(-) diff --git a/lib/class-wp-theme-json-resolver.php b/lib/class-wp-theme-json-resolver.php index d54ae84c8dcd08..9ca30a3c8f2965 100644 --- a/lib/class-wp-theme-json-resolver.php +++ b/lib/class-wp-theme-json-resolver.php @@ -24,7 +24,7 @@ class WP_Theme_JSON_Resolver { * * @var WP_Theme_JSON */ - private $theme = null; + private static $theme = null; /** * Container for data coming from the user. @@ -258,27 +258,39 @@ private static function get_core_origin() { } /** - * Returns the theme's origin config. + * Returns the theme's data. * - * It uses the theme support data if - * the theme hasn't declared any via theme.json. + * Data from theme.json can be augmented via the + * $theme_support_data variable. This is useful, for example, + * to backfill the gaps in theme.json that a theme has declared + * via add_theme_supports. + * + * Note that if the same data is present in theme.json + * and in $theme_support_data, the theme.json's is not overwritten. * * @param array $theme_support_data Theme support data in theme.json format. * * @return WP_Theme_JSON Entity that holds theme data. */ - private function get_theme_origin( $theme_support_data = array() ) { - $theme_json_data = self::get_from_file( locate_template( 'experimental-theme.json' ) ); - self::translate_presets( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); + public function get_theme_data( $theme_support_data = array() ) { + if ( null === self::$theme ) { + $theme_json_data = self::get_from_file( locate_template( 'experimental-theme.json' ) ); + self::translate_presets( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); + self::$theme = new WP_Theme_JSON( $theme_json_data ); + } + + if ( empty( $theme_support_data ) ) { + return self::$theme; + } /* * We want the presets and settings declared in theme.json * to override the ones declared via add_theme_support. */ - $this->theme = new WP_Theme_JSON( $theme_support_data ); - $this->theme->merge( new WP_Theme_JSON( $theme_json_data ) ); + $with_theme_supports = new WP_Theme_JSON( $theme_support_data ); + $with_theme_supports->merge( self::$theme ); - return $this->theme; + return $with_theme_supports; } /** @@ -395,7 +407,7 @@ public function get_origin( $theme_support_data = array(), $origin = 'user', $me if ( ( 'user' === $origin ) && $merged ) { $result = new WP_Theme_JSON(); $result->merge( self::get_core_origin() ); - $result->merge( $this->get_theme_origin( $theme_support_data ) ); + $result->merge( $this->get_theme_data( $theme_support_data ) ); $result->merge( self::get_user_origin() ); return $result; } @@ -403,7 +415,7 @@ public function get_origin( $theme_support_data = array(), $origin = 'user', $me if ( ( 'theme' === $origin ) && $merged ) { $result = new WP_Theme_JSON(); $result->merge( self::get_core_origin() ); - $result->merge( $this->get_theme_origin( $theme_support_data ) ); + $result->merge( $this->get_theme_data( $theme_support_data ) ); return $result; } @@ -412,7 +424,7 @@ public function get_origin( $theme_support_data = array(), $origin = 'user', $me } if ( 'theme' === $origin ) { - return $this->get_theme_origin( $theme_support_data ); + return $this->get_theme_data( $theme_support_data ); } return self::get_core_origin(); diff --git a/lib/class-wp-theme-json.php b/lib/class-wp-theme-json.php index 44b59ceff81d30..353a4180a1983d 100644 --- a/lib/class-wp-theme-json.php +++ b/lib/class-wp-theme-json.php @@ -103,7 +103,8 @@ class WP_Theme_JSON { * } */ const SCHEMA = array( - 'styles' => array( + 'pageTemplates' => null, + 'styles' => array( 'border' => array( 'radius' => null, 'color' => null, @@ -134,7 +135,7 @@ class WP_Theme_JSON { 'textTransform' => null, ), ), - 'settings' => array( + 'settings' => array( 'border' => array( 'customRadius' => null, 'customColor' => null, @@ -1050,6 +1051,19 @@ public function get_settings() { } } + /** + * Returns the page templates of the current theme. + * + * @return array + */ + public function get_page_templates() { + if ( ! isset( $this->theme_json['pageTemplates'] ) ) { + return array(); + } else { + return $this->theme_json['pageTemplates']; + } + } + /** * Returns the stylesheet that results of processing * the theme.json structure this object represents. diff --git a/lib/full-site-editing/page-templates.php b/lib/full-site-editing/page-templates.php index 89ce31dba143f0..f3a798de1d959f 100644 --- a/lib/full-site-editing/page-templates.php +++ b/lib/full-site-editing/page-templates.php @@ -17,17 +17,12 @@ function gutenberg_load_block_page_templates( $templates, $theme, $post ) { if ( ! gutenberg_is_fse_theme() ) { return $templates; } - $config_file = locate_template( 'experimental-theme.json' ); - if ( ! file_exists( $config_file ) ) { - return $templates; - } - $data = json_decode( - file_get_contents( $config_file ), - true - ); + + $resolver = new WP_Theme_JSON_Resolver(); + $data = $resolver->get_theme_data()->get_page_templates(); $page_templates = array(); - if ( isset( $data['pageTemplates'] ) ) { - foreach ( $data['pageTemplates'] as $key => $page_template ) { + if ( isset( $data ) ) { + foreach ( $data as $key => $page_template ) { if ( ( ! isset( $page_template['postTypes'] ) && 'page' === $post->post_type ) || ( isset( $page_template['postTypes'] ) && in_array( $post->post_type, $page_template['postTypes'], true ) ) ) { diff --git a/lib/load.php b/lib/load.php index 7772cac90e15e8..ad56b7651e7efe 100644 --- a/lib/load.php +++ b/lib/load.php @@ -91,6 +91,12 @@ function gutenberg_is_experiment_enabled( $name ) { if ( ! class_exists( 'WP_Block_Template ' ) ) { require __DIR__ . '/full-site-editing/class-wp-block-template.php'; } + +// These are used by some FSE features +// as well as global styles. +require __DIR__ . '/class-wp-theme-json.php'; +require __DIR__ . '/class-wp-theme-json-resolver.php'; + require __DIR__ . '/full-site-editing/full-site-editing.php'; require __DIR__ . '/full-site-editing/block-templates.php'; require __DIR__ . '/full-site-editing/default-template-types.php'; @@ -109,8 +115,6 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/navigation.php'; require __DIR__ . '/navigation-page.php'; require __DIR__ . '/experiments-page.php'; -require __DIR__ . '/class-wp-theme-json.php'; -require __DIR__ . '/class-wp-theme-json-resolver.php'; require __DIR__ . '/global-styles.php'; require __DIR__ . '/query-utils.php'; diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 34d916a546f49a..50eee839ea182a 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -736,4 +736,27 @@ function test_remove_insecure_properties_removes_unsafe_preset_settings() { ); $this->assertEqualSetsWithIndex( $expected, $result ); } + + function test_get_page_templates() { + $theme_json = new WP_Theme_JSON( + array( + 'pageTemplates' => array( + 'page-home' => array( + 'title' => 'Some title', + ), + ), + ) + ); + + $page_templates = $theme_json->get_page_templates(); + + $this->assertEqualSetsWithIndex( + $page_templates, + array( + 'page-home' => array( + 'title' => 'Some title', + ), + ) + ); + } }