// Check the element type, so that we're only recursing if we really have to.
if ( is_array( $el ) || is_object( $el ) ) {
$output[ $clean_id ] = _wp_json_sanity_check( $el, $depth - 1 );
} elseif ( is_string( $el ) ) {
$output[ $clean_id ] = _wp_json_convert_string( $el );
$output[ $clean_id ] = $el;
} elseif ( is_object( $data ) ) {
foreach ( $data as $id => $el ) {
if ( is_string( $id ) ) {
$clean_id = _wp_json_convert_string( $id );
if ( is_array( $el ) || is_object( $el ) ) {
$output->$clean_id = _wp_json_sanity_check( $el, $depth - 1 );
} elseif ( is_string( $el ) ) {
$output->$clean_id = _wp_json_convert_string( $el );
$output->$clean_id = $el;
} elseif ( is_string( $data ) ) {
return _wp_json_convert_string( $data );
* Convert a string to UTF-8, so that it can be safely encoded to JSON.
* @see _wp_json_sanity_check()
* @param string $string The string which is to be converted.
* @return string The checked string.
function _wp_json_convert_string( $string ) {
if ( is_null( $use_mb ) ) {
$use_mb = function_exists( 'mb_convert_encoding' );
$encoding = mb_detect_encoding( $string, mb_detect_order(), true );
return mb_convert_encoding( $string, 'UTF-8', $encoding );
return mb_convert_encoding( $string, 'UTF-8', 'UTF-8' );
return wp_check_invalid_utf8( $string, true );
* Prepares response data to be serialized to JSON.
* This supports the JsonSerializable interface for PHP 5.2-5.3 as well.
* @deprecated 5.3.0 This function is no longer needed as support for PHP 5.2-5.3
* @param mixed $data Native representation.
* @return bool|int|float|null|string|array Data ready for `json_encode()`.
function _wp_json_prepare_data( $data ) {
_deprecated_function( __FUNCTION__, '5.3.0' );
* Send a JSON response back to an Ajax request.
* @since 4.7.0 The `$status_code` parameter was added.
* @since 5.6.0 The `$options` parameter was added.
* @param mixed $response Variable (usually an array or object) to encode as JSON,
* @param int $status_code Optional. The HTTP status code to output. Default null.
* @param int $options Optional. Options to be passed to json_encode(). Default 0.
function wp_send_json( $response, $status_code = null, $options = 0 ) {
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
/* translators: 1: WP_REST_Response, 2: WP_Error */
__( 'Return a %1$s or %2$s object from your callback when using the REST API.' ),
if ( ! headers_sent() ) {
header( 'Content-Type: application/json; charset=' . get_option( 'blog_charset' ) );
if ( null !== $status_code ) {
status_header( $status_code );
echo wp_json_encode( $response, $options );
* Send a JSON response back to an Ajax request, indicating success.
* @since 4.7.0 The `$status_code` parameter was added.
* @since 5.6.0 The `$options` parameter was added.
* @param mixed $data Optional. Data to encode as JSON, then print and die. Default null.
* @param int $status_code Optional. The HTTP status code to output. Default null.
* @param int $options Optional. Options to be passed to json_encode(). Default 0.
function wp_send_json_success( $data = null, $status_code = null, $options = 0 ) {
$response = array( 'success' => true );
$response['data'] = $data;
wp_send_json( $response, $status_code, $options );
* Send a JSON response back to an Ajax request, indicating failure.
* If the `$data` parameter is a WP_Error object, the errors
* within the object are processed and output as an array of error
* codes and corresponding messages. All other types are output
* without further processing.
* @since 4.1.0 The `$data` parameter is now processed if a WP_Error object is passed in.
* @since 4.7.0 The `$status_code` parameter was added.
* @since 5.6.0 The `$options` parameter was added.
* @param mixed $data Optional. Data to encode as JSON, then print and die. Default null.
* @param int $status_code Optional. The HTTP status code to output. Default null.
* @param int $options Optional. Options to be passed to json_encode(). Default 0.
function wp_send_json_error( $data = null, $status_code = null, $options = 0 ) {
$response = array( 'success' => false );
if ( is_wp_error( $data ) ) {
foreach ( $data->errors as $code => $messages ) {
foreach ( $messages as $message ) {
$response['data'] = $result;
$response['data'] = $data;
wp_send_json( $response, $status_code, $options );
* Checks that a JSONP callback is a valid JavaScript callback name.
* Only allows alphanumeric characters and the dot character in callback
* function names. This helps to mitigate XSS attacks caused by directly
* @param string $callback Supplied JSONP callback function name.
* @return bool Whether the callback function name is valid.
function wp_check_jsonp_callback( $callback ) {
if ( ! is_string( $callback ) ) {
preg_replace( '/[^\w\.]/', '', $callback, -1, $illegal_char_count );
return 0 === $illegal_char_count;
* Retrieve the WordPress home page URL.
* If the constant named 'WP_HOME' exists, then it will be used and returned
* by the function. This can be used to counter the redirection on your local
* development environment.
* @param string $url URL for the home location.
* @return string Homepage location.
function _config_wp_home( $url = '' ) {
if ( defined( 'WP_HOME' ) ) {
return untrailingslashit( WP_HOME );
* Retrieve the WordPress site URL.
* If the constant named 'WP_SITEURL' is defined, then the value in that
* constant will always be returned. This can be used for debugging a site
* on your localhost while not having to change the database to your URL.
* @param string $url URL to set the WordPress site location.
* @return string The WordPress Site URL.
function _config_wp_siteurl( $url = '' ) {
if ( defined( 'WP_SITEURL' ) ) {
return untrailingslashit( WP_SITEURL );
* Delete the fresh site option.
function _delete_option_fresh_site() {
update_option( 'fresh_site', '0' );
* Set the localized direction for MCE plugin.
* Will only set the direction to 'rtl', if the WordPress locale has
* the text direction set to 'rtl'.
* Fills in the 'directionality' setting, enables the 'directionality'
* plugin, and adds the 'ltr' button to 'toolbar1', formerly
* 'theme_advanced_buttons1' array keys. These keys are then returned
* in the $mce_init (TinyMCE settings) array.
* @param array $mce_init MCE settings array.
* @return array Direction set for 'rtl', if needed by locale.
function _mce_set_direction( $mce_init ) {
$mce_init['directionality'] = 'rtl';
$mce_init['rtl_ui'] = true;
if ( ! empty( $mce_init['plugins'] ) && strpos( $mce_init['plugins'], 'directionality' ) === false ) {
$mce_init['plugins'] .= ',directionality';
if ( ! empty( $mce_init['toolbar1'] ) && ! preg_match( '/\bltr\b/', $mce_init['toolbar1'] ) ) {
$mce_init['toolbar1'] .= ',ltr';
* Convert smiley code to the icon graphic file equivalent.
* You can turn off smilies, by going to the write setting screen and unchecking
* the box, or by setting 'use_smilies' option to false or removing the option.
* Plugins may override the default smiley list by setting the $wpsmiliestrans
* to an array, with the key the code the blogger types in and the value the
* The $wp_smiliessearch global is for the regular expression and is set each
* time the function is called.
* The full list of smilies can be found in the function and won't be listed in
* the description. Probably should create a Codex page for it, so that it is
* @global array $wpsmiliestrans
* @global array $wp_smiliessearch
function smilies_init() {
global $wpsmiliestrans, $wp_smiliessearch;
// Don't bother setting up smilies if they are disabled.
if ( ! get_option( 'use_smilies' ) ) {
if ( ! isset( $wpsmiliestrans ) ) {
':mrgreen:' => 'mrgreen.png',
':neutral:' => "\xf0\x9f\x98\x90",
':twisted:' => "\xf0\x9f\x98\x88",
':arrow:' => "\xe2\x9e\xa1",
':shock:' => "\xf0\x9f\x98\xaf",
':smile:' => "\xf0\x9f\x99\x82",
':???:' => "\xf0\x9f\x98\x95",
':cool:' => "\xf0\x9f\x98\x8e",
':evil:' => "\xf0\x9f\x91\xbf",
':grin:' => "\xf0\x9f\x98\x80",
':idea:' => "\xf0\x9f\x92\xa1",
':oops:' => "\xf0\x9f\x98\xb3",
':razz:' => "\xf0\x9f\x98\x9b",
':roll:' => "\xf0\x9f\x99\x84",
':wink:' => "\xf0\x9f\x98\x89",
':cry:' => "\xf0\x9f\x98\xa5",
':eek:' => "\xf0\x9f\x98\xae",
':lol:' => "\xf0\x9f\x98\x86",
':mad:' => "\xf0\x9f\x98\xa1",
':sad:' => "\xf0\x9f\x99\x81",
'8-)' => "\xf0\x9f\x98\x8e",
'8-O' => "\xf0\x9f\x98\xaf",
':-(' => "\xf0\x9f\x99\x81",
':-)' => "\xf0\x9f\x99\x82",
':-?' => "\xf0\x9f\x98\x95",
':-D' => "\xf0\x9f\x98\x80",
':-P' => "\xf0\x9f\x98\x9b",
':-o' => "\xf0\x9f\x98\xae",
':-x' => "\xf0\x9f\x98\xa1",
':-|' => "\xf0\x9f\x98\x90",
';-)' => "\xf0\x9f\x98\x89",
// This one transformation breaks regular text with frequency.
// '8)' => "\xf0\x9f\x98\x8e",
'8O' => "\xf0\x9f\x98\xaf",
':(' => "\xf0\x9f\x99\x81",
':)' => "\xf0\x9f\x99\x82",
':?' => "\xf0\x9f\x98\x95",
':D' => "\xf0\x9f\x98\x80",
':P' => "\xf0\x9f\x98\x9b",
':o' => "\xf0\x9f\x98\xae",
':x' => "\xf0\x9f\x98\xa1",
':|' => "\xf0\x9f\x98\x90",
';)' => "\xf0\x9f\x98\x89",
* Filters all the smilies.
* This filter must be added before `smilies_init` is run, as
* it is normally only run once to setup the smilies regex.
* @param string[] $wpsmiliestrans List of the smilies' hexadecimal representations, keyed by their smily code.
$wpsmiliestrans = apply_filters( 'smilies', $wpsmiliestrans );
if ( count( $wpsmiliestrans ) == 0 ) {
* NOTE: we sort the smilies in reverse key order. This is to make sure
* we match the longest possible smilie (:???: vs :?) as the regular
* expression used below is first-match
krsort( $wpsmiliestrans );
$spaces = wp_spaces_regexp();
// Begin first "subpattern".
$wp_smiliessearch = '/(?<=' . $spaces . '|^)';
foreach ( (array) $wpsmiliestrans as $smiley => $img ) {
$firstchar = substr( $smiley, 0, 1 );
$rest = substr( $smiley, 1 );
if ( $firstchar != $subchar ) {
$wp_smiliessearch .= ')(?=' . $spaces . '|$)'; // End previous "subpattern".
$wp_smiliessearch .= '|(?<=' . $spaces . '|^)'; // Begin another "subpattern".
$wp_smiliessearch .= preg_quote( $firstchar, '/' ) . '(?:';
$wp_smiliessearch .= '|';
$wp_smiliessearch .= preg_quote( $rest, '/' );
$wp_smiliessearch .= ')(?=' . $spaces . '|$)/m';
* Merges user defined arguments into defaults array.
* This function is used throughout WordPress to allow for both string or array
* to be merged into another array.
* @since 2.3.0 `$args` can now also be an object.
* @param string|array|object $args Value to merge with $defaults.
* @param array $defaults Optional. Array that serves as the defaults.
* @return array Merged user defined values with defaults.
function wp_parse_args( $args, $defaults = array() ) {
if ( is_object( $args ) ) {
$parsed_args = get_object_vars( $args );
} elseif ( is_array( $args ) ) {
wp_parse_str( $args, $parsed_args );
if ( is_array( $defaults ) && $defaults ) {
return array_merge( $defaults, $parsed_args );
* Converts a comma- or space-separated list of scalar values to an array.
* @param array|string $list List of values.
* @return array Array of values.
function wp_parse_list( $list ) {
if ( ! is_array( $list ) ) {
return preg_split( '/[\s,]+/', $list, -1, PREG_SPLIT_NO_EMPTY );
* Cleans up an array, comma- or space-separated list of IDs.
* @param array|string $list List of IDs.
* @return int[] Sanitized array of IDs.
function wp_parse_id_list( $list ) {
$list = wp_parse_list( $list );
return array_unique( array_map( 'absint', $list ) );
* Cleans up an array, comma- or space-separated list of slugs.