wp/wp-includes/class-wp-theme.php
changeset 19 3d72ae0968f4
parent 18 be944660c56a
child 21 48c4eec2b7e6
equal deleted inserted replaced
18:be944660c56a 19:3d72ae0968f4
    21 	/**
    21 	/**
    22 	 * Headers for style.css files.
    22 	 * Headers for style.css files.
    23 	 *
    23 	 *
    24 	 * @since 3.4.0
    24 	 * @since 3.4.0
    25 	 * @since 5.4.0 Added `Requires at least` and `Requires PHP` headers.
    25 	 * @since 5.4.0 Added `Requires at least` and `Requires PHP` headers.
    26 	 * @var array
    26 	 * @var string[]
    27 	 */
    27 	 */
    28 	private static $file_headers = array(
    28 	private static $file_headers = array(
    29 		'Name'        => 'Theme Name',
    29 		'Name'        => 'Theme Name',
    30 		'ThemeURI'    => 'Theme URI',
    30 		'ThemeURI'    => 'Theme URI',
    31 		'Description' => 'Description',
    31 		'Description' => 'Description',
    42 	);
    42 	);
    43 
    43 
    44 	/**
    44 	/**
    45 	 * Default themes.
    45 	 * Default themes.
    46 	 *
    46 	 *
    47 	 * @var array
    47 	 * @since 3.4.0
       
    48 	 * @since 3.5.0 Added the Twenty Twelve theme.
       
    49 	 * @since 3.6.0 Added the Twenty Thirteen theme.
       
    50 	 * @since 3.8.0 Added the Twenty Fourteen theme.
       
    51 	 * @since 4.1.0 Added the Twenty Fifteen theme.
       
    52 	 * @since 4.4.0 Added the Twenty Sixteen theme.
       
    53 	 * @since 4.7.0 Added the Twenty Seventeen theme.
       
    54 	 * @since 5.0.0 Added the Twenty Nineteen theme.
       
    55 	 * @since 5.3.0 Added the Twenty Twenty theme.
       
    56 	 * @since 5.6.0 Added the Twenty Twenty-One theme.
       
    57 	 * @since 5.9.0 Added the Twenty Twenty-Two theme.
       
    58 	 * @var string[]
    48 	 */
    59 	 */
    49 	private static $default_themes = array(
    60 	private static $default_themes = array(
    50 		'classic'         => 'WordPress Classic',
    61 		'classic'         => 'WordPress Classic',
    51 		'default'         => 'WordPress Default',
    62 		'default'         => 'WordPress Default',
    52 		'twentyten'       => 'Twenty Ten',
    63 		'twentyten'       => 'Twenty Ten',
    58 		'twentysixteen'   => 'Twenty Sixteen',
    69 		'twentysixteen'   => 'Twenty Sixteen',
    59 		'twentyseventeen' => 'Twenty Seventeen',
    70 		'twentyseventeen' => 'Twenty Seventeen',
    60 		'twentynineteen'  => 'Twenty Nineteen',
    71 		'twentynineteen'  => 'Twenty Nineteen',
    61 		'twentytwenty'    => 'Twenty Twenty',
    72 		'twentytwenty'    => 'Twenty Twenty',
    62 		'twentytwentyone' => 'Twenty Twenty-One',
    73 		'twentytwentyone' => 'Twenty Twenty-One',
       
    74 		'twentytwentytwo' => 'Twenty Twenty-Two',
    63 	);
    75 	);
    64 
    76 
    65 	/**
    77 	/**
    66 	 * Renamed theme tags.
    78 	 * Renamed theme tags.
    67 	 *
    79 	 *
    68 	 * @var array
    80 	 * @since 3.8.0
       
    81 	 * @var string[]
    69 	 */
    82 	 */
    70 	private static $tag_map = array(
    83 	private static $tag_map = array(
    71 		'fixed-width'    => 'fixed-layout',
    84 		'fixed-width'    => 'fixed-layout',
    72 		'flexible-width' => 'fluid-layout',
    85 		'flexible-width' => 'fluid-layout',
    73 	);
    86 	);
    74 
    87 
    75 	/**
    88 	/**
    76 	 * Absolute path to the theme root, usually wp-content/themes
    89 	 * Absolute path to the theme root, usually wp-content/themes
    77 	 *
    90 	 *
       
    91 	 * @since 3.4.0
    78 	 * @var string
    92 	 * @var string
    79 	 */
    93 	 */
    80 	private $theme_root;
    94 	private $theme_root;
    81 
    95 
    82 	/**
    96 	/**
    83 	 * Header data from the theme's style.css file.
    97 	 * Header data from the theme's style.css file.
    84 	 *
    98 	 *
       
    99 	 * @since 3.4.0
    85 	 * @var array
   100 	 * @var array
    86 	 */
   101 	 */
    87 	private $headers = array();
   102 	private $headers = array();
    88 
   103 
    89 	/**
   104 	/**
    90 	 * Header data from the theme's style.css file after being sanitized.
   105 	 * Header data from the theme's style.css file after being sanitized.
    91 	 *
   106 	 *
       
   107 	 * @since 3.4.0
    92 	 * @var array
   108 	 * @var array
    93 	 */
   109 	 */
    94 	private $headers_sanitized;
   110 	private $headers_sanitized;
    95 
   111 
    96 	/**
   112 	/**
    97 	 * Header name from the theme's style.css after being translated.
   113 	 * Header name from the theme's style.css after being translated.
    98 	 *
   114 	 *
    99 	 * Cached due to sorting functions running over the translated name.
   115 	 * Cached due to sorting functions running over the translated name.
   100 	 *
   116 	 *
       
   117 	 * @since 3.4.0
   101 	 * @var string
   118 	 * @var string
   102 	 */
   119 	 */
   103 	private $name_translated;
   120 	private $name_translated;
   104 
   121 
   105 	/**
   122 	/**
   106 	 * Errors encountered when initializing the theme.
   123 	 * Errors encountered when initializing the theme.
   107 	 *
   124 	 *
       
   125 	 * @since 3.4.0
   108 	 * @var WP_Error
   126 	 * @var WP_Error
   109 	 */
   127 	 */
   110 	private $errors;
   128 	private $errors;
   111 
   129 
   112 	/**
   130 	/**
   113 	 * The directory name of the theme's files, inside the theme root.
   131 	 * The directory name of the theme's files, inside the theme root.
   114 	 *
   132 	 *
   115 	 * In the case of a child theme, this is directory name of the child theme.
   133 	 * In the case of a child theme, this is directory name of the child theme.
   116 	 * Otherwise, 'stylesheet' is the same as 'template'.
   134 	 * Otherwise, 'stylesheet' is the same as 'template'.
   117 	 *
   135 	 *
       
   136 	 * @since 3.4.0
   118 	 * @var string
   137 	 * @var string
   119 	 */
   138 	 */
   120 	private $stylesheet;
   139 	private $stylesheet;
   121 
   140 
   122 	/**
   141 	/**
   123 	 * The directory name of the theme's files, inside the theme root.
   142 	 * The directory name of the theme's files, inside the theme root.
   124 	 *
   143 	 *
   125 	 * In the case of a child theme, this is the directory name of the parent theme.
   144 	 * In the case of a child theme, this is the directory name of the parent theme.
   126 	 * Otherwise, 'template' is the same as 'stylesheet'.
   145 	 * Otherwise, 'template' is the same as 'stylesheet'.
   127 	 *
   146 	 *
       
   147 	 * @since 3.4.0
   128 	 * @var string
   148 	 * @var string
   129 	 */
   149 	 */
   130 	private $template;
   150 	private $template;
   131 
   151 
   132 	/**
   152 	/**
   133 	 * A reference to the parent theme, in the case of a child theme.
   153 	 * A reference to the parent theme, in the case of a child theme.
   134 	 *
   154 	 *
       
   155 	 * @since 3.4.0
   135 	 * @var WP_Theme
   156 	 * @var WP_Theme
   136 	 */
   157 	 */
   137 	private $parent;
   158 	private $parent;
   138 
   159 
   139 	/**
   160 	/**
   140 	 * URL to the theme root, usually an absolute URL to wp-content/themes
   161 	 * URL to the theme root, usually an absolute URL to wp-content/themes
   141 	 *
   162 	 *
       
   163 	 * @since 3.4.0
   142 	 * @var string
   164 	 * @var string
   143 	 */
   165 	 */
   144 	private $theme_root_uri;
   166 	private $theme_root_uri;
   145 
   167 
   146 	/**
   168 	/**
   147 	 * Flag for whether the theme's textdomain is loaded.
   169 	 * Flag for whether the theme's textdomain is loaded.
   148 	 *
   170 	 *
       
   171 	 * @since 3.4.0
   149 	 * @var bool
   172 	 * @var bool
   150 	 */
   173 	 */
   151 	private $textdomain_loaded;
   174 	private $textdomain_loaded;
   152 
   175 
   153 	/**
   176 	/**
   154 	 * Stores an md5 hash of the theme root, to function as the cache key.
   177 	 * Stores an md5 hash of the theme root, to function as the cache key.
   155 	 *
   178 	 *
       
   179 	 * @since 3.4.0
   156 	 * @var string
   180 	 * @var string
   157 	 */
   181 	 */
   158 	private $cache_hash;
   182 	private $cache_hash;
   159 
   183 
   160 	/**
   184 	/**
   161 	 * Flag for whether the themes cache bucket should be persistently cached.
   185 	 * Flag for whether the themes cache bucket should be persistently cached.
   162 	 *
   186 	 *
   163 	 * Default is false. Can be set with the {@see 'wp_cache_themes_persistently'} filter.
   187 	 * Default is false. Can be set with the {@see 'wp_cache_themes_persistently'} filter.
   164 	 *
   188 	 *
       
   189 	 * @since 3.4.0
   165 	 * @var bool
   190 	 * @var bool
   166 	 */
   191 	 */
   167 	private static $persistently_cache;
   192 	private static $persistently_cache;
   168 
   193 
   169 	/**
   194 	/**
   170 	 * Expiration time for the themes cache bucket.
   195 	 * Expiration time for the themes cache bucket.
   171 	 *
   196 	 *
   172 	 * By default the bucket is not cached, so this value is useless.
   197 	 * By default the bucket is not cached, so this value is useless.
   173 	 *
   198 	 *
       
   199 	 * @since 3.4.0
   174 	 * @var bool
   200 	 * @var bool
   175 	 */
   201 	 */
   176 	private static $cache_expiration = 1800;
   202 	private static $cache_expiration = 1800;
   177 
   203 
   178 	/**
   204 	/**
   254 					'stylesheet' => $this->stylesheet,
   280 					'stylesheet' => $this->stylesheet,
   255 					'template'   => $this->template,
   281 					'template'   => $this->template,
   256 				)
   282 				)
   257 			);
   283 			);
   258 			if ( ! file_exists( $this->theme_root ) ) { // Don't cache this one.
   284 			if ( ! file_exists( $this->theme_root ) ) { // Don't cache this one.
   259 				$this->errors->add( 'theme_root_missing', __( 'Error: The themes directory is either empty or doesn’t exist. Please check your installation.' ) );
   285 				$this->errors->add( 'theme_root_missing', __( '<strong>Error</strong>: The themes directory is either empty or does not exist. Please check your installation.' ) );
   260 			}
   286 			}
   261 			return;
   287 			return;
   262 		} elseif ( ! is_readable( $this->theme_root . '/' . $theme_file ) ) {
   288 		} elseif ( ! is_readable( $this->theme_root . '/' . $theme_file ) ) {
   263 			$this->headers['Name'] = $this->stylesheet;
   289 			$this->headers['Name'] = $this->stylesheet;
   264 			$this->errors          = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) );
   290 			$this->errors          = new WP_Error( 'theme_stylesheet_not_readable', __( 'Stylesheet is not readable.' ) );
   311 			$this->template = $this->headers['Template'];
   337 			$this->template = $this->headers['Template'];
   312 		}
   338 		}
   313 
   339 
   314 		if ( ! $this->template ) {
   340 		if ( ! $this->template ) {
   315 			$this->template = $this->stylesheet;
   341 			$this->template = $this->stylesheet;
   316 			if ( ! file_exists( $this->theme_root . '/' . $this->stylesheet . '/index.php' ) ) {
   342 			$theme_path     = $this->theme_root . '/' . $this->stylesheet;
       
   343 
       
   344 			if (
       
   345 				! file_exists( $theme_path . '/templates/index.html' )
       
   346 				&& ! file_exists( $theme_path . '/block-templates/index.html' ) // Deprecated path support since 5.9.0.
       
   347 				&& ! file_exists( $theme_path . '/index.php' )
       
   348 			) {
   317 				$error_message = sprintf(
   349 				$error_message = sprintf(
   318 					/* translators: 1: index.php, 2: Documentation URL, 3: style.css */
   350 					/* translators: 1: templates/index.html, 2: index.php, 3: Documentation URL, 4: Template, 5: style.css */
   319 					__( 'Template is missing. Standalone themes need to have a %1$s template file. <a href="%2$s">Child themes</a> need to have a Template header in the %3$s stylesheet.' ),
   351 					__( '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.' ),
       
   352 					'<code>templates/index.html</code>',
   320 					'<code>index.php</code>',
   353 					'<code>index.php</code>',
   321 					__( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ),
   354 					__( 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ),
       
   355 					'<code>Template</code>',
   322 					'<code>style.css</code>'
   356 					'<code>style.css</code>'
   323 				);
   357 				);
   324 				$this->errors = new WP_Error( 'theme_no_index', $error_message );
   358 				$this->errors = new WP_Error( 'theme_no_index', $error_message );
   325 				$this->cache_add(
   359 				$this->cache_add(
   326 					'theme',
   360 					'theme',
   530 	 * @since 3.4.0
   564 	 * @since 3.4.0
   531 	 *
   565 	 *
   532 	 * @param mixed $offset
   566 	 * @param mixed $offset
   533 	 * @param mixed $value
   567 	 * @param mixed $value
   534 	 */
   568 	 */
       
   569 	#[ReturnTypeWillChange]
   535 	public function offsetSet( $offset, $value ) {}
   570 	public function offsetSet( $offset, $value ) {}
   536 
   571 
   537 	/**
   572 	/**
   538 	 * Method to implement ArrayAccess for keys formerly returned by get_themes()
   573 	 * Method to implement ArrayAccess for keys formerly returned by get_themes()
   539 	 *
   574 	 *
   540 	 * @since 3.4.0
   575 	 * @since 3.4.0
   541 	 *
   576 	 *
   542 	 * @param mixed $offset
   577 	 * @param mixed $offset
   543 	 */
   578 	 */
       
   579 	#[ReturnTypeWillChange]
   544 	public function offsetUnset( $offset ) {}
   580 	public function offsetUnset( $offset ) {}
   545 
   581 
   546 	/**
   582 	/**
   547 	 * Method to implement ArrayAccess for keys formerly returned by get_themes()
   583 	 * Method to implement ArrayAccess for keys formerly returned by get_themes()
   548 	 *
   584 	 *
   549 	 * @since 3.4.0
   585 	 * @since 3.4.0
   550 	 *
   586 	 *
   551 	 * @param mixed $offset
   587 	 * @param mixed $offset
   552 	 * @return bool
   588 	 * @return bool
   553 	 */
   589 	 */
       
   590 	#[ReturnTypeWillChange]
   554 	public function offsetExists( $offset ) {
   591 	public function offsetExists( $offset ) {
   555 		static $keys = array(
   592 		static $keys = array(
   556 			'Name',
   593 			'Name',
   557 			'Version',
   594 			'Version',
   558 			'Status',
   595 			'Status',
   590 	 * @since 3.4.0
   627 	 * @since 3.4.0
   591 	 *
   628 	 *
   592 	 * @param mixed $offset
   629 	 * @param mixed $offset
   593 	 * @return mixed
   630 	 * @return mixed
   594 	 */
   631 	 */
       
   632 	#[ReturnTypeWillChange]
   595 	public function offsetGet( $offset ) {
   633 	public function offsetGet( $offset ) {
   596 		switch ( $offset ) {
   634 		switch ( $offset ) {
   597 			case 'Name':
   635 			case 'Name':
   598 			case 'Title':
   636 			case 'Title':
   599 				/*
   637 				/*
   649 	public function errors() {
   687 	public function errors() {
   650 		return is_wp_error( $this->errors ) ? $this->errors : false;
   688 		return is_wp_error( $this->errors ) ? $this->errors : false;
   651 	}
   689 	}
   652 
   690 
   653 	/**
   691 	/**
   654 	 * Whether the theme exists.
   692 	 * Determines whether the theme exists.
   655 	 *
   693 	 *
   656 	 * A theme with errors exists. A theme with the error of 'theme_not_found',
   694 	 * A theme with errors exists. A theme with the error of 'theme_not_found',
   657 	 * meaning that the theme's directory was not found, does not exist.
   695 	 * meaning that the theme's directory was not found, does not exist.
   658 	 *
   696 	 *
   659 	 * @since 3.4.0
   697 	 * @since 3.4.0
   667 	/**
   705 	/**
   668 	 * Returns reference to the parent theme.
   706 	 * Returns reference to the parent theme.
   669 	 *
   707 	 *
   670 	 * @since 3.4.0
   708 	 * @since 3.4.0
   671 	 *
   709 	 *
   672 	 * @return WP_Theme|false Parent theme, or false if the current theme is not a child theme.
   710 	 * @return WP_Theme|false Parent theme, or false if the active theme is not a child theme.
   673 	 */
   711 	 */
   674 	public function parent() {
   712 	public function parent() {
   675 		return isset( $this->parent ) ? $this->parent : false;
   713 		return isset( $this->parent ) ? $this->parent : false;
   676 	}
   714 	}
   677 
   715 
   723 		$this->headers           = array();
   761 		$this->headers           = array();
   724 		$this->__construct( $this->stylesheet, $this->theme_root );
   762 		$this->__construct( $this->stylesheet, $this->theme_root );
   725 	}
   763 	}
   726 
   764 
   727 	/**
   765 	/**
   728 	 * Get a raw, unformatted theme header.
   766 	 * Gets a raw, unformatted theme header.
   729 	 *
   767 	 *
   730 	 * The header is sanitized, but is not translated, and is not marked up for display.
   768 	 * The header is sanitized, but is not translated, and is not marked up for display.
   731 	 * To get a theme header for display, use the display() method.
   769 	 * To get a theme header for display, use the display() method.
   732 	 *
   770 	 *
   733 	 * Use the get_template() method, not the 'Template' header, for finding the template.
   771 	 * Use the get_template() method, not the 'Template' header, for finding the template.
   800 
   838 
   801 		return $value;
   839 		return $value;
   802 	}
   840 	}
   803 
   841 
   804 	/**
   842 	/**
   805 	 * Sanitize a theme header.
   843 	 * Sanitizes a theme header.
   806 	 *
   844 	 *
   807 	 * @since 3.4.0
   845 	 * @since 3.4.0
   808 	 * @since 5.4.0 Added support for `Requires at least` and `Requires PHP` headers.
   846 	 * @since 5.4.0 Added support for `Requires at least` and `Requires PHP` headers.
   809 	 *
   847 	 *
   810 	 * @param string $header Theme header. Accepts 'Name', 'Description', 'Author', 'Version',
   848 	 * @param string $header Theme header. Accepts 'Name', 'Description', 'Author', 'Version',
   864 
   902 
   865 		return $value;
   903 		return $value;
   866 	}
   904 	}
   867 
   905 
   868 	/**
   906 	/**
   869 	 * Mark up a theme header.
   907 	 * Marks up a theme header.
   870 	 *
   908 	 *
   871 	 * @since 3.4.0
   909 	 * @since 3.4.0
   872 	 *
   910 	 *
   873 	 * @param string       $header    Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags.
   911 	 * @param string       $header    Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags.
   874 	 * @param string|array $value     Value to mark up. An array for Tags header, string otherwise.
   912 	 * @param string|array $value     Value to mark up. An array for Tags header, string otherwise.
   893 				}
   931 				}
   894 				break;
   932 				break;
   895 			case 'Tags':
   933 			case 'Tags':
   896 				static $comma = null;
   934 				static $comma = null;
   897 				if ( ! isset( $comma ) ) {
   935 				if ( ! isset( $comma ) ) {
   898 					/* translators: Used between list items, there is a space after the comma. */
   936 					$comma = wp_get_list_item_separator();
   899 					$comma = __( ', ' );
       
   900 				}
   937 				}
   901 				$value = implode( $comma, $value );
   938 				$value = implode( $comma, $value );
   902 				break;
   939 				break;
   903 			case 'ThemeURI':
   940 			case 'ThemeURI':
   904 			case 'AuthorURI':
   941 			case 'AuthorURI':
   908 
   945 
   909 		return $value;
   946 		return $value;
   910 	}
   947 	}
   911 
   948 
   912 	/**
   949 	/**
   913 	 * Translate a theme header.
   950 	 * Translates a theme header.
   914 	 *
   951 	 *
   915 	 * @since 3.4.0
   952 	 * @since 3.4.0
   916 	 *
   953 	 *
   917 	 * @param string       $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags.
   954 	 * @param string       $header Theme header. Name, Description, Author, Version, ThemeURI, AuthorURI, Status, Tags.
   918 	 * @param string|array $value  Value to translate. An array for Tags header, string otherwise.
   955 	 * @param string|array $value  Value to translate. An array for Tags header, string otherwise.
   950 						'red'               => __( 'Red' ),
   987 						'red'               => __( 'Red' ),
   951 						'silver'            => __( 'Silver' ),
   988 						'silver'            => __( 'Silver' ),
   952 						'tan'               => __( 'Tan' ),
   989 						'tan'               => __( 'Tan' ),
   953 						'white'             => __( 'White' ),
   990 						'white'             => __( 'White' ),
   954 						'yellow'            => __( 'Yellow' ),
   991 						'yellow'            => __( 'Yellow' ),
   955 						'dark'              => __( 'Dark' ),
   992 						'dark'              => _x( 'Dark', 'color scheme' ),
   956 						'light'             => __( 'Light' ),
   993 						'light'             => _x( 'Light', 'color scheme' ),
   957 						'fixed-layout'      => __( 'Fixed Layout' ),
   994 						'fixed-layout'      => __( 'Fixed Layout' ),
   958 						'fluid-layout'      => __( 'Fluid Layout' ),
   995 						'fluid-layout'      => __( 'Fluid Layout' ),
   959 						'responsive-layout' => __( 'Responsive Layout' ),
   996 						'responsive-layout' => __( 'Responsive Layout' ),
   960 						'blavatar'          => __( 'Blavatar' ),
   997 						'blavatar'          => __( 'Blavatar' ),
   961 						'photoblogging'     => __( 'Photoblogging' ),
   998 						'photoblogging'     => __( 'Photoblogging' ),
   985 		}
  1022 		}
   986 		return $value;
  1023 		return $value;
   987 	}
  1024 	}
   988 
  1025 
   989 	/**
  1026 	/**
   990 	 * The directory name of the theme's "stylesheet" files, inside the theme root.
  1027 	 * Returns the directory name of the theme's "stylesheet" files, inside the theme root.
   991 	 *
  1028 	 *
   992 	 * In the case of a child theme, this is directory name of the child theme.
  1029 	 * In the case of a child theme, this is directory name of the child theme.
   993 	 * Otherwise, get_stylesheet() is the same as get_template().
  1030 	 * Otherwise, get_stylesheet() is the same as get_template().
   994 	 *
  1031 	 *
   995 	 * @since 3.4.0
  1032 	 * @since 3.4.0
   999 	public function get_stylesheet() {
  1036 	public function get_stylesheet() {
  1000 		return $this->stylesheet;
  1037 		return $this->stylesheet;
  1001 	}
  1038 	}
  1002 
  1039 
  1003 	/**
  1040 	/**
  1004 	 * The directory name of the theme's "template" files, inside the theme root.
  1041 	 * Returns the directory name of the theme's "template" files, inside the theme root.
  1005 	 *
  1042 	 *
  1006 	 * In the case of a child theme, this is the directory name of the parent theme.
  1043 	 * In the case of a child theme, this is the directory name of the parent theme.
  1007 	 * Otherwise, the get_template() is the same as get_stylesheet().
  1044 	 * Otherwise, the get_template() is the same as get_stylesheet().
  1008 	 *
  1045 	 *
  1009 	 * @since 3.4.0
  1046 	 * @since 3.4.0
  1085 
  1122 
  1086 		return $theme_root_uri . '/' . str_replace( '%2F', '/', rawurlencode( $this->template ) );
  1123 		return $theme_root_uri . '/' . str_replace( '%2F', '/', rawurlencode( $this->template ) );
  1087 	}
  1124 	}
  1088 
  1125 
  1089 	/**
  1126 	/**
  1090 	 * The absolute path to the directory of the theme root.
  1127 	 * Returns the absolute path to the directory of the theme root.
  1091 	 *
  1128 	 *
  1092 	 * This is typically the absolute path to wp-content/themes.
  1129 	 * This is typically the absolute path to wp-content/themes.
  1093 	 *
  1130 	 *
  1094 	 * @since 3.4.0
  1131 	 * @since 3.4.0
  1095 	 *
  1132 	 *
  1154 		$this->cache_add( 'screenshot', 0 );
  1191 		$this->cache_add( 'screenshot', 0 );
  1155 		return false;
  1192 		return false;
  1156 	}
  1193 	}
  1157 
  1194 
  1158 	/**
  1195 	/**
  1159 	 * Return files in the theme's directory.
  1196 	 * Returns files in the theme's directory.
  1160 	 *
  1197 	 *
  1161 	 * @since 3.4.0
  1198 	 * @since 3.4.0
  1162 	 *
  1199 	 *
  1163 	 * @param string[]|string $type          Optional. Array of extensions to find, string of a single extension,
  1200 	 * @param string[]|string $type          Optional. Array of extensions to find, string of a single extension,
  1164 	 *                                       or null for all extensions. Default null.
  1201 	 *                                       or null for all extensions. Default null.
  1173 
  1210 
  1174 		if ( $search_parent && $this->parent() ) {
  1211 		if ( $search_parent && $this->parent() ) {
  1175 			$files += (array) self::scandir( $this->get_template_directory(), $type, $depth );
  1212 			$files += (array) self::scandir( $this->get_template_directory(), $type, $depth );
  1176 		}
  1213 		}
  1177 
  1214 
  1178 		return $files;
  1215 		return array_filter( $files );
  1179 	}
  1216 	}
  1180 
  1217 
  1181 	/**
  1218 	/**
  1182 	 * Returns the theme's post templates.
  1219 	 * Returns the theme's post templates.
  1183 	 *
  1220 	 *
  1184 	 * @since 4.7.0
  1221 	 * @since 4.7.0
  1185 	 * @since 5.8.0 Include block templates.
  1222 	 * @since 5.8.0 Include block templates.
  1186 	 *
  1223 	 *
  1187 	 * @return string[] Array of page templates, keyed by filename and post type,
  1224 	 * @return array[] Array of page template arrays, keyed by post type and filename,
  1188 	 *                  with the value of the translated header name.
  1225 	 *                 with the value of the translated header name.
  1189 	 */
  1226 	 */
  1190 	public function get_post_templates() {
  1227 	public function get_post_templates() {
  1191 		// If you screw up your current theme and we invalidate your parent, most things still work. Let it slide.
  1228 		// If you screw up your active theme and we invalidate your parent, most things still work. Let it slide.
  1192 		if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) {
  1229 		if ( $this->errors() && $this->errors()->get_error_codes() !== array( 'theme_parent_invalid' ) ) {
  1193 			return array();
  1230 			return array();
  1194 		}
  1231 		}
  1195 
  1232 
  1196 		$post_templates = $this->cache_get( 'post_templates' );
  1233 		$post_templates = $this->cache_get( 'post_templates' );
  1222 
  1259 
  1223 			if ( current_theme_supports( 'block-templates' ) ) {
  1260 			if ( current_theme_supports( 'block-templates' ) ) {
  1224 				$block_templates = get_block_templates( array(), 'wp_template' );
  1261 				$block_templates = get_block_templates( array(), 'wp_template' );
  1225 				foreach ( get_post_types( array( 'public' => true ) ) as $type ) {
  1262 				foreach ( get_post_types( array( 'public' => true ) ) as $type ) {
  1226 					foreach ( $block_templates as $block_template ) {
  1263 					foreach ( $block_templates as $block_template ) {
       
  1264 						if ( ! $block_template->is_custom ) {
       
  1265 							continue;
       
  1266 						}
       
  1267 
       
  1268 						if ( isset( $block_template->post_types ) && ! in_array( $type, $block_template->post_types, true ) ) {
       
  1269 							continue;
       
  1270 						}
       
  1271 
  1227 						$post_templates[ $type ][ $block_template->slug ] = $block_template->title;
  1272 						$post_templates[ $type ][ $block_template->slug ] = $block_template->title;
  1228 					}
  1273 					}
  1229 				}
  1274 				}
  1230 			}
  1275 			}
  1231 
  1276 
  1398 		$this->textdomain_loaded = load_theme_textdomain( $textdomain, $path );
  1443 		$this->textdomain_loaded = load_theme_textdomain( $textdomain, $path );
  1399 		return $this->textdomain_loaded;
  1444 		return $this->textdomain_loaded;
  1400 	}
  1445 	}
  1401 
  1446 
  1402 	/**
  1447 	/**
  1403 	 * Whether the theme is allowed (multisite only).
  1448 	 * Determines whether the theme is allowed (multisite only).
  1404 	 *
  1449 	 *
  1405 	 * @since 3.4.0
  1450 	 * @since 3.4.0
  1406 	 *
  1451 	 *
  1407 	 * @param string $check   Optional. Whether to check only the 'network'-wide settings, the 'site'
  1452 	 * @param string $check   Optional. Whether to check only the 'network'-wide settings, the 'site'
  1408 	 *                        settings, or 'both'. Defaults to 'both'.
  1453 	 *                        settings, or 'both'. Defaults to 'both'.
  1427 				return true;
  1472 				return true;
  1428 			}
  1473 			}
  1429 		}
  1474 		}
  1430 
  1475 
  1431 		return false;
  1476 		return false;
       
  1477 	}
       
  1478 
       
  1479 	/**
       
  1480 	 * Returns whether this theme is a block-based theme or not.
       
  1481 	 *
       
  1482 	 * @since 5.9.0
       
  1483 	 *
       
  1484 	 * @return bool
       
  1485 	 */
       
  1486 	public function is_block_theme() {
       
  1487 		$paths_to_index_block_template = array(
       
  1488 			$this->get_file_path( '/block-templates/index.html' ),
       
  1489 			$this->get_file_path( '/templates/index.html' ),
       
  1490 		);
       
  1491 
       
  1492 		foreach ( $paths_to_index_block_template as $path_to_index_block_template ) {
       
  1493 			if ( is_file( $path_to_index_block_template ) && is_readable( $path_to_index_block_template ) ) {
       
  1494 				return true;
       
  1495 			}
       
  1496 		}
       
  1497 
       
  1498 		return false;
       
  1499 	}
       
  1500 
       
  1501 	/**
       
  1502 	 * Retrieves the path of a file in the theme.
       
  1503 	 *
       
  1504 	 * Searches in the stylesheet directory before the template directory so themes
       
  1505 	 * which inherit from a parent theme can just override one file.
       
  1506 	 *
       
  1507 	 * @since 5.9.0
       
  1508 	 *
       
  1509 	 * @param string $file Optional. File to search for in the stylesheet directory.
       
  1510 	 * @return string The path of the file.
       
  1511 	 */
       
  1512 	public function get_file_path( $file = '' ) {
       
  1513 		$file = ltrim( $file, '/' );
       
  1514 
       
  1515 		$stylesheet_directory = $this->get_stylesheet_directory();
       
  1516 		$template_directory   = $this->get_template_directory();
       
  1517 
       
  1518 		if ( empty( $file ) ) {
       
  1519 			$path = $stylesheet_directory;
       
  1520 		} elseif ( file_exists( $stylesheet_directory . '/' . $file ) ) {
       
  1521 			$path = $stylesheet_directory . '/' . $file;
       
  1522 		} else {
       
  1523 			$path = $template_directory . '/' . $file;
       
  1524 		}
       
  1525 
       
  1526 		/** This filter is documented in wp-includes/link-template.php */
       
  1527 		return apply_filters( 'theme_file_path', $path, $file );
  1432 	}
  1528 	}
  1433 
  1529 
  1434 	/**
  1530 	/**
  1435 	 * Determines the latest WordPress default theme that is installed.
  1531 	 * Determines the latest WordPress default theme that is installed.
  1436 	 *
  1532 	 *