: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* theme.json. `file:./` is the placeholder which is replaced by
* the theme's URL path to the theme's root.
* @param array $src Webfont file(s) `src`.
* @return array Webfont's `src` in URI.
$fn_transform_src_into_uri = static function( array $src ) {
foreach ( $src as $key => $url ) {
// Tweak the URL to be relative to the theme root.
if ( ! str_starts_with( $url, 'file:./' ) ) {
$src[ $key ] = get_theme_file_uri( str_replace( 'file:./', '', $url ) );
* Converts the font-face properties (i.e. keys) into kebab-case.
* @param array $font_face Font face to convert.
* @return array Font faces with each property in kebab-case format.
$fn_convert_keys_to_kebab_case = static function( array $font_face ) {
foreach ( $font_face as $property => $value ) {
$kebab_case = _wp_to_kebab_case( $property );
$font_face[ $kebab_case ] = $value;
if ( $kebab_case !== $property ) {
unset( $font_face[ $property ] );
* @param array $webfont The webfont arguments.
* @return array|false The validated webfont arguments, or false if the webfont is invalid.
$fn_validate_webfont = static function( $webfont ) {
$webfont = wp_parse_args(
'font-style' => 'normal',
'font-display' => 'fallback',
// Check the font-family.
if ( empty( $webfont['font-family'] ) || ! is_string( $webfont['font-family'] ) ) {
trigger_error( __( 'Webfont font family must be a non-empty string.' ) );
// Check that the `src` property is defined and a valid type.
if ( empty( $webfont['src'] ) || ( ! is_string( $webfont['src'] ) && ! is_array( $webfont['src'] ) ) ) {
trigger_error( __( 'Webfont src must be a non-empty string or an array of strings.' ) );
// Validate the `src` property.
foreach ( (array) $webfont['src'] as $src ) {
if ( ! is_string( $src ) || '' === trim( $src ) ) {
trigger_error( __( 'Each webfont src must be a non-empty string.' ) );
// Check the font-weight.
if ( ! is_string( $webfont['font-weight'] ) && ! is_int( $webfont['font-weight'] ) ) {
trigger_error( __( 'Webfont font weight must be a properly formatted string or integer.' ) );
// Check the font-display.
if ( ! in_array( $webfont['font-display'], array( 'auto', 'block', 'fallback', 'optional', 'swap' ), true ) ) {
$webfont['font-display'] = 'fallback';
'font-variation-settings',
foreach ( $webfont as $prop => $value ) {
if ( ! in_array( $prop, $valid_props, true ) ) {
unset( $webfont[ $prop ] );
* Registers webfonts declared in theme.json.
* @uses $registered_webfonts To access and update the registered webfonts registry (passed by reference).
* @uses $fn_get_webfonts_from_theme_json To run the function that gets the webfonts from theme.json.
* @uses $fn_convert_keys_to_kebab_case To run the function that converts keys into kebab-case.
* @uses $fn_validate_webfont To run the function that validates each font-face (webfont) from theme.json.
$fn_register_webfonts = static function() use ( &$registered_webfonts, $fn_get_webfonts_from_theme_json, $fn_convert_keys_to_kebab_case, $fn_validate_webfont, $fn_transform_src_into_uri ) {
$registered_webfonts = array();
foreach ( $fn_get_webfonts_from_theme_json() as $webfont ) {
if ( ! is_array( $webfont ) ) {
$webfont = $fn_convert_keys_to_kebab_case( $webfont );
$webfont = $fn_validate_webfont( $webfont );
$webfont['src'] = $fn_transform_src_into_uri( (array) $webfont['src'] );
if ( empty( $webfont ) ) {
$registered_webfonts[] = $webfont;
* Orders 'src' items to optimize for browser support.
* @param array $webfont Webfont to process.
* @return array Ordered `src` items.
$fn_order_src = static function( array $webfont ) {
foreach ( $webfont['src'] as $url ) {
if ( str_starts_with( trim( $url ), 'data:' ) ) {
$format = pathinfo( $url, PATHINFO_EXTENSION );
if ( ! empty( $src['woff2'] ) ) {
'url' => sanitize_url( $src['woff2'] ),
if ( ! empty( $src['woff'] ) ) {
'url' => sanitize_url( $src['woff'] ),
if ( ! empty( $src['ttf'] ) ) {
'url' => sanitize_url( $src['ttf'] ),
if ( ! empty( $src['eot'] ) ) {
'url' => sanitize_url( $src['eot'] ),
'format' => 'embedded-opentype',
if ( ! empty( $src['otf'] ) ) {
'url' => sanitize_url( $src['otf'] ),
$webfont['src'] = $src_ordered;
* Compiles the 'src' into valid CSS.
* @since 6.2.0 Removed local() CSS.
* @param string $font_family Font family.
* @param array $value Value to process.
* @return string The CSS.
$fn_compile_src = static function( $font_family, array $value ) {
foreach ( $value as $item ) {
$src .= ( 'data' === $item['format'] )
? ", url({$item['url']})"
: ", url('{$item['url']}') format('{$item['format']}')";
$src = ltrim( $src, ', ' );
* Compiles the font variation settings.
* @param array $font_variation_settings Array of font variation settings.
* @return string The CSS.
$fn_compile_variations = static function( array $font_variation_settings ) {
foreach ( $font_variation_settings as $key => $value ) {
$variations .= "$key $value";
* Builds the font-family's CSS.
* @uses $fn_compile_src To run the function that compiles the src.
* @uses $fn_compile_variations To run the function that compiles the variations.
* @param array $webfont Webfont to process.
* @return string This font-family's CSS.
$fn_build_font_face_css = static function( array $webfont ) use ( $fn_compile_src, $fn_compile_variations ) {
// Wrap font-family in quotes if it contains spaces.
str_contains( $webfont['font-family'], ' ' ) &&
! str_contains( $webfont['font-family'], '"' ) &&
! str_contains( $webfont['font-family'], "'" )
$webfont['font-family'] = '"' . $webfont['font-family'] . '"';
foreach ( $webfont as $key => $value ) {
* Skip "provider", since it's for internal API use,
* and not a valid CSS property.
if ( 'provider' === $key ) {
// Compile the "src" parameter.
$value = $fn_compile_src( $webfont['font-family'], $value );
// If font-variation-settings is an array, convert it to a string.
if ( 'font-variation-settings' === $key && is_array( $value ) ) {
$value = $fn_compile_variations( $value );
if ( ! empty( $value ) ) {
* Gets the '@font-face' CSS styles for locally-hosted font files.
* @uses $registered_webfonts To access and update the registered webfonts registry (passed by reference).
* @uses $fn_order_src To run the function that orders the src.
* @uses $fn_build_font_face_css To run the function that builds the font-face CSS.
* @return string The `@font-face` CSS.
$fn_get_css = static function() use ( &$registered_webfonts, $fn_order_src, $fn_build_font_face_css ) {
foreach ( $registered_webfonts as $webfont ) {
// Order the webfont's `src` items to optimize for browser support.
$webfont = $fn_order_src( $webfont );
// Build the @font-face CSS for this webfont.
$css .= '@font-face{' . $fn_build_font_face_css( $webfont ) . '}';
* Generates and enqueues webfonts styles.
* @uses $fn_get_css To run the function that gets the CSS.
$fn_generate_and_enqueue_styles = static function() use ( $fn_get_css ) {
// Bail out if there are no styles to enqueue.
// Enqueue the stylesheet.
wp_register_style( 'wp-webfonts', '' );
wp_enqueue_style( 'wp-webfonts' );
// Add the styles to the stylesheet.
wp_add_inline_style( 'wp-webfonts', $styles );
* Generates and enqueues editor styles.
* @uses $fn_get_css To run the function that gets the CSS.
$fn_generate_and_enqueue_editor_styles = static function() use ( $fn_get_css ) {
// Bail out if there are no styles to enqueue.
wp_add_inline_style( 'wp-block-library', $styles );
add_action( 'wp_loaded', $fn_register_webfonts );
add_action( 'wp_enqueue_scripts', $fn_generate_and_enqueue_styles );
add_action( 'admin_init', $fn_generate_and_enqueue_editor_styles );
* Prints the CSS in the embed iframe header.
* @deprecated 6.4.0 Use wp_enqueue_embed_styles() instead.
function print_embed_styles() {
_deprecated_function( __FUNCTION__, '6.4.0', 'wp_enqueue_embed_styles' );
$type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"';
$suffix = SCRIPT_DEBUG ? '' : '.min';
<style<?php echo $type_attr; ?>>
<?php echo file_get_contents( ABSPATH . WPINC . "/css/wp-embed-template$suffix.css" ); ?>
* Prints the important emoji-related styles.
* @deprecated 6.4.0 Use wp_enqueue_emoji_styles() instead.
function print_emoji_styles() {
_deprecated_function( __FUNCTION__, '6.4.0', 'wp_enqueue_emoji_styles' );
$type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"';
<style<?php echo $type_attr; ?>>
display: inline !important;
box-shadow: none !important;
margin: 0 0.07em !important;
vertical-align: -0.1em !important;
background: none !important;
* Prints style and scripts for the admin bar.
* @deprecated 6.4.0 Use wp_enqueue_admin_bar_header_styles() instead.
function wp_admin_bar_header() {
_deprecated_function( __FUNCTION__, '6.4.0', 'wp_enqueue_admin_bar_header_styles' );
$type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"';
<style<?php echo $type_attr; ?> media="print">#wpadminbar { display:none; }</style>
* Prints default admin bar callback.
* @deprecated 6.4.0 Use wp_enqueue_admin_bar_bump_styles() instead.
function _admin_bar_bump_cb() {
_deprecated_function( __FUNCTION__, '6.4.0', 'wp_enqueue_admin_bar_bump_styles' );
$type_attr = current_theme_supports( 'html5', 'style' ) ? '' : ' type="text/css"';
<style<?php echo $type_attr; ?> media="screen">
html { margin-top: 32px !important; }
@media screen and ( max-width: 782px ) {
html { margin-top: 46px !important; }
* Runs a remote HTTPS request to detect whether HTTPS supported, and stores potential errors.
* This internal function is called by a regular Cron hook to ensure HTTPS support is detected and maintained.
* @deprecated 6.4.0 The `wp_update_https_detection_errors()` function is no longer used and has been replaced by
* `wp_get_https_detection_errors()`. Previously the function was called by a regular Cron hook to
* update the `https_detection_errors` option, but this is no longer necessary as the errors are
* retrieved directly in Site Health and no longer used outside of Site Health.
function wp_update_https_detection_errors() {
_deprecated_function( __FUNCTION__, '6.4.0' );
* Short-circuits the process of detecting errors related to HTTPS support.
* Returning a `WP_Error` from the filter will effectively short-circuit the default logic of trying a remote
* request to the site over HTTPS, storing the errors array from the returned `WP_Error` instead.
* @deprecated 6.4.0 The `wp_update_https_detection_errors` filter is no longer used and has been replaced by `pre_wp_get_https_detection_errors`.
* @param null|WP_Error $pre Error object to short-circuit detection,