diff -r be944660c56a -r 3d72ae0968f4 wp/wp-includes/class-wp-theme.php --- a/wp/wp-includes/class-wp-theme.php Wed Sep 21 18:19:35 2022 +0200 +++ b/wp/wp-includes/class-wp-theme.php Tue Sep 27 16:37:53 2022 +0200 @@ -23,7 +23,7 @@ * * @since 3.4.0 * @since 5.4.0 Added `Requires at least` and `Requires PHP` headers. - * @var array + * @var string[] */ private static $file_headers = array( 'Name' => 'Theme Name', @@ -44,7 +44,18 @@ /** * Default themes. * - * @var array + * @since 3.4.0 + * @since 3.5.0 Added the Twenty Twelve theme. + * @since 3.6.0 Added the Twenty Thirteen theme. + * @since 3.8.0 Added the Twenty Fourteen theme. + * @since 4.1.0 Added the Twenty Fifteen theme. + * @since 4.4.0 Added the Twenty Sixteen theme. + * @since 4.7.0 Added the Twenty Seventeen theme. + * @since 5.0.0 Added the Twenty Nineteen theme. + * @since 5.3.0 Added the Twenty Twenty theme. + * @since 5.6.0 Added the Twenty Twenty-One theme. + * @since 5.9.0 Added the Twenty Twenty-Two theme. + * @var string[] */ private static $default_themes = array( 'classic' => 'WordPress Classic', @@ -60,12 +71,14 @@ 'twentynineteen' => 'Twenty Nineteen', 'twentytwenty' => 'Twenty Twenty', 'twentytwentyone' => 'Twenty Twenty-One', + 'twentytwentytwo' => 'Twenty Twenty-Two', ); /** * Renamed theme tags. * - * @var array + * @since 3.8.0 + * @var string[] */ private static $tag_map = array( 'fixed-width' => 'fixed-layout', @@ -75,6 +88,7 @@ /** * Absolute path to the theme root, usually wp-content/themes * + * @since 3.4.0 * @var string */ private $theme_root; @@ -82,6 +96,7 @@ /** * Header data from the theme's style.css file. * + * @since 3.4.0 * @var array */ private $headers = array(); @@ -89,6 +104,7 @@ /** * Header data from the theme's style.css file after being sanitized. * + * @since 3.4.0 * @var array */ private $headers_sanitized; @@ -98,6 +114,7 @@ * * Cached due to sorting functions running over the translated name. * + * @since 3.4.0 * @var string */ private $name_translated; @@ -105,6 +122,7 @@ /** * Errors encountered when initializing the theme. * + * @since 3.4.0 * @var WP_Error */ private $errors; @@ -115,6 +133,7 @@ * In the case of a child theme, this is directory name of the child theme. * Otherwise, 'stylesheet' is the same as 'template'. * + * @since 3.4.0 * @var string */ private $stylesheet; @@ -125,6 +144,7 @@ * In the case of a child theme, this is the directory name of the parent theme. * Otherwise, 'template' is the same as 'stylesheet'. * + * @since 3.4.0 * @var string */ private $template; @@ -132,6 +152,7 @@ /** * A reference to the parent theme, in the case of a child theme. * + * @since 3.4.0 * @var WP_Theme */ private $parent; @@ -139,6 +160,7 @@ /** * URL to the theme root, usually an absolute URL to wp-content/themes * + * @since 3.4.0 * @var string */ private $theme_root_uri; @@ -146,6 +168,7 @@ /** * Flag for whether the theme's textdomain is loaded. * + * @since 3.4.0 * @var bool */ private $textdomain_loaded; @@ -153,6 +176,7 @@ /** * Stores an md5 hash of the theme root, to function as the cache key. * + * @since 3.4.0 * @var string */ private $cache_hash; @@ -162,6 +186,7 @@ * * Default is false. Can be set with the {@see 'wp_cache_themes_persistently'} filter. * + * @since 3.4.0 * @var bool */ private static $persistently_cache; @@ -171,6 +196,7 @@ * * By default the bucket is not cached, so this value is useless. * + * @since 3.4.0 * @var bool */ private static $cache_expiration = 1800; @@ -256,7 +282,7 @@ ) ); if ( ! file_exists( $this->theme_root ) ) { // Don't cache this one. - $this->errors->add( 'theme_root_missing', __( 'Error: The themes directory is either empty or doesn’t exist. Please check your installation.' ) ); + $this->errors->add( 'theme_root_missing', __( 'Error: The themes directory is either empty or does not exist. Please check your installation.' ) ); } return; } elseif ( ! is_readable( $this->theme_root . '/' . $theme_file ) ) { @@ -313,12 +339,20 @@ if ( ! $this->template ) { $this->template = $this->stylesheet; - if ( ! file_exists( $this->theme_root . '/' . $this->stylesheet . '/index.php' ) ) { + $theme_path = $this->theme_root . '/' . $this->stylesheet; + + 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( - /* translators: 1: index.php, 2: Documentation URL, 3: style.css */ - __( 'Template is missing. Standalone themes need to have a %1$s template file. Child themes need to have a Template header in the %3$s stylesheet.' ), + /* 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. Child themes need to have a %4$s header in the %5$s stylesheet.' ), + 'templates/index.html', 'index.php', __( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ), + 'Template', 'style.css' ); $this->errors = new WP_Error( 'theme_no_index', $error_message ); @@ -532,6 +566,7 @@ * @param mixed $offset * @param mixed $value */ + #[ReturnTypeWillChange] public function offsetSet( $offset, $value ) {} /** @@ -541,6 +576,7 @@ * * @param mixed $offset */ + #[ReturnTypeWillChange] public function offsetUnset( $offset ) {} /** @@ -551,6 +587,7 @@ * @param mixed $offset * @return bool */ + #[ReturnTypeWillChange] public function offsetExists( $offset ) { static $keys = array( 'Name', @@ -592,6 +629,7 @@ * @param mixed $offset * @return mixed */ + #[ReturnTypeWillChange] public function offsetGet( $offset ) { switch ( $offset ) { case 'Name': @@ -651,7 +689,7 @@ } /** - * Whether the theme exists. + * Determines whether the theme exists. * * A theme with errors exists. A theme with the error of 'theme_not_found', * meaning that the theme's directory was not found, does not exist. @@ -669,7 +707,7 @@ * * @since 3.4.0 * - * @return WP_Theme|false Parent theme, or false if the current theme is not a child theme. + * @return WP_Theme|false Parent theme, or false if the active theme is not a child theme. */ public function parent() { return isset( $this->parent ) ? $this->parent : false; @@ -725,7 +763,7 @@ } /** - * Get a raw, unformatted theme header. + * Gets a raw, unformatted theme header. * * The header is sanitized, but is not translated, and is not marked up for display. * To get a theme header for display, use the display() method. @@ -802,7 +840,7 @@ } /** - * Sanitize a theme header. + * Sanitizes a theme header. * * @since 3.4.0 * @since 5.4.0 Added support for `Requires at least` and `Requires PHP` headers. @@ -866,7 +904,7 @@ } /** - * Mark up a theme header. + * Marks up a theme header. * * @since 3.4.0 * @@ -895,8 +933,7 @@ case 'Tags': static $comma = null; if ( ! isset( $comma ) ) { - /* translators: Used between list items, there is a space after the comma. */ - $comma = __( ', ' ); + $comma = wp_get_list_item_separator(); } $value = implode( $comma, $value ); break; @@ -910,7 +947,7 @@ } /** - * Translate a theme header. + * Translates a theme header. * * @since 3.4.0 * @@ -952,8 +989,8 @@ 'tan' => __( 'Tan' ), 'white' => __( 'White' ), 'yellow' => __( 'Yellow' ), - 'dark' => __( 'Dark' ), - 'light' => __( 'Light' ), + 'dark' => _x( 'Dark', 'color scheme' ), + 'light' => _x( 'Light', 'color scheme' ), 'fixed-layout' => __( 'Fixed Layout' ), 'fluid-layout' => __( 'Fluid Layout' ), 'responsive-layout' => __( 'Responsive Layout' ), @@ -987,7 +1024,7 @@ } /** - * The directory name of the theme's "stylesheet" files, inside the theme root. + * Returns the directory name of the theme's "stylesheet" files, inside the theme root. * * In the case of a child theme, this is directory name of the child theme. * Otherwise, get_stylesheet() is the same as get_template(). @@ -1001,7 +1038,7 @@ } /** - * The directory name of the theme's "template" files, inside the theme root. + * Returns the directory name of the theme's "template" files, inside the theme root. * * In the case of a child theme, this is the directory name of the parent theme. * Otherwise, the get_template() is the same as get_stylesheet(). @@ -1087,7 +1124,7 @@ } /** - * The absolute path to the directory of the theme root. + * Returns the absolute path to the directory of the theme root. * * This is typically the absolute path to wp-content/themes. * @@ -1156,7 +1193,7 @@ } /** - * Return files in the theme's directory. + * Returns files in the theme's directory. * * @since 3.4.0 * @@ -1175,7 +1212,7 @@ $files += (array) self::scandir( $this->get_template_directory(), $type, $depth ); } - return $files; + return array_filter( $files ); } /** @@ -1184,11 +1221,11 @@ * @since 4.7.0 * @since 5.8.0 Include block templates. * - * @return string[] Array of page templates, keyed by filename and post type, - * with the value of the translated header name. + * @return array[] Array of page template arrays, keyed by post type and filename, + * with the value of the translated header name. */ public function get_post_templates() { - // If you screw up your current theme and we invalidate your parent, most things still work. Let it slide. + // If you screw up your active theme and we invalidate your parent, most things still work. Let it slide. if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) { return array(); } @@ -1224,6 +1261,14 @@ $block_templates = get_block_templates( array(), 'wp_template' ); foreach ( get_post_types( array( 'public' => true ) ) as $type ) { foreach ( $block_templates as $block_template ) { + if ( ! $block_template->is_custom ) { + continue; + } + + if ( isset( $block_template->post_types ) && ! in_array( $type, $block_template->post_types, true ) ) { + continue; + } + $post_templates[ $type ][ $block_template->slug ] = $block_template->title; } } @@ -1400,7 +1445,7 @@ } /** - * Whether the theme is allowed (multisite only). + * Determines whether the theme is allowed (multisite only). * * @since 3.4.0 * @@ -1432,6 +1477,57 @@ } /** + * Returns whether this theme is a block-based theme or not. + * + * @since 5.9.0 + * + * @return bool + */ + public function is_block_theme() { + $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; + } + + /** This filter is documented in wp-includes/link-template.php */ + return apply_filters( 'theme_file_path', $path, $file ); + } + + /** * Determines the latest WordPress default theme that is installed. * * This hits the filesystem.