: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$content[ $type ][ $sidebar_id ][] = $widget;
} elseif ( is_string( $widget )
&& ! empty( $core_content[ $type ] )
&& ! empty( $core_content[ $type ][ $widget ] )
$content[ $type ][ $sidebar_id ][] = $core_content[ $type ][ $widget ];
// And nav menu items are grouped into nav menus.
foreach ( $config[ $type ] as $nav_menu_location => $nav_menu ) {
// Ensure nav menus get a name.
if ( empty( $nav_menu['name'] ) ) {
$nav_menu['name'] = $nav_menu_location;
$content[ $type ][ $nav_menu_location ]['name'] = $nav_menu['name'];
foreach ( $nav_menu['items'] as $id => $nav_menu_item ) {
if ( is_array( $nav_menu_item ) ) {
// Item extends core content.
if ( ! empty( $core_content[ $type ][ $id ] ) ) {
$nav_menu_item = array_merge( $core_content[ $type ][ $id ], $nav_menu_item );
$content[ $type ][ $nav_menu_location ]['items'][] = $nav_menu_item;
} elseif ( is_string( $nav_menu_item )
&& ! empty( $core_content[ $type ] )
&& ! empty( $core_content[ $type ][ $nav_menu_item ] )
$content[ $type ][ $nav_menu_location ]['items'][] = $core_content[ $type ][ $nav_menu_item ];
// Attachments are posts but have special treatment.
foreach ( $config[ $type ] as $id => $item ) {
if ( ! empty( $item['file'] ) ) {
$content[ $type ][ $id ] = $item;
* All that's left now are posts (besides attachments).
* Not a default case for the sake of clarity and future work.
foreach ( $config[ $type ] as $id => $item ) {
if ( is_array( $item ) ) {
// Item extends core content.
if ( ! empty( $core_content[ $type ][ $id ] ) ) {
$item = array_merge( $core_content[ $type ][ $id ], $item );
// Enforce a subset of fields.
$content[ $type ][ $id ] = wp_array_slice_assoc(
} elseif ( is_string( $item ) && ! empty( $core_content[ $type ][ $item ] ) ) {
$content[ $type ][ $item ] = $core_content[ $type ][ $item ];
* Filters the expanded array of starter content.
* @param array $content Array of starter content.
* @param array $config Array of theme-specific starter content configuration.
return apply_filters( 'get_theme_starter_content', $content, $config );
* Registers theme support for a given feature.
* Must be called in the theme's functions.php file to work.
* If attached to a hook, it must be {@see 'after_setup_theme'}.
* The {@see 'init'} hook may be too late for some features.
* add_theme_support( 'title-tag' );
* add_theme_support( 'custom-logo', array(
* @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.
* @since 4.7.0 The `starter-content` feature was added.
* @since 5.0.0 The `responsive-embeds`, `align-wide`, `dark-editor-style`, `disable-custom-colors`,
* `disable-custom-font-sizes`, `editor-color-palette`, `editor-font-sizes`,
* `editor-styles`, and `wp-block-styles` features were added.
* @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 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:
* - 'automatic-feed-links'
* - 'block-template-parts'
* - 'core-block-patterns'
* - 'customize-selective-refresh-widgets'
* - 'disable-custom-colors'
* - 'disable-custom-font-sizes'
* - 'disable-custom-gradients'
* - 'disable-layout-styles'
* - 'editor-color-palette'
* - 'editor-gradient-presets'
* - 'editor-spacing-sizes'
* - 'widgets-block-editor'
* @param mixed ...$args Optional extra arguments to pass along with certain features.
* @return void|false Void on success, false on failure.
function add_theme_support( $feature, ...$args ) {
global $_wp_theme_features;
// All post types are already supported.
if ( true === get_theme_support( 'post-thumbnails' ) ) {
* Merge post types with any that already declared their support
if ( isset( $args[0] ) && is_array( $args[0] ) && isset( $_wp_theme_features['post-thumbnails'] ) ) {
$args[0] = array_unique( array_merge( $_wp_theme_features['post-thumbnails'][0], $args[0] ) );
if ( isset( $args[0] ) && is_array( $args[0] ) ) {
$post_formats = get_post_format_slugs();
unset( $post_formats['standard'] );
$args[0] = array_intersect( $args[0], array_keys( $post_formats ) );
"add_theme_support( 'post-formats' )",
__( 'You need to pass an array of post formats.' ),
// You can't just pass 'html5', you need to pass an array of types.
if ( empty( $args[0] ) || ! is_array( $args[0] ) ) {
"add_theme_support( 'html5' )",
__( 'You need to pass an array of types.' ),
if ( ! empty( $args[0] ) && ! is_array( $args[0] ) ) {
// Build an array of types for back-compat.
$args = array( 0 => array( 'comment-list', 'comment-form', 'search-form' ) );
// Calling 'html5' again merges, rather than overwrites.
if ( isset( $_wp_theme_features['html5'] ) ) {
$args[0] = array_merge( $_wp_theme_features['html5'][0], $args[0] );
$args = array( 0 => array() );
'unlink-homepage-logo' => false,
$args[0] = wp_parse_args( array_intersect_key( $args[0], $defaults ), $defaults );
// Allow full flexibility if no size is specified.
if ( is_null( $args[0]['width'] ) && is_null( $args[0]['height'] ) ) {
$args[0]['flex-width'] = true;
$args[0]['flex-height'] = true;
case 'custom-header-uploads':
return add_theme_support( 'custom-header', array( 'uploads' => true ) );
$args = array( 0 => array() );
'random-default' => false,
'default-text-color' => '',
'wp-head-callback' => '',
'admin-head-callback' => '',
'admin-preview-callback' => '',
'video-active-callback' => 'is_front_page',
$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.)
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.
$args[0] = wp_parse_args( $args[0], $defaults );
* If a constant was defined, use that value. Otherwise, define the constant to ensure
* 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 should be avoided. Don't reference them. This is just for backward compatibility.
if ( defined( 'NO_HEADER_TEXT' ) ) {
$args[0]['header-text'] = ! NO_HEADER_TEXT;
} elseif ( isset( $args[0]['header-text'] ) ) {
define( 'NO_HEADER_TEXT', empty( $args[0]['header-text'] ) );
if ( defined( 'HEADER_IMAGE_WIDTH' ) ) {
$args[0]['width'] = (int) HEADER_IMAGE_WIDTH;
} elseif ( isset( $args[0]['width'] ) ) {
define( 'HEADER_IMAGE_WIDTH', (int) $args[0]['width'] );
if ( defined( 'HEADER_IMAGE_HEIGHT' ) ) {
$args[0]['height'] = (int) HEADER_IMAGE_HEIGHT;
} elseif ( isset( $args[0]['height'] ) ) {
define( 'HEADER_IMAGE_HEIGHT', (int) $args[0]['height'] );
if ( defined( 'HEADER_TEXTCOLOR' ) ) {
$args[0]['default-text-color'] = HEADER_TEXTCOLOR;
} elseif ( isset( $args[0]['default-text-color'] ) ) {
define( 'HEADER_TEXTCOLOR', $args[0]['default-text-color'] );
if ( defined( 'HEADER_IMAGE' ) ) {
$args[0]['default-image'] = HEADER_IMAGE;
} elseif ( isset( $args[0]['default-image'] ) ) {
define( 'HEADER_IMAGE', $args[0]['default-image'] );
if ( $jit && ! empty( $args[0]['default-image'] ) ) {
$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 ( empty( $args[0]['width'] ) && empty( $args[0]['flex-width'] ) ) {
$args[0]['flex-width'] = true;
if ( empty( $args[0]['height'] ) && empty( $args[0]['flex-height'] ) ) {
$args[0]['flex-height'] = true;
case 'custom-background':
$args = array( 0 => array() );
'default-preset' => 'default',
'default-position-x' => 'left',
'default-position-y' => 'top',
'default-size' => 'auto',
'default-repeat' => 'repeat',
'default-attachment' => 'scroll',
'wp-head-callback' => '_custom_background_cb',
'admin-head-callback' => '',
'admin-preview-callback' => '',
$jit = isset( $args[0]['__jit'] );
unset( $args[0]['__jit'] );
// Merge in data from previous add_theme_support() calls. The first value registered wins.
if ( isset( $_wp_theme_features['custom-background'] ) ) {
$args[0] = wp_parse_args( $_wp_theme_features['custom-background'][0], $args[0] );
$args[0] = wp_parse_args( $args[0], $defaults );
if ( defined( 'BACKGROUND_COLOR' ) ) {
$args[0]['default-color'] = BACKGROUND_COLOR;
} elseif ( isset( $args[0]['default-color'] ) || $jit ) {
define( 'BACKGROUND_COLOR', $args[0]['default-color'] );
if ( defined( 'BACKGROUND_IMAGE' ) ) {
$args[0]['default-image'] = BACKGROUND_IMAGE;
} elseif ( isset( $args[0]['default-image'] ) || $jit ) {
define( 'BACKGROUND_IMAGE', $args[0]['default-image'] );
// Ensure that 'title-tag' is accessible in the admin.
// Can be called in functions.php but must happen before wp_loaded, i.e. not in header.php.
if ( did_action( 'wp_loaded' ) ) {
"add_theme_support( 'title-tag' )",
/* translators: 1: title-tag, 2: wp_loaded */
__( 'Theme support for %1$s should be registered before the %2$s hook.' ),
'<code>title-tag</code>',
$_wp_theme_features[ $feature ] = $args;
* Registers the internal custom header and background routines.
* @global Custom_Image_Header $custom_image_header
* @global Custom_Background $custom_background
function _custom_header_background_just_in_time() {
global $custom_image_header, $custom_background;
if ( current_theme_supports( 'custom-header' ) ) {
// In case any constants were defined after an add_custom_image_header() call, re-run.
add_theme_support( 'custom-header', array( '__jit' => true ) );
$args = get_theme_support( 'custom-header' );
if ( $args[0]['wp-head-callback'] ) {
add_action( 'wp_head', $args[0]['wp-head-callback'] );
require_once ABSPATH . 'wp-admin/includes/class-custom-image-header.php';
$custom_image_header = new Custom_Image_Header( $args[0]['admin-head-callback'], $args[0]['admin-preview-callback'] );
if ( current_theme_supports( 'custom-background' ) ) {
// In case any constants were defined after an add_custom_background() call, re-run.
add_theme_support( 'custom-background', array( '__jit' => true ) );
$args = get_theme_support( 'custom-background' );
add_action( 'wp_head', $args[0]['wp-head-callback'] );
require_once ABSPATH . 'wp-admin/includes/class-custom-background.php';
$custom_background = new Custom_Background( $args[0]['admin-head-callback'], $args[0]['admin-preview-callback'] );
* Adds CSS to hide header text for custom logo, based on Customizer setting.
function _custom_logo_header_styles() {
if ( ! current_theme_supports( 'custom-header', 'header-text' )
&& get_theme_support( 'custom-logo', 'header-text' )
&& ! get_theme_mod( 'header_text', true )
$classes = (array) get_theme_support( 'custom-logo', 'header-text' );
$classes = array_map( 'sanitize_html_class', $classes );
$classes = '.' . implode( ', .', $classes );
$type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"';
<!-- Custom Logo: hide header text -->