: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
<style id="custom-logo-css"<?php echo $type_attr; ?>>
<?php echo $classes; ?> {
clip: rect(1px, 1px, 1px, 1px);
* Gets the theme support arguments passed when registering that support.
* get_theme_support( 'custom-logo' );
* get_theme_support( 'custom-header', 'width' );
* @since 5.3.0 Formalized the existing and already documented `...$args` parameter
* by adding it to the function signature.
* @global array $_wp_theme_features
* @param string $feature The feature to check. See add_theme_support() for the list
* @param mixed ...$args Optional extra arguments to be checked against certain features.
* @return mixed The array of extra arguments or the value for the registered feature.
function get_theme_support( $feature, ...$args ) {
global $_wp_theme_features;
if ( ! isset( $_wp_theme_features[ $feature ] ) ) {
return $_wp_theme_features[ $feature ];
case 'custom-background':
if ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) ) {
return $_wp_theme_features[ $feature ][0][ $args[0] ];
return $_wp_theme_features[ $feature ];
* Allows a theme to de-register its support of a certain feature
* Should be called in the theme's functions.php file. Generally would
* be used for child themes to override support from the parent theme.
* @see add_theme_support()
* @param string $feature The feature being removed. See add_theme_support() for the list
* @return bool|void Whether feature was removed.
function remove_theme_support( $feature ) {
// Do not remove internal registrations that are not used directly by themes.
if ( in_array( $feature, array( 'editor-style', 'widgets', 'menus' ), true ) ) {
return _remove_theme_support( $feature );
* Do not use. Removes theme support internally without knowledge of those not used
* @global array $_wp_theme_features
* @global Custom_Image_Header $custom_image_header
* @global Custom_Background $custom_background
* @param string $feature The feature being removed. See add_theme_support() for the list
* @return bool True if support was removed, false if the feature was not registered.
function _remove_theme_support( $feature ) {
global $_wp_theme_features;
case 'custom-header-uploads':
if ( ! isset( $_wp_theme_features['custom-header'] ) ) {
add_theme_support( 'custom-header', array( 'uploads' => false ) );
return; // Do not continue - custom-header-uploads no longer exists.
if ( ! isset( $_wp_theme_features[ $feature ] ) ) {
if ( ! did_action( 'wp_loaded' ) ) {
$support = get_theme_support( 'custom-header' );
if ( isset( $support[0]['wp-head-callback'] ) ) {
remove_action( 'wp_head', $support[0]['wp-head-callback'] );
if ( isset( $GLOBALS['custom_image_header'] ) ) {
remove_action( 'admin_menu', array( $GLOBALS['custom_image_header'], 'init' ) );
unset( $GLOBALS['custom_image_header'] );
case 'custom-background':
if ( ! did_action( 'wp_loaded' ) ) {
$support = get_theme_support( 'custom-background' );
if ( isset( $support[0]['wp-head-callback'] ) ) {
remove_action( 'wp_head', $support[0]['wp-head-callback'] );
remove_action( 'admin_menu', array( $GLOBALS['custom_background'], 'init' ) );
unset( $GLOBALS['custom_background'] );
unset( $_wp_theme_features[ $feature ] );
* Checks a theme's support for a given feature.
* current_theme_supports( 'custom-logo' );
* current_theme_supports( 'html5', 'comment-form' );
* @since 5.3.0 Formalized the existing and already documented `...$args` parameter
* by adding it to the function signature.
* @global array $_wp_theme_features
* @param string $feature The feature being checked. See add_theme_support() for the list
* @param mixed ...$args Optional extra arguments to be checked against certain features.
* @return bool True if the active theme supports the feature, false otherwise.
function current_theme_supports( $feature, ...$args ) {
global $_wp_theme_features;
if ( 'custom-header-uploads' === $feature ) {
return current_theme_supports( 'custom-header', 'uploads' );
if ( ! isset( $_wp_theme_features[ $feature ] ) ) {
// If no args passed then no extra checks need to be performed.
/** This filter is documented in wp-includes/theme.php */
return apply_filters( "current_theme_supports-{$feature}", true, $args, $_wp_theme_features[ $feature ] ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
* post-thumbnails can be registered for only certain content/post types
* by passing an array of types to add_theme_support().
* If no array was passed, then any type is accepted.
if ( true === $_wp_theme_features[ $feature ] ) { // Registered for all types.
$content_type = $args[0];
return in_array( $content_type, $_wp_theme_features[ $feature ][0], true );
* Specific post formats can be registered by passing an array of types
* to add_theme_support().
* Specific areas of HTML5 support *must* be passed via an array to add_theme_support().
return in_array( $type, $_wp_theme_features[ $feature ][0], true );
case 'custom-background':
// Specific capabilities can be registered by passing an array to add_theme_support().
return ( isset( $_wp_theme_features[ $feature ][0][ $args[0] ] ) && $_wp_theme_features[ $feature ][0][ $args[0] ] );
* Filters whether the active theme supports a specific feature.
* The dynamic portion of the hook name, `$feature`, refers to the specific
* theme feature. See add_theme_support() for the list of possible values.
* @param bool $supports Whether the active theme supports the given feature. Default true.
* @param array $args Array of arguments for the feature.
* @param string $feature The theme feature.
return apply_filters( "current_theme_supports-{$feature}", true, $args, $_wp_theme_features[ $feature ] ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
* Checks a theme's support for a given feature before loading the functions which implement it.
* @param string $feature The feature being checked. See add_theme_support() for the list
* @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, $file ) {
if ( current_theme_supports( $feature ) ) {
* Registers a theme feature for use in add_theme_support().
* This does not indicate that the active theme supports the feature, it only describes
* the feature's supported options.
* @see add_theme_support()
* @global array $_wp_registered_theme_features
* @param string $feature The name uniquely identifying the feature. See add_theme_support()
* for the list of possible values.
* Data used to describe the theme.
* @type string $type The type of data associated with this feature.
* Valid values are 'string', 'boolean', 'integer',
* 'number', 'array', and 'object'. Defaults to 'boolean'.
* @type bool $variadic Does this feature utilize the variadic support
* of add_theme_support(), or are all arguments specified
* as the second parameter. Must be used with the "array" type.
* @type string $description A short description of the feature. Included in
* the Themes REST API schema. Intended for developers.
* @type bool|array $show_in_rest {
* Whether this feature should be included in the Themes REST API endpoint.
* Defaults to not being included. When registering an 'array' or 'object' type,
* this argument must be an array with the 'schema' key.
* @type array $schema Specifies the JSON Schema definition describing
* the feature. If any objects in the schema do not include
* the 'additionalProperties' keyword, it is set to false.
* @type string $name An alternate name to be used as the property name
* @type callable $prepare_callback A function used to format the theme support in the REST API.
* Receives the raw theme support value.
* @return true|WP_Error True if the theme feature was successfully registered, a WP_Error object if not.
function register_theme_feature( $feature, $args = array() ) {
global $_wp_registered_theme_features;
if ( ! is_array( $_wp_registered_theme_features ) ) {
$_wp_registered_theme_features = array();
$args = wp_parse_args( $args, $defaults );
if ( true === $args['show_in_rest'] ) {
$args['show_in_rest'] = array();
if ( is_array( $args['show_in_rest'] ) ) {
$args['show_in_rest'] = wp_parse_args(
'prepare_callback' => null,
if ( ! in_array( $args['type'], array( 'string', 'boolean', 'integer', 'number', 'array', 'object' ), true ) ) {
__( 'The feature "type" is not valid JSON Schema type.' )
if ( true === $args['variadic'] && 'array' !== $args['type'] ) {
'variadic_must_be_array',
__( 'When registering a "variadic" theme feature, the "type" must be an "array".' )
if ( false !== $args['show_in_rest'] && in_array( $args['type'], array( 'array', 'object' ), true ) ) {
if ( ! is_array( $args['show_in_rest'] ) || empty( $args['show_in_rest']['schema'] ) ) {
__( 'When registering an "array" or "object" feature to show in the REST API, the feature\'s schema must also be defined.' )
if ( 'array' === $args['type'] && ! isset( $args['show_in_rest']['schema']['items'] ) ) {
__( 'When registering an "array" feature, the feature\'s schema must include the "items" keyword.' )
if ( 'object' === $args['type'] && ! isset( $args['show_in_rest']['schema']['properties'] ) ) {
'missing_schema_properties',
__( 'When registering an "object" feature, the feature\'s schema must include the "properties" keyword.' )
if ( is_array( $args['show_in_rest'] ) ) {
if ( isset( $args['show_in_rest']['prepare_callback'] )
&& ! is_callable( $args['show_in_rest']['prepare_callback'] )
'invalid_rest_prepare_callback',
/* translators: %s: prepare_callback */
__( 'The "%s" must be a callable function.' ),
$args['show_in_rest']['schema'] = wp_parse_args(
$args['show_in_rest']['schema'],
'description' => $args['description'],
if ( is_bool( $args['show_in_rest']['schema']['default'] )
&& ! in_array( 'boolean', (array) $args['show_in_rest']['schema']['type'], true )
// Automatically include the "boolean" type when the default value is a boolean.
$args['show_in_rest']['schema']['type'] = (array) $args['show_in_rest']['schema']['type'];
array_unshift( $args['show_in_rest']['schema']['type'], 'boolean' );
$args['show_in_rest']['schema'] = rest_default_additional_properties_to_false( $args['show_in_rest']['schema'] );
$_wp_registered_theme_features[ $feature ] = $args;
* Gets the list of registered theme features.
* @global array $_wp_registered_theme_features
* @return array[] List of theme features, keyed by their name.
function get_registered_theme_features() {
global $_wp_registered_theme_features;
if ( ! is_array( $_wp_registered_theme_features ) ) {
return $_wp_registered_theme_features;
* Gets the registration config for a theme feature.
* @global array $_wp_registered_theme_features
* @param string $feature The feature name. See add_theme_support() for the list
* @return array|null The registration args, or null if the feature was not registered.
function get_registered_theme_feature( $feature ) {
global $_wp_registered_theme_features;
if ( ! is_array( $_wp_registered_theme_features ) ) {
return isset( $_wp_registered_theme_features[ $feature ] ) ? $_wp_registered_theme_features[ $feature ] : null;
* Checks an attachment being deleted to see if it's a header or background image.
* If true it removes the theme modification which would be pointing at the deleted
* @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.
function _delete_attachment_theme_mod( $id ) {
$attachment_image = wp_get_attachment_url( $id );
$header_image = get_header_image();
$background_image = get_background_image();
$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 ( $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 ) {
remove_theme_mod( 'background_image' );
* Checks if a theme has been changed and runs 'after_switch_theme' hook on the next WP load.
* See {@see 'after_switch_theme'}.
function check_theme_switched() {
$stylesheet = get_option( 'theme_switched' );
$old_theme = wp_get_theme( $stylesheet );
// Prevent widget & menu mapping from running since Customizer already called it up front.
if ( get_option( 'theme_switched_via_customizer' ) ) {
remove_action( 'after_switch_theme', '_wp_menus_changed' );
remove_action( 'after_switch_theme', '_wp_sidebars_changed' );
update_option( 'theme_switched_via_customizer', false );
if ( $old_theme->exists() ) {
* Fires on the next WP load after the theme has been switched.
* 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
* See {@see 'switch_theme'}.