wp/wp-includes/theme.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
--- a/wp/wp-includes/theme.php	Thu Sep 29 08:06:27 2022 +0200
+++ b/wp/wp-includes/theme.php	Fri Sep 05 18:40:08 2025 +0200
@@ -45,8 +45,10 @@
 	$theme_directories = search_theme_directories();
 
 	if ( is_array( $wp_theme_directories ) && count( $wp_theme_directories ) > 1 ) {
-		// Make sure the active theme wins out, in case search_theme_directories() picks the wrong
-		// one in the case of a conflict. (Normally, last registered theme root wins.)
+		/*
+		 * Make sure the active theme wins out, in case search_theme_directories() picks the wrong
+		 * one in the case of a conflict. (Normally, last registered theme root wins.)
+		 */
 		$current_theme = get_stylesheet();
 		if ( isset( $theme_directories[ $current_theme ] ) ) {
 			$root_of_current_theme = get_raw_theme_root( $current_theme );
@@ -89,7 +91,7 @@
 
 	if ( null !== $args['errors'] ) {
 		foreach ( $themes as $theme => $wp_theme ) {
-			if ( $wp_theme->errors() != $args['errors'] ) {
+			if ( (bool) $wp_theme->errors() !== $args['errors'] ) {
 				unset( $themes[ $theme ] );
 			}
 		}
@@ -151,11 +153,17 @@
  * Whether a child theme is in use.
  *
  * @since 3.0.0
+ * @since 6.5.0 Makes use of global template variables.
+ *
+ * @global string $wp_stylesheet_path Path to current theme's stylesheet directory.
+ * @global string $wp_template_path   Path to current theme's template directory.
  *
  * @return bool True if a child theme is in use, false otherwise.
  */
 function is_child_theme() {
-	return ( TEMPLATEPATH !== STYLESHEETPATH );
+	global $wp_stylesheet_path, $wp_template_path;
+
+	return $wp_stylesheet_path !== $wp_template_path;
 }
 
 /**
@@ -185,6 +193,8 @@
  * Retrieves stylesheet directory path for the active theme.
  *
  * @since 1.5.0
+ * @since 6.4.0 Memoizes filter execution so that it only runs once for the current theme.
+ * @since 6.4.2 Memoization removed.
  *
  * @return string Path to active theme's stylesheet directory.
  */
@@ -319,6 +329,8 @@
  * Retrieves template directory path for the active theme.
  *
  * @since 1.5.0
+ * @since 6.4.0 Memoizes filter execution so that it only runs once for the current theme.
+ * @since 6.4.1 Memoization removed.
  *
  * @return string Path to active theme's template directory.
  */
@@ -457,7 +469,7 @@
 	 * to use in get_theme_root().
 	 */
 	foreach ( $wp_theme_directories as $theme_root ) {
-		if ( 0 === strpos( $theme_root, WP_CONTENT_DIR ) ) {
+		if ( str_starts_with( $theme_root, WP_CONTENT_DIR ) ) {
 			$relative_theme_roots[ str_replace( WP_CONTENT_DIR, '', $theme_root ) ] = $theme_root;
 		} else {
 			$relative_theme_roots[ $theme_root ] = $theme_root;
@@ -502,7 +514,7 @@
 		// Start with directories in the root of the active theme directory.
 		$dirs = @ scandir( $theme_root );
 		if ( ! $dirs ) {
-			trigger_error( "$theme_root is not readable", E_USER_NOTICE );
+			wp_trigger_error( __FUNCTION__, "$theme_root is not readable" );
 			continue;
 		}
 		foreach ( $dirs as $dir ) {
@@ -510,19 +522,23 @@
 				continue;
 			}
 			if ( file_exists( $theme_root . '/' . $dir . '/style.css' ) ) {
-				// wp-content/themes/a-single-theme
-				// wp-content/themes is $theme_root, a-single-theme is $dir.
+				/*
+				 * wp-content/themes/a-single-theme
+				 * wp-content/themes is $theme_root, a-single-theme is $dir.
+				 */
 				$found_themes[ $dir ] = array(
 					'theme_file' => $dir . '/style.css',
 					'theme_root' => $theme_root,
 				);
 			} else {
 				$found_theme = false;
-				// wp-content/themes/a-folder-of-themes/*
-				// wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs.
+				/*
+				 * wp-content/themes/a-folder-of-themes/*
+				 * wp-content/themes is $theme_root, a-folder-of-themes is $dir, then themes are $sub_dirs.
+				 */
 				$sub_dirs = @ scandir( $theme_root . '/' . $dir );
 				if ( ! $sub_dirs ) {
-					trigger_error( "$theme_root/$dir is not readable", E_USER_NOTICE );
+					wp_trigger_error( __FUNCTION__, "$theme_root/$dir is not readable" );
 					continue;
 				}
 				foreach ( $sub_dirs as $sub_dir ) {
@@ -538,8 +554,10 @@
 					);
 					$found_theme                           = true;
 				}
-				// Never mind the above, it's just a theme missing a style.css.
-				// Return it; WP_Theme will catch the error.
+				/*
+				 * Never mind the above, it's just a theme missing a style.css.
+				 * Return it; WP_Theme will catch the error.
+				 */
 				if ( ! $found_theme ) {
 					$found_themes[ $dir ] = array(
 						'theme_file' => $dir . '/style.css',
@@ -559,7 +577,7 @@
 		$theme_roots[ $theme_dir ] = $relative_theme_roots[ $theme_data['theme_root'] ]; // Convert absolute to relative.
 	}
 
-	if ( get_site_transient( 'theme_roots' ) != $theme_roots ) {
+	if ( get_site_transient( 'theme_roots' ) !== $theme_roots ) {
 		set_site_transient( 'theme_roots', $theme_roots, $cache_expiration );
 	}
 
@@ -587,8 +605,10 @@
 	if ( $stylesheet_or_template ) {
 		$theme_root = get_raw_theme_root( $stylesheet_or_template );
 		if ( $theme_root ) {
-			// Always prepend WP_CONTENT_DIR unless the root currently registered as a theme directory.
-			// This gives relative theme roots the benefit of the doubt when things go haywire.
+			/*
+			 * Always prepend WP_CONTENT_DIR unless the root currently registered as a theme directory.
+			 * This gives relative theme roots the benefit of the doubt when things go haywire.
+			 */
 			if ( ! in_array( $theme_root, (array) $wp_theme_directories, true ) ) {
 				$theme_root = WP_CONTENT_DIR . $theme_root;
 			}
@@ -634,11 +654,11 @@
 	if ( $stylesheet_or_template && $theme_root ) {
 		if ( in_array( $theme_root, (array) $wp_theme_directories, true ) ) {
 			// Absolute path. Make an educated guess. YMMV -- but note the filter below.
-			if ( 0 === strpos( $theme_root, WP_CONTENT_DIR ) ) {
+			if ( str_starts_with( $theme_root, WP_CONTENT_DIR ) ) {
 				$theme_root_uri = content_url( str_replace( WP_CONTENT_DIR, '', $theme_root ) );
-			} elseif ( 0 === strpos( $theme_root, ABSPATH ) ) {
+			} elseif ( str_starts_with( $theme_root, ABSPATH ) ) {
 				$theme_root_uri = site_url( str_replace( ABSPATH, '', $theme_root ) );
-			} elseif ( 0 === strpos( $theme_root, WP_PLUGIN_DIR ) || 0 === strpos( $theme_root, WPMU_PLUGIN_DIR ) ) {
+			} elseif ( str_starts_with( $theme_root, WP_PLUGIN_DIR ) || str_starts_with( $theme_root, WPMU_PLUGIN_DIR ) ) {
 				$theme_root_uri = plugins_url( basename( $theme_root ), $theme_root );
 			} else {
 				$theme_root_uri = $theme_root;
@@ -685,9 +705,9 @@
 
 	// If requesting the root for the active theme, consult options to avoid calling get_theme_roots().
 	if ( ! $skip_cache ) {
-		if ( get_option( 'stylesheet' ) == $stylesheet_or_template ) {
+		if ( get_option( 'stylesheet' ) === $stylesheet_or_template ) {
 			$theme_root = get_option( 'stylesheet_root' );
-		} elseif ( get_option( 'template' ) == $stylesheet_or_template ) {
+		} elseif ( get_option( 'template' ) === $stylesheet_or_template ) {
 			$theme_root = get_option( 'template_root' );
 		}
 	}
@@ -733,11 +753,12 @@
  * @global array                $wp_theme_directories
  * @global WP_Customize_Manager $wp_customize
  * @global array                $sidebars_widgets
+ * @global array                $wp_registered_sidebars
  *
  * @param string $stylesheet Stylesheet name.
  */
 function switch_theme( $stylesheet ) {
-	global $wp_theme_directories, $wp_customize, $sidebars_widgets;
+	global $wp_theme_directories, $wp_customize, $sidebars_widgets, $wp_registered_sidebars;
 
 	$requirements = validate_theme_requirements( $stylesheet );
 	if ( is_wp_error( $requirements ) ) {
@@ -814,11 +835,39 @@
 		}
 	}
 
+	// Stores classic sidebars for later use by block themes.
+	if ( $new_theme->is_block_theme() ) {
+		set_theme_mod( 'wp_classic_sidebars', $wp_registered_sidebars );
+	}
+
 	update_option( 'theme_switched', $old_theme->get_stylesheet() );
 
+	/*
+	 * Reset template globals when switching themes outside of a switched blog
+	 * context to ensure templates will be loaded from the new theme.
+	 */
+	if ( ! is_multisite() || ! ms_is_switched() ) {
+		wp_set_template_globals();
+	}
+
+	// Clear pattern caches.
+	if ( ! is_multisite() ) {
+		$new_theme->delete_pattern_cache();
+		$old_theme->delete_pattern_cache();
+	}
+
+	// Set autoload=no for the old theme, autoload=yes for the switched theme.
+	$theme_mods_options = array(
+		'theme_mods_' . $stylesheet                  => 'yes',
+		'theme_mods_' . $old_theme->get_stylesheet() => 'no',
+	);
+	wp_set_option_autoload_values( $theme_mods_options );
+
 	/**
 	 * Fires after the theme is switched.
 	 *
+	 * See {@see 'after_switch_theme'}.
+	 *
 	 * @since 1.5.0
 	 * @since 4.5.0 Introduced the `$old_theme` parameter.
 	 *
@@ -893,7 +942,7 @@
 	 * if it turns out there is no default theme installed. (That's `false`.)
 	 */
 	$default = WP_Theme::get_core_default_theme();
-	if ( false === $default || get_stylesheet() == $default->get_stylesheet() ) {
+	if ( false === $default || get_stylesheet() === $default->get_stylesheet() ) {
 		return true;
 	}
 
@@ -991,18 +1040,18 @@
 /**
  * Retrieves theme modification value for the active theme.
  *
- * If the modification name does not exist and `$default` is a string, then the
+ * If the modification name does not exist and `$default_value` is a string, then the
  * default will be passed through the {@link https://www.php.net/sprintf sprintf()}
  * PHP function with the template directory URI as the first value and the
  * stylesheet directory URI as the second value.
  *
  * @since 2.1.0
  *
- * @param string $name    Theme modification name.
- * @param mixed  $default Optional. Theme modification default value. Default false.
+ * @param string $name          Theme modification name.
+ * @param mixed  $default_value Optional. Theme modification default value. Default false.
  * @return mixed Theme modification value.
  */
-function get_theme_mod( $name, $default = false ) {
+function get_theme_mod( $name, $default_value = false ) {
 	$mods = get_theme_mods();
 
 	if ( isset( $mods[ $name ] ) ) {
@@ -1020,17 +1069,17 @@
 		return apply_filters( "theme_mod_{$name}", $mods[ $name ] );
 	}
 
-	if ( is_string( $default ) ) {
+	if ( is_string( $default_value ) ) {
 		// Only run the replacement if an sprintf() string format pattern was found.
-		if ( preg_match( '#(?<!%)%(?:\d+\$?)?s#', $default ) ) {
+		if ( preg_match( '#(?<!%)%(?:\d+\$?)?s#', $default_value ) ) {
 			// Remove a single trailing percent sign.
-			$default = preg_replace( '#(?<!%)%$#', '', $default );
-			$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
+			$default_value = preg_replace( '#(?<!%)%$#', '', $default_value );
+			$default_value = sprintf( $default_value, get_template_directory_uri(), get_stylesheet_directory_uri() );
 		}
 	}
 
 	/** This filter is documented in wp-includes/theme.php */
-	return apply_filters( "theme_mod_{$name}", $default );
+	return apply_filters( "theme_mod_{$name}", $default_value );
 }
 
 /**
@@ -1179,7 +1228,21 @@
 		$url = get_random_header_image();
 	}
 
-	return esc_url_raw( set_url_scheme( $url ) );
+	/**
+	 * Filters the header image URL.
+	 *
+	 * @since 6.1.0
+	 *
+	 * @param string $url Header image URL.
+	 */
+	$url = apply_filters( 'get_header_image', $url );
+
+	if ( ! is_string( $url ) ) {
+		return false;
+	}
+
+	$url = trim( $url );
+	return sanitize_url( set_url_scheme( $url ) );
 }
 
 /**
@@ -1243,6 +1306,29 @@
 		}
 	}
 
+	$attr = array_merge(
+		$attr,
+		wp_get_loading_optimization_attributes( 'img', $attr, 'get_header_image_tag' )
+	);
+
+	/*
+	 * If the default value of `lazy` for the `loading` attribute is overridden
+	 * to omit the attribute for this image, ensure it is not included.
+	 */
+	if ( isset( $attr['loading'] ) && ! $attr['loading'] ) {
+		unset( $attr['loading'] );
+	}
+
+	// If the `fetchpriority` attribute is overridden and set to false or an empty string.
+	if ( isset( $attr['fetchpriority'] ) && ! $attr['fetchpriority'] ) {
+		unset( $attr['fetchpriority'] );
+	}
+
+	// If the `decoding` attribute is overridden and set to false or an empty string.
+	if ( isset( $attr['decoding'] ) && ! $attr['decoding'] ) {
+		unset( $attr['decoding'] );
+	}
+
 	/**
 	 * Filters the list of header image attributes.
 	 *
@@ -1317,7 +1403,7 @@
 		}
 
 		if ( empty( $headers ) ) {
-			return new stdClass;
+			return new stdClass();
 		}
 
 		$_wp_random_header = (object) $headers[ array_rand( $headers ) ];
@@ -1374,14 +1460,16 @@
 	if ( 'any' === $type ) {
 		if ( 'random-default-image' === $header_image_mod
 			|| 'random-uploaded-image' === $header_image_mod
-			|| ( '' !== get_random_header_image() && empty( $header_image_mod ) )
+			|| ( empty( $header_image_mod ) && '' !== get_random_header_image() )
 		) {
 			return true;
 		}
 	} else {
 		if ( "random-$type-image" === $header_image_mod ) {
 			return true;
-		} elseif ( 'default' === $type && empty( $header_image_mod ) && '' !== get_random_header_image() ) {
+		} elseif ( 'default' === $type
+			&& empty( $header_image_mod ) && '' !== get_random_header_image()
+		) {
 			return true;
 		}
 	}
@@ -1428,7 +1516,7 @@
 	}
 
 	foreach ( (array) $headers as $header ) {
-		$url          = esc_url_raw( wp_get_attachment_url( $header->ID ) );
+		$url          = sanitize_url( wp_get_attachment_url( $header->ID ) );
 		$header_data  = wp_get_attachment_metadata( $header->ID );
 		$header_index = $header->ID;
 
@@ -1479,7 +1567,7 @@
 			if ( ! empty( $_wp_default_headers ) ) {
 				foreach ( (array) $_wp_default_headers as $default_header ) {
 					$url = vsprintf( $default_header['url'], $directory_args );
-					if ( $data['url'] == $url ) {
+					if ( $data['url'] === $url ) {
 						$data                  = $default_header;
 						$data['url']           = $url;
 						$data['thumbnail_url'] = vsprintf( $data['thumbnail_url'], $directory_args );
@@ -1589,7 +1677,7 @@
 		return false;
 	}
 
-	return esc_url_raw( set_url_scheme( $url ) );
+	return sanitize_url( set_url_scheme( $url ) );
 }
 
 /**
@@ -1786,8 +1874,10 @@
 	// $background is the saved custom image, or the default image.
 	$background = set_url_scheme( get_background_image() );
 
-	// $color is the saved custom color.
-	// A default has to be specified in style.css. It will not be printed here.
+	/*
+	 * $color is the saved custom color.
+	 * A default has to be specified in style.css. It will not be printed here.
+	 */
 	$color = get_background_color();
 
 	if ( get_theme_support( 'custom-background', 'default-color' ) === $color ) {
@@ -1806,7 +1896,7 @@
 	$style = $color ? "background-color: #$color;" : '';
 
 	if ( $background ) {
-		$image = ' background-image: url("' . esc_url_raw( $background ) . '");';
+		$image = ' background-image: url("' . sanitize_url( $background ) . '");';
 
 		// Background Position.
 		$position_x = get_theme_mod( 'background_position_x', get_theme_support( 'custom-background', 'default-position-x' ) );
@@ -2054,7 +2144,8 @@
 			}
 
 			// Trigger creation of a revision. This should be removed once #30854 is resolved.
-			if ( 0 === count( wp_get_post_revisions( $r ) ) ) {
+			$revisions = wp_get_latest_revision_id_and_total_count( $r );
+			if ( ! is_wp_error( $revisions ) && 0 === $revisions['count'] ) {
 				wp_save_post_revision( $r );
 			}
 		}
@@ -2146,7 +2237,7 @@
 		// Support externally referenced styles (like, say, fonts).
 		foreach ( $editor_styles as $key => $file ) {
 			if ( preg_match( '~^(https?:)?//~', $file ) ) {
-				$stylesheets[] = esc_url_raw( $file );
+				$stylesheets[] = sanitize_url( $file );
 				unset( $editor_styles[ $key ] );
 			}
 		}
@@ -2355,7 +2446,7 @@
 				'post_title'   => _x( 'About', 'Theme starter content' ),
 				'post_content' => sprintf(
 					"<!-- wp:paragraph -->\n<p>%s</p>\n<!-- /wp:paragraph -->",
-					_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' )
+					_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' )
 				),
 			),
 			'contact'          => array(
@@ -2460,8 +2551,10 @@
 				}
 				break;
 
-			// All that's left now are posts (besides attachments).
-			// Not a default case for the sake of clarity and future work.
+			/*
+			 * All that's left now are posts (besides attachments).
+			 * Not a default case for the sake of clarity and future work.
+			 */
 			case 'posts':
 				foreach ( $config[ $type ] as $id => $item ) {
 					if ( is_array( $item ) ) {
@@ -2523,6 +2616,8 @@
  * @since 2.9.0
  * @since 3.4.0 The `custom-header-uploads` feature was deprecated.
  * @since 3.6.0 The `html5` feature was added.
+ * @since 3.6.1 The `html5` feature requires an array of types to be passed. Defaults to
+ *              'comment-list', 'comment-form', 'search-form' for backward compatibility.
  * @since 3.9.0 The `html5` feature now also accepts 'gallery' and 'caption'.
  * @since 4.1.0 The `title-tag` feature was added.
  * @since 4.5.0 The `customize-selective-refresh-widgets` feature was added.
@@ -2533,17 +2628,32 @@
  * @since 5.3.0 The `html5` feature now also accepts 'script' and 'style'.
  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
  *              by adding it to the function signature.
+ * @since 5.4.0 The `disable-custom-gradients` feature limits to default gradients or gradients added
+ *              through `editor-gradient-presets` theme support.
  * @since 5.5.0 The `core-block-patterns` feature was added and is enabled by default.
  * @since 5.5.0 The `custom-logo` feature now also accepts 'unlink-homepage-logo'.
- * @since 5.6.0 The `post-formats` feature warns if no array is passed.
+ * @since 5.6.0 The `post-formats` feature warns if no array is passed as the second parameter.
  * @since 5.8.0 The `widgets-block-editor` feature enables the Widgets block editor.
+ * @since 5.8.0 The `block-templates` feature indicates whether a theme uses block-based templates.
+ * @since 6.0.0 The `html5` feature warns if no array is passed as the second parameter.
+ * @since 6.1.0 The `block-template-parts` feature allows to edit any reusable template part from site editor.
+ * @since 6.1.0 The `disable-layout-styles` feature disables the default layout styles.
+ * @since 6.3.0 The `link-color` feature allows to enable the link color setting.
+ * @since 6.3.0 The `border` feature allows themes without theme.json to add border styles to blocks.
+ * @since 6.5.0 The `appearance-tools` feature enables a few design tools for blocks,
+ *              see `WP_Theme_JSON::APPEARANCE_TOOLS_OPT_INS` for a complete list.
+ * @since 6.6.0 The `editor-spacing-sizes` feature was added.
  *
  * @global array $_wp_theme_features
  *
  * @param string $feature The feature being added. Likely core values include:
  *                          - 'admin-bar'
  *                          - 'align-wide'
+ *                          - 'appearance-tools'
  *                          - 'automatic-feed-links'
+ *                          - 'block-templates'
+ *                          - 'block-template-parts'
+ *                          - 'border'
  *                          - 'core-block-patterns'
  *                          - 'custom-background'
  *                          - 'custom-header'
@@ -2555,21 +2665,25 @@
  *                          - 'dark-editor-style'
  *                          - 'disable-custom-colors'
  *                          - 'disable-custom-font-sizes'
+ *                          - 'disable-custom-gradients'
+ *                          - 'disable-layout-styles'
  *                          - 'editor-color-palette'
  *                          - 'editor-gradient-presets'
  *                          - 'editor-font-sizes'
+ *                          - 'editor-spacing-sizes'
  *                          - 'editor-styles'
  *                          - 'featured-content'
  *                          - 'html5'
+ *                          - 'link-color'
  *                          - 'menus'
  *                          - 'post-formats'
  *                          - 'post-thumbnails'
  *                          - 'responsive-embeds'
  *                          - 'starter-content'
  *                          - 'title-tag'
- *                          - 'wp-block-styles'
  *                          - 'widgets'
  *                          - 'widgets-block-editor'
+ *                          - 'wp-block-styles'
  * @param mixed  ...$args Optional extra arguments to pass along with certain features.
  * @return void|false Void on success, false on failure.
  */
@@ -2685,14 +2799,18 @@
 			$jit = isset( $args[0]['__jit'] );
 			unset( $args[0]['__jit'] );
 
-			// Merge in data from previous add_theme_support() calls.
-			// The first value registered wins. (A child theme is set up first.)
+			/*
+			 * Merge in data from previous add_theme_support() calls.
+			 * The first value registered wins. (A child theme is set up first.)
+			 */
 			if ( isset( $_wp_theme_features['custom-header'] ) ) {
 				$args[0] = wp_parse_args( $_wp_theme_features['custom-header'][0], $args[0] );
 			}
 
-			// Load in the defaults at the end, as we need to insure first one wins.
-			// This will cause all constants to be defined, as each arg will then be set to the default.
+			/*
+			 * Load in the defaults at the end, as we need to insure first one wins.
+			 * This will cause all constants to be defined, as each arg will then be set to the default.
+			 */
 			if ( $jit ) {
 				$args[0] = wp_parse_args( $args[0], $defaults );
 			}
@@ -2702,7 +2820,7 @@
 			 * the constant is always accurate (and is not defined later,  overriding our value).
 			 * As stated above, the first value wins.
 			 * Once we get to wp_loaded (just-in-time), define any constants we haven't already.
-			 * Constants are lame. Don't reference them. This is just for backward compatibility.
+			 * Constants should be avoided. Don't reference them. This is just for backward compatibility.
 			 */
 
 			if ( defined( 'NO_HEADER_TEXT' ) ) {
@@ -2739,8 +2857,10 @@
 				$args[0]['random-default'] = false;
 			}
 
-			// If headers are supported, and we still don't have a defined width or height,
-			// we have implicit flex sizes.
+			/*
+			 * If headers are supported, and we still don't have a defined width or height,
+			 * we have implicit flex sizes.
+			 */
 			if ( $jit ) {
 				if ( empty( $args[0]['width'] ) && empty( $args[0]['flex-width'] ) ) {
 					$args[0]['flex-width'] = true;
@@ -3107,12 +3227,12 @@
  *
  * @param string $feature The feature being checked. See add_theme_support() for the list
  *                        of possible values.
- * @param string $include Path to the file.
+ * @param string $file    Path to the file.
  * @return bool True if the active theme supports the supplied feature, false otherwise.
  */
-function require_if_theme_supports( $feature, $include ) {
+function require_if_theme_supports( $feature, $file ) {
 	if ( current_theme_supports( $feature ) ) {
-		require $include;
+		require $file;
 		return true;
 	}
 	return false;
@@ -3316,6 +3436,7 @@
  * @since 3.0.0
  * @since 4.3.0 Also removes `header_image_data`.
  * @since 4.5.0 Also removes custom logo theme mods.
+ * @since 6.6.0 Also removes `site_logo` option set by the site logo block.
  *
  * @param int $id The attachment ID.
  */
@@ -3323,19 +3444,24 @@
 	$attachment_image = wp_get_attachment_url( $id );
 	$header_image     = get_header_image();
 	$background_image = get_background_image();
-	$custom_logo_id   = get_theme_mod( 'custom_logo' );
-
-	if ( $custom_logo_id && $custom_logo_id == $id ) {
+	$custom_logo_id   = (int) get_theme_mod( 'custom_logo' );
+	$site_logo_id     = (int) get_option( 'site_logo' );
+
+	if ( $custom_logo_id && $custom_logo_id === $id ) {
 		remove_theme_mod( 'custom_logo' );
 		remove_theme_mod( 'header_text' );
 	}
 
-	if ( $header_image && $header_image == $attachment_image ) {
+	if ( $site_logo_id && $site_logo_id === $id ) {
+		delete_option( 'site_logo' );
+	}
+
+	if ( $header_image && $header_image === $attachment_image ) {
 		remove_theme_mod( 'header_image' );
 		remove_theme_mod( 'header_image_data' );
 	}
 
-	if ( $background_image && $background_image == $attachment_image ) {
+	if ( $background_image && $background_image === $attachment_image ) {
 		remove_theme_mod( 'background_image' );
 	}
 }
@@ -3362,13 +3488,14 @@
 
 		if ( $old_theme->exists() ) {
 			/**
-			 * Fires on the first WP load after a theme switch if the old theme still exists.
+			 * Fires on the next WP load after the theme has been switched.
 			 *
-			 * This action fires multiple times and the parameters differs
-			 * according to the context, if the old theme exists or not.
-			 * If the old theme is missing, the parameter will be the slug
+			 * The parameters differ according to whether the old theme exists or not.
+			 * If the old theme is missing, the old name will instead be the slug
 			 * of the old theme.
 			 *
+			 * See {@see 'switch_theme'}.
+			 *
 			 * @since 3.3.0
 			 *
 			 * @param string   $old_name  Old theme name.
@@ -3436,12 +3563,16 @@
 	$autosaved         = null;
 	$messenger_channel = null;
 
-	// Value false indicates UUID should be determined after_setup_theme
-	// to either re-use existing saved changeset or else generate a new UUID if none exists.
+	/*
+	 * Value false indicates UUID should be determined after_setup_theme
+	 * to either re-use existing saved changeset or else generate a new UUID if none exists.
+	 */
 	$changeset_uuid = false;
 
-	// Set initially fo false since defaults to true for back-compat;
-	// can be overridden via the customize_changeset_branching filter.
+	/*
+	 * Set initially to false since defaults to true for back-compat;
+	 * can be overridden via the customize_changeset_branching filter.
+	 */
 	$branching = false;
 
 	if ( $is_customize_admin_page && isset( $input_vars['changeset_uuid'] ) ) {
@@ -3500,7 +3631,6 @@
  * @since 4.7.0
  * @access private
  *
- * @global wpdb                 $wpdb         WordPress database abstraction object.
  * @global WP_Customize_Manager $wp_customize Customizer instance.
  *
  * @param string  $new_status     New post status.
@@ -3508,7 +3638,7 @@
  * @param WP_Post $changeset_post Changeset post object.
  */
 function _wp_customize_publish_changeset( $new_status, $old_status, $changeset_post ) {
-	global $wp_customize, $wpdb;
+	global $wp_customize;
 
 	$is_publishing_changeset = (
 		'customize_changeset' === $changeset_post->post_type
@@ -3549,7 +3679,7 @@
 		remove_action( 'customize_register', array( $wp_customize, 'register_controls' ) );
 		$wp_customize->register_controls();
 
-		/** This filter is documented in /wp-includes/class-wp-customize-manager.php */
+		/** This filter is documented in wp-includes/class-wp-customize-manager.php */
 		do_action( 'customize_register', $wp_customize );
 	}
 	$wp_customize->_publish_changeset_values( $changeset_post->ID );
@@ -3601,7 +3731,7 @@
 function _wp_customize_loader_settings() {
 	$admin_origin = parse_url( admin_url() );
 	$home_origin  = parse_url( home_url() );
-	$cross_domain = ( strtolower( $admin_origin['host'] ) != strtolower( $home_origin['host'] ) );
+	$cross_domain = ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
 
 	$browser = array(
 		'mobile' => wp_is_mobile(),
@@ -3666,10 +3796,10 @@
 function wp_customize_support_script() {
 	$admin_origin = parse_url( admin_url() );
 	$home_origin  = parse_url( home_url() );
-	$cross_domain = ( strtolower( $admin_origin['host'] ) != strtolower( $home_origin['host'] ) );
-	$type_attr    = current_theme_supports( 'html5', 'script' ) ? '' : ' type="text/javascript"';
+	$cross_domain = ( strtolower( $admin_origin['host'] ) !== strtolower( $home_origin['host'] ) );
+	ob_start();
 	?>
-	<script<?php echo $type_attr; ?>>
+	<script>
 		(function() {
 			var request, b = document.body, c = 'className', cs = 'customize-support', rcs = new RegExp('(^|\\s+)(no-)?'+cs+'(\\s+|$)');
 
@@ -3685,6 +3815,7 @@
 		}());
 	</script>
 	<?php
+	wp_print_inline_script_tag( wp_remove_surrounding_empty_script_tags( ob_get_clean() ) );
 }
 
 /**
@@ -3826,6 +3957,13 @@
 		)
 	);
 	register_theme_feature(
+		'block-template-parts',
+		array(
+			'description'  => __( 'Whether a theme uses block-based template parts.' ),
+			'show_in_rest' => true,
+		)
+	);
+	register_theme_feature(
 		'custom-background',
 		array(
 			'description'  => __( 'Custom background if defined by the theme.' ),
@@ -4009,6 +4147,13 @@
 		)
 	);
 	register_theme_feature(
+		'disable-layout-styles',
+		array(
+			'description'  => __( 'Whether the theme disables generated layout styles.' ),
+			'show_in_rest' => true,
+		)
+	);
+	register_theme_feature(
 		'editor-color-palette',
 		array(
 			'type'         => 'array',
@@ -4084,6 +4229,31 @@
 		)
 	);
 	register_theme_feature(
+		'editor-spacing-sizes',
+		array(
+			'type'         => 'array',
+			'description'  => __( 'Custom spacing sizes if defined by the theme.' ),
+			'show_in_rest' => array(
+				'schema' => array(
+					'items' => array(
+						'type'       => 'object',
+						'properties' => array(
+							'name' => array(
+								'type' => 'string',
+							),
+							'size' => array(
+								'type' => 'string',
+							),
+							'slug' => array(
+								'type' => 'string',
+							),
+						),
+					),
+				),
+			),
+		)
+	);
+	register_theme_feature(
 		'editor-styles',
 		array(
 			'description'  => __( 'Whether theme opts in to the editor styles CSS wrapper.' ),
@@ -4179,16 +4349,31 @@
  *
  * @since 5.9.0
  *
- * @return boolean Whether the active theme is a block-based theme or not.
+ * @return bool Whether the active theme is a block-based theme or not.
  */
 function wp_is_block_theme() {
 	return wp_get_theme()->is_block_theme();
 }
 
 /**
- * Adds default theme supports for block themes when the 'setup_theme' action fires.
- *
- * See {@see 'setup_theme'}.
+ * Given an element name, returns a class name.
+ *
+ * Alias of WP_Theme_JSON::get_element_class_name.
+ *
+ * @since 6.1.0
+ *
+ * @param string $element The name of the element.
+ *
+ * @return string The name of the class.
+ */
+function wp_theme_get_element_class_name( $element ) {
+	return WP_Theme_JSON::get_element_class_name( $element );
+}
+
+/**
+ * Adds default theme supports for block themes when the 'after_setup_theme' action fires.
+ *
+ * See {@see 'after_setup_theme'}.
  *
  * @since 5.9.0
  * @access private
@@ -4210,4 +4395,23 @@
 	add_theme_support( 'automatic-feed-links' );
 
 	add_filter( 'should_load_separate_core_block_assets', '__return_true' );
+
+	/*
+	 * Remove the Customizer's Menus panel when block theme is active.
+	 */
+	add_filter(
+		'customize_panel_active',
+		static function ( $active, WP_Customize_Panel $panel ) {
+			if (
+				'nav_menus' === $panel->id &&
+				! current_theme_supports( 'menus' ) &&
+				! current_theme_supports( 'widgets' )
+			) {
+				$active = false;
+			}
+			return $active;
+		},
+		10,
+		2
+	);
 }