wp/wp-includes/theme.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    43 	$args     = wp_parse_args( $args, $defaults );
    43 	$args     = wp_parse_args( $args, $defaults );
    44 
    44 
    45 	$theme_directories = search_theme_directories();
    45 	$theme_directories = search_theme_directories();
    46 
    46 
    47 	if ( is_array( $wp_theme_directories ) && count( $wp_theme_directories ) > 1 ) {
    47 	if ( is_array( $wp_theme_directories ) && count( $wp_theme_directories ) > 1 ) {
    48 		// Make sure the active theme wins out, in case search_theme_directories() picks the wrong
    48 		/*
    49 		// one in the case of a conflict. (Normally, last registered theme root wins.)
    49 		 * Make sure the active theme wins out, in case search_theme_directories() picks the wrong
       
    50 		 * one in the case of a conflict. (Normally, last registered theme root wins.)
       
    51 		 */
    50 		$current_theme = get_stylesheet();
    52 		$current_theme = get_stylesheet();
    51 		if ( isset( $theme_directories[ $current_theme ] ) ) {
    53 		if ( isset( $theme_directories[ $current_theme ] ) ) {
    52 			$root_of_current_theme = get_raw_theme_root( $current_theme );
    54 			$root_of_current_theme = get_raw_theme_root( $current_theme );
    53 			if ( ! in_array( $root_of_current_theme, $wp_theme_directories, true ) ) {
    55 			if ( ! in_array( $root_of_current_theme, $wp_theme_directories, true ) ) {
    54 				$root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
    56 				$root_of_current_theme = WP_CONTENT_DIR . $root_of_current_theme;
    87 		}
    89 		}
    88 	}
    90 	}
    89 
    91 
    90 	if ( null !== $args['errors'] ) {
    92 	if ( null !== $args['errors'] ) {
    91 		foreach ( $themes as $theme => $wp_theme ) {
    93 		foreach ( $themes as $theme => $wp_theme ) {
    92 			if ( $wp_theme->errors() != $args['errors'] ) {
    94 			if ( (bool) $wp_theme->errors() !== $args['errors'] ) {
    93 				unset( $themes[ $theme ] );
    95 				unset( $themes[ $theme ] );
    94 			}
    96 			}
    95 		}
    97 		}
    96 	}
    98 	}
    97 
    99 
   149 
   151 
   150 /**
   152 /**
   151  * Whether a child theme is in use.
   153  * Whether a child theme is in use.
   152  *
   154  *
   153  * @since 3.0.0
   155  * @since 3.0.0
       
   156  * @since 6.5.0 Makes use of global template variables.
       
   157  *
       
   158  * @global string $wp_stylesheet_path Path to current theme's stylesheet directory.
       
   159  * @global string $wp_template_path   Path to current theme's template directory.
   154  *
   160  *
   155  * @return bool True if a child theme is in use, false otherwise.
   161  * @return bool True if a child theme is in use, false otherwise.
   156  */
   162  */
   157 function is_child_theme() {
   163 function is_child_theme() {
   158 	return ( TEMPLATEPATH !== STYLESHEETPATH );
   164 	global $wp_stylesheet_path, $wp_template_path;
       
   165 
       
   166 	return $wp_stylesheet_path !== $wp_template_path;
   159 }
   167 }
   160 
   168 
   161 /**
   169 /**
   162  * Retrieves name of the current stylesheet.
   170  * Retrieves name of the current stylesheet.
   163  *
   171  *
   183 
   191 
   184 /**
   192 /**
   185  * Retrieves stylesheet directory path for the active theme.
   193  * Retrieves stylesheet directory path for the active theme.
   186  *
   194  *
   187  * @since 1.5.0
   195  * @since 1.5.0
       
   196  * @since 6.4.0 Memoizes filter execution so that it only runs once for the current theme.
       
   197  * @since 6.4.2 Memoization removed.
   188  *
   198  *
   189  * @return string Path to active theme's stylesheet directory.
   199  * @return string Path to active theme's stylesheet directory.
   190  */
   200  */
   191 function get_stylesheet_directory() {
   201 function get_stylesheet_directory() {
   192 	$stylesheet     = get_stylesheet();
   202 	$stylesheet     = get_stylesheet();
   317 
   327 
   318 /**
   328 /**
   319  * Retrieves template directory path for the active theme.
   329  * Retrieves template directory path for the active theme.
   320  *
   330  *
   321  * @since 1.5.0
   331  * @since 1.5.0
       
   332  * @since 6.4.0 Memoizes filter execution so that it only runs once for the current theme.
       
   333  * @since 6.4.1 Memoization removed.
   322  *
   334  *
   323  * @return string Path to active theme's template directory.
   335  * @return string Path to active theme's template directory.
   324  */
   336  */
   325 function get_template_directory() {
   337 function get_template_directory() {
   326 	$template     = get_template();
   338 	$template     = get_template();
   455 	 * Set up maybe-relative, maybe-absolute array of theme directories.
   467 	 * Set up maybe-relative, maybe-absolute array of theme directories.
   456 	 * We always want to return absolute, but we need to cache relative
   468 	 * We always want to return absolute, but we need to cache relative
   457 	 * to use in get_theme_root().
   469 	 * to use in get_theme_root().
   458 	 */
   470 	 */
   459 	foreach ( $wp_theme_directories as $theme_root ) {
   471 	foreach ( $wp_theme_directories as $theme_root ) {
   460 		if ( 0 === strpos( $theme_root, WP_CONTENT_DIR ) ) {
   472 		if ( str_starts_with( $theme_root, WP_CONTENT_DIR ) ) {
   461 			$relative_theme_roots[ str_replace( WP_CONTENT_DIR, '', $theme_root ) ] = $theme_root;
   473 			$relative_theme_roots[ str_replace( WP_CONTENT_DIR, '', $theme_root ) ] = $theme_root;
   462 		} else {
   474 		} else {
   463 			$relative_theme_roots[ $theme_root ] = $theme_root;
   475 			$relative_theme_roots[ $theme_root ] = $theme_root;
   464 		}
   476 		}
   465 	}
   477 	}
   500 	foreach ( $wp_theme_directories as $theme_root ) {
   512 	foreach ( $wp_theme_directories as $theme_root ) {
   501 
   513 
   502 		// Start with directories in the root of the active theme directory.
   514 		// Start with directories in the root of the active theme directory.
   503 		$dirs = @ scandir( $theme_root );
   515 		$dirs = @ scandir( $theme_root );
   504 		if ( ! $dirs ) {
   516 		if ( ! $dirs ) {
   505 			trigger_error( "$theme_root is not readable", E_USER_NOTICE );
   517 			wp_trigger_error( __FUNCTION__, "$theme_root is not readable" );
   506 			continue;
   518 			continue;
   507 		}
   519 		}
   508 		foreach ( $dirs as $dir ) {
   520 		foreach ( $dirs as $dir ) {
   509 			if ( ! is_dir( $theme_root . '/' . $dir ) || '.' === $dir[0] || 'CVS' === $dir ) {
   521 			if ( ! is_dir( $theme_root . '/' . $dir ) || '.' === $dir[0] || 'CVS' === $dir ) {
   510 				continue;
   522 				continue;
   511 			}
   523 			}
   512 			if ( file_exists( $theme_root . '/' . $dir . '/style.css' ) ) {
   524 			if ( file_exists( $theme_root . '/' . $dir . '/style.css' ) ) {
   513 				// wp-content/themes/a-single-theme
   525 				/*
   514 				// wp-content/themes is $theme_root, a-single-theme is $dir.
   526 				 * wp-content/themes/a-single-theme
       
   527 				 * wp-content/themes is $theme_root, a-single-theme is $dir.
       
   528 				 */
   515 				$found_themes[ $dir ] = array(
   529 				$found_themes[ $dir ] = array(
   516 					'theme_file' => $dir . '/style.css',
   530 					'theme_file' => $dir . '/style.css',
   517 					'theme_root' => $theme_root,
   531 					'theme_root' => $theme_root,
   518 				);
   532 				);
   519 			} else {
   533 			} else {
   520 				$found_theme = false;
   534 				$found_theme = false;
   521 				// wp-content/themes/a-folder-of-themes/*
   535 				/*
   522 				// wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs.
   536 				 * wp-content/themes/a-folder-of-themes/*
       
   537 				 * wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs.
       
   538 				 */
   523 				$sub_dirs = @ scandir( $theme_root . '/' . $dir );
   539 				$sub_dirs = @ scandir( $theme_root . '/' . $dir );
   524 				if ( ! $sub_dirs ) {
   540 				if ( ! $sub_dirs ) {
   525 					trigger_error( "$theme_root/$dir is not readable", E_USER_NOTICE );
   541 					wp_trigger_error( __FUNCTION__, "$theme_root/$dir is not readable" );
   526 					continue;
   542 					continue;
   527 				}
   543 				}
   528 				foreach ( $sub_dirs as $sub_dir ) {
   544 				foreach ( $sub_dirs as $sub_dir ) {
   529 					if ( ! is_dir( $theme_root . '/' . $dir . '/' . $sub_dir ) || '.' === $dir[0] || 'CVS' === $dir ) {
   545 					if ( ! is_dir( $theme_root . '/' . $dir . '/' . $sub_dir ) || '.' === $dir[0] || 'CVS' === $dir ) {
   530 						continue;
   546 						continue;
   536 						'theme_file' => $dir . '/' . $sub_dir . '/style.css',
   552 						'theme_file' => $dir . '/' . $sub_dir . '/style.css',
   537 						'theme_root' => $theme_root,
   553 						'theme_root' => $theme_root,
   538 					);
   554 					);
   539 					$found_theme                           = true;
   555 					$found_theme                           = true;
   540 				}
   556 				}
   541 				// Never mind the above, it's just a theme missing a style.css.
   557 				/*
   542 				// Return it; WP_Theme will catch the error.
   558 				 * Never mind the above, it's just a theme missing a style.css.
       
   559 				 * Return it; WP_Theme will catch the error.
       
   560 				 */
   543 				if ( ! $found_theme ) {
   561 				if ( ! $found_theme ) {
   544 					$found_themes[ $dir ] = array(
   562 					$found_themes[ $dir ] = array(
   545 						'theme_file' => $dir . '/style.css',
   563 						'theme_file' => $dir . '/style.css',
   546 						'theme_root' => $theme_root,
   564 						'theme_root' => $theme_root,
   547 					);
   565 					);
   557 
   575 
   558 	foreach ( $found_themes as $theme_dir => $theme_data ) {
   576 	foreach ( $found_themes as $theme_dir => $theme_data ) {
   559 		$theme_roots[ $theme_dir ] = $relative_theme_roots[ $theme_data['theme_root'] ]; // Convert absolute to relative.
   577 		$theme_roots[ $theme_dir ] = $relative_theme_roots[ $theme_data['theme_root'] ]; // Convert absolute to relative.
   560 	}
   578 	}
   561 
   579 
   562 	if ( get_site_transient( 'theme_roots' ) != $theme_roots ) {
   580 	if ( get_site_transient( 'theme_roots' ) !== $theme_roots ) {
   563 		set_site_transient( 'theme_roots', $theme_roots, $cache_expiration );
   581 		set_site_transient( 'theme_roots', $theme_roots, $cache_expiration );
   564 	}
   582 	}
   565 
   583 
   566 	return $found_themes;
   584 	return $found_themes;
   567 }
   585 }
   585 	$theme_root = '';
   603 	$theme_root = '';
   586 
   604 
   587 	if ( $stylesheet_or_template ) {
   605 	if ( $stylesheet_or_template ) {
   588 		$theme_root = get_raw_theme_root( $stylesheet_or_template );
   606 		$theme_root = get_raw_theme_root( $stylesheet_or_template );
   589 		if ( $theme_root ) {
   607 		if ( $theme_root ) {
   590 			// Always prepend WP_CONTENT_DIR unless the root currently registered as a theme directory.
   608 			/*
   591 			// This gives relative theme roots the benefit of the doubt when things go haywire.
   609 			 * Always prepend WP_CONTENT_DIR unless the root currently registered as a theme directory.
       
   610 			 * This gives relative theme roots the benefit of the doubt when things go haywire.
       
   611 			 */
   592 			if ( ! in_array( $theme_root, (array) $wp_theme_directories, true ) ) {
   612 			if ( ! in_array( $theme_root, (array) $wp_theme_directories, true ) ) {
   593 				$theme_root = WP_CONTENT_DIR . $theme_root;
   613 				$theme_root = WP_CONTENT_DIR . $theme_root;
   594 			}
   614 			}
   595 		}
   615 		}
   596 	}
   616 	}
   632 	}
   652 	}
   633 
   653 
   634 	if ( $stylesheet_or_template && $theme_root ) {
   654 	if ( $stylesheet_or_template && $theme_root ) {
   635 		if ( in_array( $theme_root, (array) $wp_theme_directories, true ) ) {
   655 		if ( in_array( $theme_root, (array) $wp_theme_directories, true ) ) {
   636 			// Absolute path. Make an educated guess. YMMV -- but note the filter below.
   656 			// Absolute path. Make an educated guess. YMMV -- but note the filter below.
   637 			if ( 0 === strpos( $theme_root, WP_CONTENT_DIR ) ) {
   657 			if ( str_starts_with( $theme_root, WP_CONTENT_DIR ) ) {
   638 				$theme_root_uri = content_url( str_replace( WP_CONTENT_DIR, '', $theme_root ) );
   658 				$theme_root_uri = content_url( str_replace( WP_CONTENT_DIR, '', $theme_root ) );
   639 			} elseif ( 0 === strpos( $theme_root, ABSPATH ) ) {
   659 			} elseif ( str_starts_with( $theme_root, ABSPATH ) ) {
   640 				$theme_root_uri = site_url( str_replace( ABSPATH, '', $theme_root ) );
   660 				$theme_root_uri = site_url( str_replace( ABSPATH, '', $theme_root ) );
   641 			} elseif ( 0 === strpos( $theme_root, WP_PLUGIN_DIR ) || 0 === strpos( $theme_root, WPMU_PLUGIN_DIR ) ) {
   661 			} elseif ( str_starts_with( $theme_root, WP_PLUGIN_DIR ) || str_starts_with( $theme_root, WPMU_PLUGIN_DIR ) ) {
   642 				$theme_root_uri = plugins_url( basename( $theme_root ), $theme_root );
   662 				$theme_root_uri = plugins_url( basename( $theme_root ), $theme_root );
   643 			} else {
   663 			} else {
   644 				$theme_root_uri = $theme_root;
   664 				$theme_root_uri = $theme_root;
   645 			}
   665 			}
   646 		} else {
   666 		} else {
   683 
   703 
   684 	$theme_root = false;
   704 	$theme_root = false;
   685 
   705 
   686 	// If requesting the root for the active theme, consult options to avoid calling get_theme_roots().
   706 	// If requesting the root for the active theme, consult options to avoid calling get_theme_roots().
   687 	if ( ! $skip_cache ) {
   707 	if ( ! $skip_cache ) {
   688 		if ( get_option( 'stylesheet' ) == $stylesheet_or_template ) {
   708 		if ( get_option( 'stylesheet' ) === $stylesheet_or_template ) {
   689 			$theme_root = get_option( 'stylesheet_root' );
   709 			$theme_root = get_option( 'stylesheet_root' );
   690 		} elseif ( get_option( 'template' ) == $stylesheet_or_template ) {
   710 		} elseif ( get_option( 'template' ) === $stylesheet_or_template ) {
   691 			$theme_root = get_option( 'template_root' );
   711 			$theme_root = get_option( 'template_root' );
   692 		}
   712 		}
   693 	}
   713 	}
   694 
   714 
   695 	if ( empty( $theme_root ) ) {
   715 	if ( empty( $theme_root ) ) {
   731  * @since 2.5.0
   751  * @since 2.5.0
   732  *
   752  *
   733  * @global array                $wp_theme_directories
   753  * @global array                $wp_theme_directories
   734  * @global WP_Customize_Manager $wp_customize
   754  * @global WP_Customize_Manager $wp_customize
   735  * @global array                $sidebars_widgets
   755  * @global array                $sidebars_widgets
       
   756  * @global array                $wp_registered_sidebars
   736  *
   757  *
   737  * @param string $stylesheet Stylesheet name.
   758  * @param string $stylesheet Stylesheet name.
   738  */
   759  */
   739 function switch_theme( $stylesheet ) {
   760 function switch_theme( $stylesheet ) {
   740 	global $wp_theme_directories, $wp_customize, $sidebars_widgets;
   761 	global $wp_theme_directories, $wp_customize, $sidebars_widgets, $wp_registered_sidebars;
   741 
   762 
   742 	$requirements = validate_theme_requirements( $stylesheet );
   763 	$requirements = validate_theme_requirements( $stylesheet );
   743 	if ( is_wp_error( $requirements ) ) {
   764 	if ( is_wp_error( $requirements ) ) {
   744 		wp_die( $requirements );
   765 		wp_die( $requirements );
   745 	}
   766 	}
   812 		if ( 'wp_ajax_customize_save' === current_action() ) {
   833 		if ( 'wp_ajax_customize_save' === current_action() ) {
   813 			remove_theme_mod( 'sidebars_widgets' );
   834 			remove_theme_mod( 'sidebars_widgets' );
   814 		}
   835 		}
   815 	}
   836 	}
   816 
   837 
       
   838 	// Stores classic sidebars for later use by block themes.
       
   839 	if ( $new_theme->is_block_theme() ) {
       
   840 		set_theme_mod( 'wp_classic_sidebars', $wp_registered_sidebars );
       
   841 	}
       
   842 
   817 	update_option( 'theme_switched', $old_theme->get_stylesheet() );
   843 	update_option( 'theme_switched', $old_theme->get_stylesheet() );
       
   844 
       
   845 	/*
       
   846 	 * Reset template globals when switching themes outside of a switched blog
       
   847 	 * context to ensure templates will be loaded from the new theme.
       
   848 	 */
       
   849 	if ( ! is_multisite() || ! ms_is_switched() ) {
       
   850 		wp_set_template_globals();
       
   851 	}
       
   852 
       
   853 	// Clear pattern caches.
       
   854 	if ( ! is_multisite() ) {
       
   855 		$new_theme->delete_pattern_cache();
       
   856 		$old_theme->delete_pattern_cache();
       
   857 	}
       
   858 
       
   859 	// Set autoload=no for the old theme, autoload=yes for the switched theme.
       
   860 	$theme_mods_options = array(
       
   861 		'theme_mods_' . $stylesheet                  => 'yes',
       
   862 		'theme_mods_' . $old_theme->get_stylesheet() => 'no',
       
   863 	);
       
   864 	wp_set_option_autoload_values( $theme_mods_options );
   818 
   865 
   819 	/**
   866 	/**
   820 	 * Fires after the theme is switched.
   867 	 * Fires after the theme is switched.
       
   868 	 *
       
   869 	 * See {@see 'after_switch_theme'}.
   821 	 *
   870 	 *
   822 	 * @since 1.5.0
   871 	 * @since 1.5.0
   823 	 * @since 4.5.0 Introduced the `$old_theme` parameter.
   872 	 * @since 4.5.0 Introduced the `$old_theme` parameter.
   824 	 *
   873 	 *
   825 	 * @param string   $new_name  Name of the new theme.
   874 	 * @param string   $new_name  Name of the new theme.
   891 	 * rather than going into an infinite loop. (This is why there are
   940 	 * rather than going into an infinite loop. (This is why there are
   892 	 * checks against WP_DEFAULT_THEME above, also.) We also can't do anything
   941 	 * checks against WP_DEFAULT_THEME above, also.) We also can't do anything
   893 	 * if it turns out there is no default theme installed. (That's `false`.)
   942 	 * if it turns out there is no default theme installed. (That's `false`.)
   894 	 */
   943 	 */
   895 	$default = WP_Theme::get_core_default_theme();
   944 	$default = WP_Theme::get_core_default_theme();
   896 	if ( false === $default || get_stylesheet() == $default->get_stylesheet() ) {
   945 	if ( false === $default || get_stylesheet() === $default->get_stylesheet() ) {
   897 		return true;
   946 		return true;
   898 	}
   947 	}
   899 
   948 
   900 	switch_theme( $default->get_stylesheet() );
   949 	switch_theme( $default->get_stylesheet() );
   901 	return false;
   950 	return false;
   989 }
  1038 }
   990 
  1039 
   991 /**
  1040 /**
   992  * Retrieves theme modification value for the active theme.
  1041  * Retrieves theme modification value for the active theme.
   993  *
  1042  *
   994  * If the modification name does not exist and `$default` is a string, then the
  1043  * If the modification name does not exist and `$default_value` is a string, then the
   995  * default will be passed through the {@link https://www.php.net/sprintf sprintf()}
  1044  * default will be passed through the {@link https://www.php.net/sprintf sprintf()}
   996  * PHP function with the template directory URI as the first value and the
  1045  * PHP function with the template directory URI as the first value and the
   997  * stylesheet directory URI as the second value.
  1046  * stylesheet directory URI as the second value.
   998  *
  1047  *
   999  * @since 2.1.0
  1048  * @since 2.1.0
  1000  *
  1049  *
  1001  * @param string $name    Theme modification name.
  1050  * @param string $name          Theme modification name.
  1002  * @param mixed  $default Optional. Theme modification default value. Default false.
  1051  * @param mixed  $default_value Optional. Theme modification default value. Default false.
  1003  * @return mixed Theme modification value.
  1052  * @return mixed Theme modification value.
  1004  */
  1053  */
  1005 function get_theme_mod( $name, $default = false ) {
  1054 function get_theme_mod( $name, $default_value = false ) {
  1006 	$mods = get_theme_mods();
  1055 	$mods = get_theme_mods();
  1007 
  1056 
  1008 	if ( isset( $mods[ $name ] ) ) {
  1057 	if ( isset( $mods[ $name ] ) ) {
  1009 		/**
  1058 		/**
  1010 		 * Filters the theme modification, or 'theme_mod', value.
  1059 		 * Filters the theme modification, or 'theme_mod', value.
  1018 		 * @param mixed $current_mod The value of the active theme modification.
  1067 		 * @param mixed $current_mod The value of the active theme modification.
  1019 		 */
  1068 		 */
  1020 		return apply_filters( "theme_mod_{$name}", $mods[ $name ] );
  1069 		return apply_filters( "theme_mod_{$name}", $mods[ $name ] );
  1021 	}
  1070 	}
  1022 
  1071 
  1023 	if ( is_string( $default ) ) {
  1072 	if ( is_string( $default_value ) ) {
  1024 		// Only run the replacement if an sprintf() string format pattern was found.
  1073 		// Only run the replacement if an sprintf() string format pattern was found.
  1025 		if ( preg_match( '#(?<!%)%(?:\d+\$?)?s#', $default ) ) {
  1074 		if ( preg_match( '#(?<!%)%(?:\d+\$?)?s#', $default_value ) ) {
  1026 			// Remove a single trailing percent sign.
  1075 			// Remove a single trailing percent sign.
  1027 			$default = preg_replace( '#(?<!%)%$#', '', $default );
  1076 			$default_value = preg_replace( '#(?<!%)%$#', '', $default_value );
  1028 			$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
  1077 			$default_value = sprintf( $default_value, get_template_directory_uri(), get_stylesheet_directory_uri() );
  1029 		}
  1078 		}
  1030 	}
  1079 	}
  1031 
  1080 
  1032 	/** This filter is documented in wp-includes/theme.php */
  1081 	/** This filter is documented in wp-includes/theme.php */
  1033 	return apply_filters( "theme_mod_{$name}", $default );
  1082 	return apply_filters( "theme_mod_{$name}", $default_value );
  1034 }
  1083 }
  1035 
  1084 
  1036 /**
  1085 /**
  1037  * Updates theme modification value for the active theme.
  1086  * Updates theme modification value for the active theme.
  1038  *
  1087  *
  1177 
  1226 
  1178 	if ( is_random_header_image() ) {
  1227 	if ( is_random_header_image() ) {
  1179 		$url = get_random_header_image();
  1228 		$url = get_random_header_image();
  1180 	}
  1229 	}
  1181 
  1230 
  1182 	return esc_url_raw( set_url_scheme( $url ) );
  1231 	/**
       
  1232 	 * Filters the header image URL.
       
  1233 	 *
       
  1234 	 * @since 6.1.0
       
  1235 	 *
       
  1236 	 * @param string $url Header image URL.
       
  1237 	 */
       
  1238 	$url = apply_filters( 'get_header_image', $url );
       
  1239 
       
  1240 	if ( ! is_string( $url ) ) {
       
  1241 		return false;
       
  1242 	}
       
  1243 
       
  1244 	$url = trim( $url );
       
  1245 	return sanitize_url( set_url_scheme( $url ) );
  1183 }
  1246 }
  1184 
  1247 
  1185 /**
  1248 /**
  1186  * Creates image tag markup for a custom header image.
  1249  * Creates image tag markup for a custom header image.
  1187  *
  1250  *
  1239 			if ( $srcset && $sizes ) {
  1302 			if ( $srcset && $sizes ) {
  1240 				$attr['srcset'] = $srcset;
  1303 				$attr['srcset'] = $srcset;
  1241 				$attr['sizes']  = $sizes;
  1304 				$attr['sizes']  = $sizes;
  1242 			}
  1305 			}
  1243 		}
  1306 		}
       
  1307 	}
       
  1308 
       
  1309 	$attr = array_merge(
       
  1310 		$attr,
       
  1311 		wp_get_loading_optimization_attributes( 'img', $attr, 'get_header_image_tag' )
       
  1312 	);
       
  1313 
       
  1314 	/*
       
  1315 	 * If the default value of `lazy` for the `loading` attribute is overridden
       
  1316 	 * to omit the attribute for this image, ensure it is not included.
       
  1317 	 */
       
  1318 	if ( isset( $attr['loading'] ) && ! $attr['loading'] ) {
       
  1319 		unset( $attr['loading'] );
       
  1320 	}
       
  1321 
       
  1322 	// If the `fetchpriority` attribute is overridden and set to false or an empty string.
       
  1323 	if ( isset( $attr['fetchpriority'] ) && ! $attr['fetchpriority'] ) {
       
  1324 		unset( $attr['fetchpriority'] );
       
  1325 	}
       
  1326 
       
  1327 	// If the `decoding` attribute is overridden and set to false or an empty string.
       
  1328 	if ( isset( $attr['decoding'] ) && ! $attr['decoding'] ) {
       
  1329 		unset( $attr['decoding'] );
  1244 	}
  1330 	}
  1245 
  1331 
  1246 	/**
  1332 	/**
  1247 	 * Filters the list of header image attributes.
  1333 	 * Filters the list of header image attributes.
  1248 	 *
  1334 	 *
  1315 				}
  1401 				}
  1316 			}
  1402 			}
  1317 		}
  1403 		}
  1318 
  1404 
  1319 		if ( empty( $headers ) ) {
  1405 		if ( empty( $headers ) ) {
  1320 			return new stdClass;
  1406 			return new stdClass();
  1321 		}
  1407 		}
  1322 
  1408 
  1323 		$_wp_random_header = (object) $headers[ array_rand( $headers ) ];
  1409 		$_wp_random_header = (object) $headers[ array_rand( $headers ) ];
  1324 
  1410 
  1325 		$_wp_random_header->url = sprintf(
  1411 		$_wp_random_header->url = sprintf(
  1372 	$header_image_mod = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) );
  1458 	$header_image_mod = get_theme_mod( 'header_image', get_theme_support( 'custom-header', 'default-image' ) );
  1373 
  1459 
  1374 	if ( 'any' === $type ) {
  1460 	if ( 'any' === $type ) {
  1375 		if ( 'random-default-image' === $header_image_mod
  1461 		if ( 'random-default-image' === $header_image_mod
  1376 			|| 'random-uploaded-image' === $header_image_mod
  1462 			|| 'random-uploaded-image' === $header_image_mod
  1377 			|| ( '' !== get_random_header_image() && empty( $header_image_mod ) )
  1463 			|| ( empty( $header_image_mod ) && '' !== get_random_header_image() )
  1378 		) {
  1464 		) {
  1379 			return true;
  1465 			return true;
  1380 		}
  1466 		}
  1381 	} else {
  1467 	} else {
  1382 		if ( "random-$type-image" === $header_image_mod ) {
  1468 		if ( "random-$type-image" === $header_image_mod ) {
  1383 			return true;
  1469 			return true;
  1384 		} elseif ( 'default' === $type && empty( $header_image_mod ) && '' !== get_random_header_image() ) {
  1470 		} elseif ( 'default' === $type
       
  1471 			&& empty( $header_image_mod ) && '' !== get_random_header_image()
       
  1472 		) {
  1385 			return true;
  1473 			return true;
  1386 		}
  1474 		}
  1387 	}
  1475 	}
  1388 
  1476 
  1389 	return false;
  1477 	return false;
  1426 	if ( empty( $headers ) ) {
  1514 	if ( empty( $headers ) ) {
  1427 		return array();
  1515 		return array();
  1428 	}
  1516 	}
  1429 
  1517 
  1430 	foreach ( (array) $headers as $header ) {
  1518 	foreach ( (array) $headers as $header ) {
  1431 		$url          = esc_url_raw( wp_get_attachment_url( $header->ID ) );
  1519 		$url          = sanitize_url( wp_get_attachment_url( $header->ID ) );
  1432 		$header_data  = wp_get_attachment_metadata( $header->ID );
  1520 		$header_data  = wp_get_attachment_metadata( $header->ID );
  1433 		$header_index = $header->ID;
  1521 		$header_index = $header->ID;
  1434 
  1522 
  1435 		$header_images[ $header_index ]                  = array();
  1523 		$header_images[ $header_index ]                  = array();
  1436 		$header_images[ $header_index ]['attachment_id'] = $header->ID;
  1524 		$header_images[ $header_index ]['attachment_id'] = $header->ID;
  1477 			$data['url']           = vsprintf( get_theme_support( 'custom-header', 'default-image' ), $directory_args );
  1565 			$data['url']           = vsprintf( get_theme_support( 'custom-header', 'default-image' ), $directory_args );
  1478 			$data['thumbnail_url'] = $data['url'];
  1566 			$data['thumbnail_url'] = $data['url'];
  1479 			if ( ! empty( $_wp_default_headers ) ) {
  1567 			if ( ! empty( $_wp_default_headers ) ) {
  1480 				foreach ( (array) $_wp_default_headers as $default_header ) {
  1568 				foreach ( (array) $_wp_default_headers as $default_header ) {
  1481 					$url = vsprintf( $default_header['url'], $directory_args );
  1569 					$url = vsprintf( $default_header['url'], $directory_args );
  1482 					if ( $data['url'] == $url ) {
  1570 					if ( $data['url'] === $url ) {
  1483 						$data                  = $default_header;
  1571 						$data                  = $default_header;
  1484 						$data['url']           = $url;
  1572 						$data['url']           = $url;
  1485 						$data['thumbnail_url'] = vsprintf( $data['thumbnail_url'], $directory_args );
  1573 						$data['thumbnail_url'] = vsprintf( $data['thumbnail_url'], $directory_args );
  1486 						break;
  1574 						break;
  1487 					}
  1575 					}
  1587 
  1675 
  1588 	if ( ! $id && ! $url ) {
  1676 	if ( ! $id && ! $url ) {
  1589 		return false;
  1677 		return false;
  1590 	}
  1678 	}
  1591 
  1679 
  1592 	return esc_url_raw( set_url_scheme( $url ) );
  1680 	return sanitize_url( set_url_scheme( $url ) );
  1593 }
  1681 }
  1594 
  1682 
  1595 /**
  1683 /**
  1596  * Displays header video URL.
  1684  * Displays header video URL.
  1597  *
  1685  *
  1784  */
  1872  */
  1785 function _custom_background_cb() {
  1873 function _custom_background_cb() {
  1786 	// $background is the saved custom image, or the default image.
  1874 	// $background is the saved custom image, or the default image.
  1787 	$background = set_url_scheme( get_background_image() );
  1875 	$background = set_url_scheme( get_background_image() );
  1788 
  1876 
  1789 	// $color is the saved custom color.
  1877 	/*
  1790 	// A default has to be specified in style.css. It will not be printed here.
  1878 	 * $color is the saved custom color.
       
  1879 	 * A default has to be specified in style.css. It will not be printed here.
       
  1880 	 */
  1791 	$color = get_background_color();
  1881 	$color = get_background_color();
  1792 
  1882 
  1793 	if ( get_theme_support( 'custom-background', 'default-color' ) === $color ) {
  1883 	if ( get_theme_support( 'custom-background', 'default-color' ) === $color ) {
  1794 		$color = false;
  1884 		$color = false;
  1795 	}
  1885 	}
  1804 	}
  1894 	}
  1805 
  1895 
  1806 	$style = $color ? "background-color: #$color;" : '';
  1896 	$style = $color ? "background-color: #$color;" : '';
  1807 
  1897 
  1808 	if ( $background ) {
  1898 	if ( $background ) {
  1809 		$image = ' background-image: url("' . esc_url_raw( $background ) . '");';
  1899 		$image = ' background-image: url("' . sanitize_url( $background ) . '");';
  1810 
  1900 
  1811 		// Background Position.
  1901 		// Background Position.
  1812 		$position_x = get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) );
  1902 		$position_x = get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) );
  1813 		$position_y = get_theme_mod( 'background_position_y', get_theme_support( 'custom-background', 'default-position-y' ) );
  1903 		$position_y = get_theme_mod( 'background_position_y', get_theme_support( 'custom-background', 'default-position-y' ) );
  1814 
  1904 
  2052 			if ( get_stylesheet() === $args['stylesheet'] ) {
  2142 			if ( get_stylesheet() === $args['stylesheet'] ) {
  2053 				set_theme_mod( 'custom_css_post_id', $r );
  2143 				set_theme_mod( 'custom_css_post_id', $r );
  2054 			}
  2144 			}
  2055 
  2145 
  2056 			// Trigger creation of a revision. This should be removed once #30854 is resolved.
  2146 			// Trigger creation of a revision. This should be removed once #30854 is resolved.
  2057 			if ( 0 === count( wp_get_post_revisions( $r ) ) ) {
  2147 			$revisions = wp_get_latest_revision_id_and_total_count( $r );
       
  2148 			if ( ! is_wp_error( $revisions ) && 0 === $revisions['count'] ) {
  2058 				wp_save_post_revision( $r );
  2149 				wp_save_post_revision( $r );
  2059 			}
  2150 			}
  2060 		}
  2151 		}
  2061 	}
  2152 	}
  2062 
  2153 
  2144 		$style_dir     = get_stylesheet_directory();
  2235 		$style_dir     = get_stylesheet_directory();
  2145 
  2236 
  2146 		// Support externally referenced styles (like, say, fonts).
  2237 		// Support externally referenced styles (like, say, fonts).
  2147 		foreach ( $editor_styles as $key => $file ) {
  2238 		foreach ( $editor_styles as $key => $file ) {
  2148 			if ( preg_match( '~^(https?:)?//~', $file ) ) {
  2239 			if ( preg_match( '~^(https?:)?//~', $file ) ) {
  2149 				$stylesheets[] = esc_url_raw( $file );
  2240 				$stylesheets[] = sanitize_url( $file );
  2150 				unset( $editor_styles[ $key ] );
  2241 				unset( $editor_styles[ $key ] );
  2151 			}
  2242 			}
  2152 		}
  2243 		}
  2153 
  2244 
  2154 		// Look in a parent theme first, that way child theme CSS overrides.
  2245 		// Look in a parent theme first, that way child theme CSS overrides.
  2353 			'about'            => array(
  2444 			'about'            => array(
  2354 				'post_type'    => 'page',
  2445 				'post_type'    => 'page',
  2355 				'post_title'   => _x( 'About', 'Theme starter content' ),
  2446 				'post_title'   => _x( 'About', 'Theme starter content' ),
  2356 				'post_content' => sprintf(
  2447 				'post_content' => sprintf(
  2357 					"<!-- wp:paragraph -->\n<p>%s</p>\n<!-- /wp:paragraph -->",
  2448 					"<!-- wp:paragraph -->\n<p>%s</p>\n<!-- /wp:paragraph -->",
  2358 					_x( 'You might be an artist who would like to introduce yourself and your work here or maybe you&rsquo;re a business with a mission to describe.', 'Theme starter content' )
  2449 					_x( 'You might be an artist who would like to introduce yourself and your work here or maybe you are a business with a mission to describe.', 'Theme starter content' )
  2359 				),
  2450 				),
  2360 			),
  2451 			),
  2361 			'contact'          => array(
  2452 			'contact'          => array(
  2362 				'post_type'    => 'page',
  2453 				'post_type'    => 'page',
  2363 				'post_title'   => _x( 'Contact', 'Theme starter content' ),
  2454 				'post_title'   => _x( 'Contact', 'Theme starter content' ),
  2458 						$content[ $type ][ $id ] = $item;
  2549 						$content[ $type ][ $id ] = $item;
  2459 					}
  2550 					}
  2460 				}
  2551 				}
  2461 				break;
  2552 				break;
  2462 
  2553 
  2463 			// All that's left now are posts (besides attachments).
  2554 			/*
  2464 			// Not a default case for the sake of clarity and future work.
  2555 			 * All that's left now are posts (besides attachments).
       
  2556 			 * Not a default case for the sake of clarity and future work.
       
  2557 			 */
  2465 			case 'posts':
  2558 			case 'posts':
  2466 				foreach ( $config[ $type ] as $id => $item ) {
  2559 				foreach ( $config[ $type ] as $id => $item ) {
  2467 					if ( is_array( $item ) ) {
  2560 					if ( is_array( $item ) ) {
  2468 
  2561 
  2469 						// Item extends core content.
  2562 						// Item extends core content.
  2521  *     ) );
  2614  *     ) );
  2522  *
  2615  *
  2523  * @since 2.9.0
  2616  * @since 2.9.0
  2524  * @since 3.4.0 The `custom-header-uploads` feature was deprecated.
  2617  * @since 3.4.0 The `custom-header-uploads` feature was deprecated.
  2525  * @since 3.6.0 The `html5` feature was added.
  2618  * @since 3.6.0 The `html5` feature was added.
       
  2619  * @since 3.6.1 The `html5` feature requires an array of types to be passed. Defaults to
       
  2620  *              'comment-list', 'comment-form', 'search-form' for backward compatibility.
  2526  * @since 3.9.0 The `html5` feature now also accepts 'gallery' and 'caption'.
  2621  * @since 3.9.0 The `html5` feature now also accepts 'gallery' and 'caption'.
  2527  * @since 4.1.0 The `title-tag` feature was added.
  2622  * @since 4.1.0 The `title-tag` feature was added.
  2528  * @since 4.5.0 The `customize-selective-refresh-widgets` feature was added.
  2623  * @since 4.5.0 The `customize-selective-refresh-widgets` feature was added.
  2529  * @since 4.7.0 The `starter-content` feature was added.
  2624  * @since 4.7.0 The `starter-content` feature was added.
  2530  * @since 5.0.0 The `responsive-embeds`, `align-wide`, `dark-editor-style`, `disable-custom-colors`,
  2625  * @since 5.0.0 The `responsive-embeds`, `align-wide`, `dark-editor-style`, `disable-custom-colors`,
  2531  *              `disable-custom-font-sizes`, `editor-color-palette`, `editor-font-sizes`,
  2626  *              `disable-custom-font-sizes`, `editor-color-palette`, `editor-font-sizes`,
  2532  *              `editor-styles`, and `wp-block-styles` features were added.
  2627  *              `editor-styles`, and `wp-block-styles` features were added.
  2533  * @since 5.3.0 The `html5` feature now also accepts 'script' and 'style'.
  2628  * @since 5.3.0 The `html5` feature now also accepts 'script' and 'style'.
  2534  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
  2629  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
  2535  *              by adding it to the function signature.
  2630  *              by adding it to the function signature.
       
  2631  * @since 5.4.0 The `disable-custom-gradients` feature limits to default gradients or gradients added
       
  2632  *              through `editor-gradient-presets` theme support.
  2536  * @since 5.5.0 The `core-block-patterns` feature was added and is enabled by default.
  2633  * @since 5.5.0 The `core-block-patterns` feature was added and is enabled by default.
  2537  * @since 5.5.0 The `custom-logo` feature now also accepts 'unlink-homepage-logo'.
  2634  * @since 5.5.0 The `custom-logo` feature now also accepts 'unlink-homepage-logo'.
  2538  * @since 5.6.0 The `post-formats` feature warns if no array is passed.
  2635  * @since 5.6.0 The `post-formats` feature warns if no array is passed as the second parameter.
  2539  * @since 5.8.0 The `widgets-block-editor` feature enables the Widgets block editor.
  2636  * @since 5.8.0 The `widgets-block-editor` feature enables the Widgets block editor.
       
  2637  * @since 5.8.0 The `block-templates` feature indicates whether a theme uses block-based templates.
       
  2638  * @since 6.0.0 The `html5` feature warns if no array is passed as the second parameter.
       
  2639  * @since 6.1.0 The `block-template-parts` feature allows to edit any reusable template part from site editor.
       
  2640  * @since 6.1.0 The `disable-layout-styles` feature disables the default layout styles.
       
  2641  * @since 6.3.0 The `link-color` feature allows to enable the link color setting.
       
  2642  * @since 6.3.0 The `border` feature allows themes without theme.json to add border styles to blocks.
       
  2643  * @since 6.5.0 The `appearance-tools` feature enables a few design tools for blocks,
       
  2644  *              see `WP_Theme_JSON::APPEARANCE_TOOLS_OPT_INS` for a complete list.
       
  2645  * @since 6.6.0 The `editor-spacing-sizes` feature was added.
  2540  *
  2646  *
  2541  * @global array $_wp_theme_features
  2647  * @global array $_wp_theme_features
  2542  *
  2648  *
  2543  * @param string $feature The feature being added. Likely core values include:
  2649  * @param string $feature The feature being added. Likely core values include:
  2544  *                          - 'admin-bar'
  2650  *                          - 'admin-bar'
  2545  *                          - 'align-wide'
  2651  *                          - 'align-wide'
       
  2652  *                          - 'appearance-tools'
  2546  *                          - 'automatic-feed-links'
  2653  *                          - 'automatic-feed-links'
       
  2654  *                          - 'block-templates'
       
  2655  *                          - 'block-template-parts'
       
  2656  *                          - 'border'
  2547  *                          - 'core-block-patterns'
  2657  *                          - 'core-block-patterns'
  2548  *                          - 'custom-background'
  2658  *                          - 'custom-background'
  2549  *                          - 'custom-header'
  2659  *                          - 'custom-header'
  2550  *                          - 'custom-line-height'
  2660  *                          - 'custom-line-height'
  2551  *                          - 'custom-logo'
  2661  *                          - 'custom-logo'
  2553  *                          - 'custom-spacing'
  2663  *                          - 'custom-spacing'
  2554  *                          - 'custom-units'
  2664  *                          - 'custom-units'
  2555  *                          - 'dark-editor-style'
  2665  *                          - 'dark-editor-style'
  2556  *                          - 'disable-custom-colors'
  2666  *                          - 'disable-custom-colors'
  2557  *                          - 'disable-custom-font-sizes'
  2667  *                          - 'disable-custom-font-sizes'
       
  2668  *                          - 'disable-custom-gradients'
       
  2669  *                          - 'disable-layout-styles'
  2558  *                          - 'editor-color-palette'
  2670  *                          - 'editor-color-palette'
  2559  *                          - 'editor-gradient-presets'
  2671  *                          - 'editor-gradient-presets'
  2560  *                          - 'editor-font-sizes'
  2672  *                          - 'editor-font-sizes'
       
  2673  *                          - 'editor-spacing-sizes'
  2561  *                          - 'editor-styles'
  2674  *                          - 'editor-styles'
  2562  *                          - 'featured-content'
  2675  *                          - 'featured-content'
  2563  *                          - 'html5'
  2676  *                          - 'html5'
       
  2677  *                          - 'link-color'
  2564  *                          - 'menus'
  2678  *                          - 'menus'
  2565  *                          - 'post-formats'
  2679  *                          - 'post-formats'
  2566  *                          - 'post-thumbnails'
  2680  *                          - 'post-thumbnails'
  2567  *                          - 'responsive-embeds'
  2681  *                          - 'responsive-embeds'
  2568  *                          - 'starter-content'
  2682  *                          - 'starter-content'
  2569  *                          - 'title-tag'
  2683  *                          - 'title-tag'
  2570  *                          - 'wp-block-styles'
       
  2571  *                          - 'widgets'
  2684  *                          - 'widgets'
  2572  *                          - 'widgets-block-editor'
  2685  *                          - 'widgets-block-editor'
       
  2686  *                          - 'wp-block-styles'
  2573  * @param mixed  ...$args Optional extra arguments to pass along with certain features.
  2687  * @param mixed  ...$args Optional extra arguments to pass along with certain features.
  2574  * @return void|false Void on success, false on failure.
  2688  * @return void|false Void on success, false on failure.
  2575  */
  2689  */
  2576 function add_theme_support( $feature, ...$args ) {
  2690 function add_theme_support( $feature, ...$args ) {
  2577 	global $_wp_theme_features;
  2691 	global $_wp_theme_features;
  2683 			);
  2797 			);
  2684 
  2798 
  2685 			$jit = isset( $args[0]['__jit'] );
  2799 			$jit = isset( $args[0]['__jit'] );
  2686 			unset( $args[0]['__jit'] );
  2800 			unset( $args[0]['__jit'] );
  2687 
  2801 
  2688 			// Merge in data from previous add_theme_support() calls.
  2802 			/*
  2689 			// The first value registered wins. (A child theme is set up first.)
  2803 			 * Merge in data from previous add_theme_support() calls.
       
  2804 			 * The first value registered wins. (A child theme is set up first.)
       
  2805 			 */
  2690 			if ( isset( $_wp_theme_features['custom-header'] ) ) {
  2806 			if ( isset( $_wp_theme_features['custom-header'] ) ) {
  2691 				$args[0] = wp_parse_args( $_wp_theme_features['custom-header'][0], $args[0] );
  2807 				$args[0] = wp_parse_args( $_wp_theme_features['custom-header'][0], $args[0] );
  2692 			}
  2808 			}
  2693 
  2809 
  2694 			// Load in the defaults at the end, as we need to insure first one wins.
  2810 			/*
  2695 			// This will cause all constants to be defined, as each arg will then be set to the default.
  2811 			 * Load in the defaults at the end, as we need to insure first one wins.
       
  2812 			 * This will cause all constants to be defined, as each arg will then be set to the default.
       
  2813 			 */
  2696 			if ( $jit ) {
  2814 			if ( $jit ) {
  2697 				$args[0] = wp_parse_args( $args[0], $defaults );
  2815 				$args[0] = wp_parse_args( $args[0], $defaults );
  2698 			}
  2816 			}
  2699 
  2817 
  2700 			/*
  2818 			/*
  2701 			 * If a constant was defined, use that value. Otherwise, define the constant to ensure
  2819 			 * If a constant was defined, use that value. Otherwise, define the constant to ensure
  2702 			 * the constant is always accurate (and is not defined later,  overriding our value).
  2820 			 * the constant is always accurate (and is not defined later,  overriding our value).
  2703 			 * As stated above, the first value wins.
  2821 			 * As stated above, the first value wins.
  2704 			 * Once we get to wp_loaded (just-in-time), define any constants we haven't already.
  2822 			 * Once we get to wp_loaded (just-in-time), define any constants we haven't already.
  2705 			 * Constants are lame. Don't reference them. This is just for backward compatibility.
  2823 			 * Constants should be avoided. Don't reference them. This is just for backward compatibility.
  2706 			 */
  2824 			 */
  2707 
  2825 
  2708 			if ( defined( 'NO_HEADER_TEXT' ) ) {
  2826 			if ( defined( 'NO_HEADER_TEXT' ) ) {
  2709 				$args[0]['header-text'] = ! NO_HEADER_TEXT;
  2827 				$args[0]['header-text'] = ! NO_HEADER_TEXT;
  2710 			} elseif ( isset( $args[0]['header-text'] ) ) {
  2828 			} elseif ( isset( $args[0]['header-text'] ) ) {
  2737 
  2855 
  2738 			if ( $jit && ! empty( $args[0]['default-image'] ) ) {
  2856 			if ( $jit && ! empty( $args[0]['default-image'] ) ) {
  2739 				$args[0]['random-default'] = false;
  2857 				$args[0]['random-default'] = false;
  2740 			}
  2858 			}
  2741 
  2859 
  2742 			// If headers are supported, and we still don't have a defined width or height,
  2860 			/*
  2743 			// we have implicit flex sizes.
  2861 			 * If headers are supported, and we still don't have a defined width or height,
       
  2862 			 * we have implicit flex sizes.
       
  2863 			 */
  2744 			if ( $jit ) {
  2864 			if ( $jit ) {
  2745 				if ( empty( $args[0]['width'] ) && empty( $args[0]['flex-width'] ) ) {
  2865 				if ( empty( $args[0]['width'] ) && empty( $args[0]['flex-width'] ) ) {
  2746 					$args[0]['flex-width'] = true;
  2866 					$args[0]['flex-width'] = true;
  2747 				}
  2867 				}
  2748 				if ( empty( $args[0]['height'] ) && empty( $args[0]['flex-height'] ) ) {
  2868 				if ( empty( $args[0]['height'] ) && empty( $args[0]['flex-height'] ) ) {
  3105  *
  3225  *
  3106  * @since 2.9.0
  3226  * @since 2.9.0
  3107  *
  3227  *
  3108  * @param string $feature The feature being checked. See add_theme_support() for the list
  3228  * @param string $feature The feature being checked. See add_theme_support() for the list
  3109  *                        of possible values.
  3229  *                        of possible values.
  3110  * @param string $include Path to the file.
  3230  * @param string $file    Path to the file.
  3111  * @return bool True if the active theme supports the supplied feature, false otherwise.
  3231  * @return bool True if the active theme supports the supplied feature, false otherwise.
  3112  */
  3232  */
  3113 function require_if_theme_supports( $feature, $include ) {
  3233 function require_if_theme_supports( $feature, $file ) {
  3114 	if ( current_theme_supports( $feature ) ) {
  3234 	if ( current_theme_supports( $feature ) ) {
  3115 		require $include;
  3235 		require $file;
  3116 		return true;
  3236 		return true;
  3117 	}
  3237 	}
  3118 	return false;
  3238 	return false;
  3119 }
  3239 }
  3120 
  3240 
  3314  *
  3434  *
  3315  * @access private
  3435  * @access private
  3316  * @since 3.0.0
  3436  * @since 3.0.0
  3317  * @since 4.3.0 Also removes `header_image_data`.
  3437  * @since 4.3.0 Also removes `header_image_data`.
  3318  * @since 4.5.0 Also removes custom logo theme mods.
  3438  * @since 4.5.0 Also removes custom logo theme mods.
       
  3439  * @since 6.6.0 Also removes `site_logo` option set by the site logo block.
  3319  *
  3440  *
  3320  * @param int $id The attachment ID.
  3441  * @param int $id The attachment ID.
  3321  */
  3442  */
  3322 function _delete_attachment_theme_mod( $id ) {
  3443 function _delete_attachment_theme_mod( $id ) {
  3323 	$attachment_image = wp_get_attachment_url( $id );
  3444 	$attachment_image = wp_get_attachment_url( $id );
  3324 	$header_image     = get_header_image();
  3445 	$header_image     = get_header_image();
  3325 	$background_image = get_background_image();
  3446 	$background_image = get_background_image();
  3326 	$custom_logo_id   = get_theme_mod( 'custom_logo' );
  3447 	$custom_logo_id   = (int) get_theme_mod( 'custom_logo' );
  3327 
  3448 	$site_logo_id     = (int) get_option( 'site_logo' );
  3328 	if ( $custom_logo_id && $custom_logo_id == $id ) {
  3449 
       
  3450 	if ( $custom_logo_id && $custom_logo_id === $id ) {
  3329 		remove_theme_mod( 'custom_logo' );
  3451 		remove_theme_mod( 'custom_logo' );
  3330 		remove_theme_mod( 'header_text' );
  3452 		remove_theme_mod( 'header_text' );
  3331 	}
  3453 	}
  3332 
  3454 
  3333 	if ( $header_image && $header_image == $attachment_image ) {
  3455 	if ( $site_logo_id && $site_logo_id === $id ) {
       
  3456 		delete_option( 'site_logo' );
       
  3457 	}
       
  3458 
       
  3459 	if ( $header_image && $header_image === $attachment_image ) {
  3334 		remove_theme_mod( 'header_image' );
  3460 		remove_theme_mod( 'header_image' );
  3335 		remove_theme_mod( 'header_image_data' );
  3461 		remove_theme_mod( 'header_image_data' );
  3336 	}
  3462 	}
  3337 
  3463 
  3338 	if ( $background_image && $background_image == $attachment_image ) {
  3464 	if ( $background_image && $background_image === $attachment_image ) {
  3339 		remove_theme_mod( 'background_image' );
  3465 		remove_theme_mod( 'background_image' );
  3340 	}
  3466 	}
  3341 }
  3467 }
  3342 
  3468 
  3343 /**
  3469 /**
  3360 			update_option( 'theme_switched_via_customizer', false );
  3486 			update_option( 'theme_switched_via_customizer', false );
  3361 		}
  3487 		}
  3362 
  3488 
  3363 		if ( $old_theme->exists() ) {
  3489 		if ( $old_theme->exists() ) {
  3364 			/**
  3490 			/**
  3365 			 * Fires on the first WP load after a theme switch if the old theme still exists.
  3491 			 * Fires on the next WP load after the theme has been switched.
  3366 			 *
  3492 			 *
  3367 			 * This action fires multiple times and the parameters differs
  3493 			 * The parameters differ according to whether the old theme exists or not.
  3368 			 * according to the context, if the old theme exists or not.
  3494 			 * If the old theme is missing, the old name will instead be the slug
  3369 			 * If the old theme is missing, the parameter will be the slug
       
  3370 			 * of the old theme.
  3495 			 * of the old theme.
       
  3496 			 *
       
  3497 			 * See {@see 'switch_theme'}.
  3371 			 *
  3498 			 *
  3372 			 * @since 3.3.0
  3499 			 * @since 3.3.0
  3373 			 *
  3500 			 *
  3374 			 * @param string   $old_name  Old theme name.
  3501 			 * @param string   $old_name  Old theme name.
  3375 			 * @param WP_Theme $old_theme WP_Theme instance of the old theme.
  3502 			 * @param WP_Theme $old_theme WP_Theme instance of the old theme.
  3434 
  3561 
  3435 	$theme             = null;
  3562 	$theme             = null;
  3436 	$autosaved         = null;
  3563 	$autosaved         = null;
  3437 	$messenger_channel = null;
  3564 	$messenger_channel = null;
  3438 
  3565 
  3439 	// Value false indicates UUID should be determined after_setup_theme
  3566 	/*
  3440 	// to either re-use existing saved changeset or else generate a new UUID if none exists.
  3567 	 * Value false indicates UUID should be determined after_setup_theme
       
  3568 	 * to either re-use existing saved changeset or else generate a new UUID if none exists.
       
  3569 	 */
  3441 	$changeset_uuid = false;
  3570 	$changeset_uuid = false;
  3442 
  3571 
  3443 	// Set initially fo false since defaults to true for back-compat;
  3572 	/*
  3444 	// can be overridden via the customize_changeset_branching filter.
  3573 	 * Set initially to false since defaults to true for back-compat;
       
  3574 	 * can be overridden via the customize_changeset_branching filter.
       
  3575 	 */
  3445 	$branching = false;
  3576 	$branching = false;
  3446 
  3577 
  3447 	if ( $is_customize_admin_page && isset( $input_vars['changeset_uuid'] ) ) {
  3578 	if ( $is_customize_admin_page && isset( $input_vars['changeset_uuid'] ) ) {
  3448 		$changeset_uuid = sanitize_key( $input_vars['changeset_uuid'] );
  3579 		$changeset_uuid = sanitize_key( $input_vars['changeset_uuid'] );
  3449 	} elseif ( ! empty( $input_vars['customize_changeset_uuid'] ) ) {
  3580 	} elseif ( ! empty( $input_vars['customize_changeset_uuid'] ) ) {
  3498  * Publishes a snapshot's changes.
  3629  * Publishes a snapshot's changes.
  3499  *
  3630  *
  3500  * @since 4.7.0
  3631  * @since 4.7.0
  3501  * @access private
  3632  * @access private
  3502  *
  3633  *
  3503  * @global wpdb                 $wpdb         WordPress database abstraction object.
       
  3504  * @global WP_Customize_Manager $wp_customize Customizer instance.
  3634  * @global WP_Customize_Manager $wp_customize Customizer instance.
  3505  *
  3635  *
  3506  * @param string  $new_status     New post status.
  3636  * @param string  $new_status     New post status.
  3507  * @param string  $old_status     Old post status.
  3637  * @param string  $old_status     Old post status.
  3508  * @param WP_Post $changeset_post Changeset post object.
  3638  * @param WP_Post $changeset_post Changeset post object.
  3509  */
  3639  */
  3510 function _wp_customize_publish_changeset( $new_status, $old_status, $changeset_post ) {
  3640 function _wp_customize_publish_changeset( $new_status, $old_status, $changeset_post ) {
  3511 	global $wp_customize, $wpdb;
  3641 	global $wp_customize;
  3512 
  3642 
  3513 	$is_publishing_changeset = (
  3643 	$is_publishing_changeset = (
  3514 		'customize_changeset' === $changeset_post->post_type
  3644 		'customize_changeset' === $changeset_post->post_type
  3515 		&&
  3645 		&&
  3516 		'publish' === $new_status
  3646 		'publish' === $new_status
  3547 		 * settings up front before doing the action.
  3677 		 * settings up front before doing the action.
  3548 		 */
  3678 		 */
  3549 		remove_action( 'customize_register', array( $wp_customize, 'register_controls' ) );
  3679 		remove_action( 'customize_register', array( $wp_customize, 'register_controls' ) );
  3550 		$wp_customize->register_controls();
  3680 		$wp_customize->register_controls();
  3551 
  3681 
  3552 		/** This filter is documented in /wp-includes/class-wp-customize-manager.php */
  3682 		/** This filter is documented in wp-includes/class-wp-customize-manager.php */
  3553 		do_action( 'customize_register', $wp_customize );
  3683 		do_action( 'customize_register', $wp_customize );
  3554 	}
  3684 	}
  3555 	$wp_customize->_publish_changeset_values( $changeset_post->ID );
  3685 	$wp_customize->_publish_changeset_values( $changeset_post->ID );
  3556 
  3686 
  3557 	/*
  3687 	/*
  3599  * @since 3.4.0
  3729  * @since 3.4.0
  3600  */
  3730  */
  3601 function _wp_customize_loader_settings() {
  3731 function _wp_customize_loader_settings() {
  3602 	$admin_origin = parse_url( admin_url() );
  3732 	$admin_origin = parse_url( admin_url() );
  3603 	$home_origin  = parse_url( home_url() );
  3733 	$home_origin  = parse_url( home_url() );
  3604 	$cross_domain = ( strtolower( $admin_origin['host'] ) != strtolower( $home_origin['host'] ) );
  3734 	$cross_domain = ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
  3605 
  3735 
  3606 	$browser = array(
  3736 	$browser = array(
  3607 		'mobile' => wp_is_mobile(),
  3737 		'mobile' => wp_is_mobile(),
  3608 		'ios'    => wp_is_mobile() && preg_match( '/iPad|iPod|iPhone/', $_SERVER['HTTP_USER_AGENT'] ),
  3738 		'ios'    => wp_is_mobile() && preg_match( '/iPad|iPod|iPhone/', $_SERVER['HTTP_USER_AGENT'] ),
  3609 	);
  3739 	);
  3664  * @since 5.5.0 IE8 and older are no longer supported.
  3794  * @since 5.5.0 IE8 and older are no longer supported.
  3665  */
  3795  */
  3666 function wp_customize_support_script() {
  3796 function wp_customize_support_script() {
  3667 	$admin_origin = parse_url( admin_url() );
  3797 	$admin_origin = parse_url( admin_url() );
  3668 	$home_origin  = parse_url( home_url() );
  3798 	$home_origin  = parse_url( home_url() );
  3669 	$cross_domain = ( strtolower( $admin_origin['host'] ) != strtolower( $home_origin['host'] ) );
  3799 	$cross_domain = ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
  3670 	$type_attr    = current_theme_supports( 'html5', 'script' ) ? '' : ' type="text/javascript"';
  3800 	ob_start();
  3671 	?>
  3801 	?>
  3672 	<script<?php echo $type_attr; ?>>
  3802 	<script>
  3673 		(function() {
  3803 		(function() {
  3674 			var request, b = document.body, c = 'className', cs = 'customize-support', rcs = new RegExp('(^|\\s+)(no-)?'+cs+'(\\s+|$)');
  3804 			var request, b = document.body, c = 'className', cs = 'customize-support', rcs = new RegExp('(^|\\s+)(no-)?'+cs+'(\\s+|$)');
  3675 
  3805 
  3676 	<?php	if ( $cross_domain ) : ?>
  3806 	<?php	if ( $cross_domain ) : ?>
  3677 			request = (function(){ var xhr = new XMLHttpRequest(); return ('withCredentials' in xhr); })();
  3807 			request = (function(){ var xhr = new XMLHttpRequest(); return ('withCredentials' in xhr); })();
  3683 			// The customizer requires postMessage and CORS (if the site is cross domain).
  3813 			// The customizer requires postMessage and CORS (if the site is cross domain).
  3684 			b[c] += ( window.postMessage && request ? ' ' : ' no-' ) + cs;
  3814 			b[c] += ( window.postMessage && request ? ' ' : ' no-' ) + cs;
  3685 		}());
  3815 		}());
  3686 	</script>
  3816 	</script>
  3687 	<?php
  3817 	<?php
       
  3818 	wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) );
  3688 }
  3819 }
  3689 
  3820 
  3690 /**
  3821 /**
  3691  * Whether the site is being previewed in the Customizer.
  3822  * Whether the site is being previewed in the Customizer.
  3692  *
  3823  *
  3820 	);
  3951 	);
  3821 	register_theme_feature(
  3952 	register_theme_feature(
  3822 		'block-templates',
  3953 		'block-templates',
  3823 		array(
  3954 		array(
  3824 			'description'  => __( 'Whether a theme uses block-based templates.' ),
  3955 			'description'  => __( 'Whether a theme uses block-based templates.' ),
       
  3956 			'show_in_rest' => true,
       
  3957 		)
       
  3958 	);
       
  3959 	register_theme_feature(
       
  3960 		'block-template-parts',
       
  3961 		array(
       
  3962 			'description'  => __( 'Whether a theme uses block-based template parts.' ),
  3825 			'show_in_rest' => true,
  3963 			'show_in_rest' => true,
  3826 		)
  3964 		)
  3827 	);
  3965 	);
  3828 	register_theme_feature(
  3966 	register_theme_feature(
  3829 		'custom-background',
  3967 		'custom-background',
  4007 			'description'  => __( 'Whether the theme disables custom gradients.' ),
  4145 			'description'  => __( 'Whether the theme disables custom gradients.' ),
  4008 			'show_in_rest' => true,
  4146 			'show_in_rest' => true,
  4009 		)
  4147 		)
  4010 	);
  4148 	);
  4011 	register_theme_feature(
  4149 	register_theme_feature(
       
  4150 		'disable-layout-styles',
       
  4151 		array(
       
  4152 			'description'  => __( 'Whether the theme disables generated layout styles.' ),
       
  4153 			'show_in_rest' => true,
       
  4154 		)
       
  4155 	);
       
  4156 	register_theme_feature(
  4012 		'editor-color-palette',
  4157 		'editor-color-palette',
  4013 		array(
  4158 		array(
  4014 			'type'         => 'array',
  4159 			'type'         => 'array',
  4015 			'description'  => __( 'Custom color palette if defined by the theme.' ),
  4160 			'description'  => __( 'Custom color palette if defined by the theme.' ),
  4016 			'show_in_rest' => array(
  4161 			'show_in_rest' => array(
  4082 				),
  4227 				),
  4083 			),
  4228 			),
  4084 		)
  4229 		)
  4085 	);
  4230 	);
  4086 	register_theme_feature(
  4231 	register_theme_feature(
       
  4232 		'editor-spacing-sizes',
       
  4233 		array(
       
  4234 			'type'         => 'array',
       
  4235 			'description'  => __( 'Custom spacing sizes if defined by the theme.' ),
       
  4236 			'show_in_rest' => array(
       
  4237 				'schema' => array(
       
  4238 					'items' => array(
       
  4239 						'type'       => 'object',
       
  4240 						'properties' => array(
       
  4241 							'name' => array(
       
  4242 								'type' => 'string',
       
  4243 							),
       
  4244 							'size' => array(
       
  4245 								'type' => 'string',
       
  4246 							),
       
  4247 							'slug' => array(
       
  4248 								'type' => 'string',
       
  4249 							),
       
  4250 						),
       
  4251 					),
       
  4252 				),
       
  4253 			),
       
  4254 		)
       
  4255 	);
       
  4256 	register_theme_feature(
  4087 		'editor-styles',
  4257 		'editor-styles',
  4088 		array(
  4258 		array(
  4089 			'description'  => __( 'Whether theme opts in to the editor styles CSS wrapper.' ),
  4259 			'description'  => __( 'Whether theme opts in to the editor styles CSS wrapper.' ),
  4090 			'show_in_rest' => true,
  4260 			'show_in_rest' => true,
  4091 		)
  4261 		)
  4177 /**
  4347 /**
  4178  * Returns whether the active theme is a block-based theme or not.
  4348  * Returns whether the active theme is a block-based theme or not.
  4179  *
  4349  *
  4180  * @since 5.9.0
  4350  * @since 5.9.0
  4181  *
  4351  *
  4182  * @return boolean Whether the active theme is a block-based theme or not.
  4352  * @return bool Whether the active theme is a block-based theme or not.
  4183  */
  4353  */
  4184 function wp_is_block_theme() {
  4354 function wp_is_block_theme() {
  4185 	return wp_get_theme()->is_block_theme();
  4355 	return wp_get_theme()->is_block_theme();
  4186 }
  4356 }
  4187 
  4357 
  4188 /**
  4358 /**
  4189  * Adds default theme supports for block themes when the 'setup_theme' action fires.
  4359  * Given an element name, returns a class name.
  4190  *
  4360  *
  4191  * See {@see 'setup_theme'}.
  4361  * Alias of WP_Theme_JSON::get_element_class_name.
       
  4362  *
       
  4363  * @since 6.1.0
       
  4364  *
       
  4365  * @param string $element The name of the element.
       
  4366  *
       
  4367  * @return string The name of the class.
       
  4368  */
       
  4369 function wp_theme_get_element_class_name( $element ) {
       
  4370 	return WP_Theme_JSON::get_element_class_name( $element );
       
  4371 }
       
  4372 
       
  4373 /**
       
  4374  * Adds default theme supports for block themes when the 'after_setup_theme' action fires.
       
  4375  *
       
  4376  * See {@see 'after_setup_theme'}.
  4192  *
  4377  *
  4193  * @since 5.9.0
  4378  * @since 5.9.0
  4194  * @access private
  4379  * @access private
  4195  */
  4380  */
  4196 function _add_default_theme_supports() {
  4381 function _add_default_theme_supports() {
  4208 	 */
  4393 	 */
  4209 	add_theme_support( 'html5', array( 'comment-form', 'comment-list', 'search-form', 'gallery', 'caption', 'style', 'script' ) );
  4394 	add_theme_support( 'html5', array( 'comment-form', 'comment-list', 'search-form', 'gallery', 'caption', 'style', 'script' ) );
  4210 	add_theme_support( 'automatic-feed-links' );
  4395 	add_theme_support( 'automatic-feed-links' );
  4211 
  4396 
  4212 	add_filter( 'should_load_separate_core_block_assets', '__return_true' );
  4397 	add_filter( 'should_load_separate_core_block_assets', '__return_true' );
  4213 }
  4398 
       
  4399 	/*
       
  4400 	 * Remove the Customizer's Menus panel when block theme is active.
       
  4401 	 */
       
  4402 	add_filter(
       
  4403 		'customize_panel_active',
       
  4404 		static function ( $active, WP_Customize_Panel $panel ) {
       
  4405 			if (
       
  4406 				'nav_menus' === $panel->id &&
       
  4407 				! current_theme_supports( 'menus' ) &&
       
  4408 				! current_theme_supports( 'widgets' )
       
  4409 			) {
       
  4410 				$active = false;
       
  4411 			}
       
  4412 			return $active;
       
  4413 		},
       
  4414 		10,
       
  4415 		2
       
  4416 	);
       
  4417 }