: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
$value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value );
if ( is_wp_error( $value ) ) {
$error = $value->get_error_message();
if ( ! is_array( $value ) ) {
$value = explode( ' ', $value );
$value = array_values( array_filter( array_map( 'trim', $value ) ) );
case 'limited_email_domains':
case 'banned_email_domains':
$value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value );
if ( is_wp_error( $value ) ) {
$error = $value->get_error_message();
if ( ! is_array( $value ) ) {
$value = explode( "\n", $value );
$domains = array_values( array_filter( array_map( 'trim', $value ) ) );
foreach ( $domains as $domain ) {
if ( ! preg_match( '/(--|\.\.)/', $domain ) && preg_match( '|^([a-zA-Z0-9-\.])+$|', $domain ) ) {
$allowed_zones = timezone_identifiers_list( DateTimeZone::ALL_WITH_BC );
if ( ! in_array( $value, $allowed_zones, true ) && ! empty( $value ) ) {
$error = __( 'The timezone you have entered is not valid. Please select a valid timezone.' );
case 'permalink_structure':
$value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value );
if ( is_wp_error( $value ) ) {
$error = $value->get_error_message();
$value = sanitize_url( $value );
$value = str_replace( 'http://', '', $value );
if ( 'permalink_structure' === $option && null === $error
&& '' !== $value && ! preg_match( '/%[^\/%]+%/', $value )
/* translators: %s: Documentation URL. */
__( 'A structure tag is required when using custom permalinks. <a href="%s">Learn more</a>' ),
__( 'https://wordpress.org/documentation/article/customize-permalinks/#choosing-your-permalink-structure' )
if ( ! get_role( $value ) && get_role( 'subscriber' ) ) {
$value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value );
if ( is_wp_error( $value ) ) {
$error = $value->get_error_message();
$value = explode( "\n", $value );
$value = array_filter( array_map( 'trim', $value ) );
$value = array_unique( $value );
$value = implode( "\n", $value );
if ( '' === $error && is_wp_error( $value ) ) {
/* translators: 1: Option name, 2: Error code. */
$error = sprintf( __( 'Could not sanitize the %1$s option. Error code: %2$s' ), $option, $value->get_error_code() );
$value = get_option( $option );
if ( function_exists( 'add_settings_error' ) ) {
add_settings_error( $option, "invalid_{$option}", $error );
* Filters an option value following sanitization.
* @since 4.3.0 Added the `$original_value` parameter.
* @param mixed $value The sanitized option value.
* @param string $option The option name.
* @param mixed $original_value The original value passed to the function.
return apply_filters( "sanitize_option_{$option}", $value, $option, $original_value );
* Maps a function to all non-iterable elements of an array or an object.
* This is similar to `array_walk_recursive()` but acts upon objects too.
* @param mixed $value The array, object, or scalar.
* @param callable $callback The function to map onto $value.
* @return mixed The value with the callback applied to all non-arrays and non-objects inside it.
function map_deep( $value, $callback ) {
if ( is_array( $value ) ) {
foreach ( $value as $index => $item ) {
$value[ $index ] = map_deep( $item, $callback );
} elseif ( is_object( $value ) ) {
$object_vars = get_object_vars( $value );
foreach ( $object_vars as $property_name => $property_value ) {
$value->$property_name = map_deep( $property_value, $callback );
$value = call_user_func( $callback, $value );
* Parses a string into variables to be stored in an array.
* @param string $input_string The string to be parsed.
* @param array $result Variables will be stored in this array.
function wp_parse_str( $input_string, &$result ) {
parse_str( (string) $input_string, $result );
* Filters the array of variables derived from a parsed string.
* @param array $result The array populated with variables.
$result = apply_filters( 'wp_parse_str', $result );
* Converts lone less than signs.
* KSES already converts lone greater than signs.
* @param string $content Text to be converted.
* @return string Converted text.
function wp_pre_kses_less_than( $content ) {
return preg_replace_callback( '%<[^>]*?((?=<)|>|$)%', 'wp_pre_kses_less_than_callback', $content );
* Callback function used by preg_replace.
* @param string[] $matches Populated by matches to preg_replace.
* @return string The text returned after esc_html if needed.
function wp_pre_kses_less_than_callback( $matches ) {
if ( ! str_contains( $matches[0], '>' ) ) {
return esc_html( $matches[0] );
* Removes non-allowable HTML from parsed block attribute values when filtering
* @param string $content Content to be run through KSES.
* @param array[]|string $allowed_html An array of allowed HTML elements
* and attributes, or a context name
* @param string[] $allowed_protocols Array of allowed URL protocols.
* @return string Filtered text to run through KSES.
function wp_pre_kses_block_attributes( $content, $allowed_html, $allowed_protocols ) {
* `filter_block_content` is expected to call `wp_kses`. Temporarily remove
* the filter to avoid recursion.
remove_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10 );
$content = filter_block_content( $content, $allowed_html, $allowed_protocols );
add_filter( 'pre_kses', 'wp_pre_kses_block_attributes', 10, 3 );
* WordPress' implementation of PHP sprintf() with filters.
* @since 5.3.0 Formalized the existing and already documented `...$args` parameter
* by adding it to the function signature.
* @link https://www.php.net/sprintf
* @param string $pattern The string which formatted args are inserted.
* @param mixed ...$args Arguments to be formatted into the $pattern string.
* @return string The formatted string.
function wp_sprintf( $pattern, ...$args ) {
$len = strlen( $pattern );
while ( $len > $start ) {
// Last character: append and break.
if ( strlen( $pattern ) - 1 === $start ) {
$result .= substr( $pattern, -1 );
// Literal %: append and continue.
if ( '%%' === substr( $pattern, $start, 2 ) ) {
// Get fragment before next %.
$end = strpos( $pattern, '%', $start + 1 );
$fragment = substr( $pattern, $start, $end - $start );
// Fragment has a specifier.
if ( '%' === $pattern[ $start ] ) {
// Find numbered arguments or take the next one in order.
if ( preg_match( '/^%(\d+)\$/', $fragment, $matches ) ) {
$index = $matches[1] - 1; // 0-based array vs 1-based sprintf() arguments.
$arg = isset( $args[ $index ] ) ? $args[ $index ] : '';
$fragment = str_replace( "%{$matches[1]}$", '%', $fragment );
$arg = isset( $args[ $arg_index ] ) ? $args[ $arg_index ] : '';
* Filters a fragment from the pattern passed to wp_sprintf().
* If the fragment is unchanged, then sprintf() will be run on the fragment.
* @param string $fragment A fragment from the pattern.
* @param string $arg The argument.
$_fragment = apply_filters( 'wp_sprintf', $fragment, $arg );
if ( $_fragment !== $fragment ) {
$fragment = sprintf( $fragment, (string) $arg );
// Append to result and move to next fragment.
* Localizes list items before the rest of the content.
* The '%l' must be at the first characters can then contain the rest of the
* content. The list items will have ', ', ', and', and ' and ' added depending
* on the amount of list items in the $args parameter.
* @param string $pattern Content containing '%l' at the beginning.
* @param array $args List items to prepend to the content and replace '%l'.
* @return string Localized list items and rest of the content.
function wp_sprintf_l( $pattern, $args ) {
if ( ! str_starts_with( $pattern, '%l' ) ) {
* Filters the translated delimiters used by wp_sprintf_l().
* Placeholders (%s) are included to assist translators and then
* removed before the array of strings reaches the filter.
* Please note: Ampersands and entities should be avoided here.
* @param array $delimiters An array of translated delimiters.
/* translators: Used to join items in a list with more than 2 items. */
'between' => sprintf( __( '%1$s, %2$s' ), '', '' ),
/* translators: Used to join last two items in a list with more than 2 times. */
'between_last_two' => sprintf( __( '%1$s, and %2$s' ), '', '' ),
/* translators: Used to join items in a list with only 2 items. */
'between_only_two' => sprintf( __( '%1$s and %2$s' ), '', '' ),
$result = array_shift( $args );
if ( count( $args ) === 1 ) {
$result .= $l['between_only_two'] . array_shift( $args );
// Loop when more than two args.
$arg = array_shift( $args );
$result .= $l['between_last_two'] . $arg;
$result .= $l['between'] . $arg;
return $result . substr( $pattern, 2 );
* Safely extracts not more than the first $count characters from HTML string.
* UTF-8, tags and entities safe prefix extraction. Entities inside will *NOT*
* be counted as one character. For example & will be counted as 4, < as
* @param string $str String to get the excerpt from.
* @param int $count Maximum number of characters to take.
* @param string $more Optional. What to append if $str needs to be trimmed. Defaults to empty string.
* @return string The excerpt.
function wp_html_excerpt( $str, $count, $more = null ) {
$str = wp_strip_all_tags( $str, true );
$excerpt = mb_substr( $str, 0, $count );
// Remove part of an entity at the end.
$excerpt = preg_replace( '/&[^;\s]{0,6}$/', '', $excerpt );
if ( $str !== $excerpt ) {
$excerpt = trim( $excerpt ) . $more;
* Adds a base URL to relative links in passed content.
* By default, this function supports the 'src' and 'href' attributes.
* However, this can be modified via the `$attrs` parameter.
* @global string $_links_add_base
* @param string $content String to search for links in.
* @param string $base The base URL to prefix to links.
* @param array $attrs The attributes which should be processed.
* @return string The processed content.
function links_add_base_url( $content, $base, $attrs = array( 'src', 'href' ) ) {
$_links_add_base = $base;
$attrs = implode( '|', (array) $attrs );
return preg_replace_callback( "!($attrs)=(['\"])(.+?)\\2!i", '_links_add_base', $content );
* Callback to add a base URL to relative links in passed content.
* @global string $_links_add_base
* @param string $m The matched link.
* @return string The processed link.
function _links_add_base( $m ) {
// 1 = attribute name 2 = quotation mark 3 = URL.
return $m[1] . '=' . $m[2] .
( preg_match( '#^(\w{1,20}):#', $m[3], $protocol ) && in_array( $protocol[1], wp_allowed_protocols(), true ) ?
WP_Http::make_absolute_url( $m[3], $_links_add_base )
* Adds a target attribute to all links in passed content.
* By default, this function only applies to `<a>` tags.
* However, this can be modified via the `$tags` parameter.
* *NOTE:* Any current target attribute will be stripped and replaced.
* @global string $_links_add_target
* @param string $content String to search for links in.
* @param string $target The target to add to the links.
* @param string[] $tags An array of tags to apply to.
* @return string The processed content.
function links_add_target( $content, $target = '_blank', $tags = array( 'a' ) ) {
global $_links_add_target;
$_links_add_target = $target;
$tags = implode( '|', (array) $tags );
return preg_replace_callback( "!<($tags)((\s[^>]*)?)>!i", '_links_add_target', $content );
* Callback to add a target attribute to all links in passed content.
* @global string $_links_add_target
* @param string $m The matched link.
* @return string The processed link.
function _links_add_target( $m ) {
global $_links_add_target;
$link = preg_replace( '|( target=([\'"])(.*?)\2)|i', '', $m[2] );
return '<' . $tag . $link . ' target="' . esc_attr( $_links_add_target ) . '">';
* Normalizes EOL characters and strips duplicate whitespace.
* @param string $str The string to normalize.
* @return string The normalized string.
function normalize_whitespace( $str ) {
$str = str_replace( "\r", "\n", $str );
$str = preg_replace( array( '/\n+/', '/[ \t]+/' ), array( "\n", ' ' ), $str );