: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( empty( $api_root ) ) {
printf( '<link rel="https://api.w.org/" href="%s" />', esc_url( $api_root ) );
$resource = rest_get_queried_resource_route();
'<link rel="alternate" title="%1$s" type="application/json" href="%2$s" />',
_x( 'JSON', 'REST API resource link name' ),
esc_url( rest_url( $resource ) )
* Sends a Link header for the REST API.
function rest_output_link_header() {
$api_root = get_rest_url();
if ( empty( $api_root ) ) {
header( sprintf( 'Link: <%s>; rel="https://api.w.org/"', sanitize_url( $api_root ) ), false );
$resource = rest_get_queried_resource_route();
'Link: <%1$s>; rel="alternate"; title="%2$s"; type="application/json"',
sanitize_url( rest_url( $resource ) ),
_x( 'JSON', 'REST API resource link name' )
* Checks for errors when using cookie-based authentication.
* WordPress' built-in cookie authentication is always active
* for logged in users. However, the API has to check nonces
* for each request to ensure users are not vulnerable to CSRF.
* @global mixed $wp_rest_auth_cookie
* @param WP_Error|mixed $result Error from another authentication handler,
* null if we should handle it, or another value if not.
* @return WP_Error|mixed|bool WP_Error if the cookie is invalid, the $result, otherwise true.
function rest_cookie_check_errors( $result ) {
if ( ! empty( $result ) ) {
global $wp_rest_auth_cookie;
* Is cookie authentication being used? (If we get an auth
* error, but we're still logged in, another authentication
if ( true !== $wp_rest_auth_cookie && is_user_logged_in() ) {
// Determine if there is a nonce.
if ( isset( $_REQUEST['_wpnonce'] ) ) {
$nonce = $_REQUEST['_wpnonce'];
} elseif ( isset( $_SERVER['HTTP_X_WP_NONCE'] ) ) {
$nonce = $_SERVER['HTTP_X_WP_NONCE'];
// No nonce at all, so act as if it's an unauthenticated request.
wp_set_current_user( 0 );
$result = wp_verify_nonce( $nonce, 'wp_rest' );
add_filter( 'rest_send_nocache_headers', '__return_true', 20 );
return new WP_Error( 'rest_cookie_invalid_nonce', __( 'Cookie check failed' ), array( 'status' => 403 ) );
// Send a refreshed nonce in header.
rest_get_server()->send_header( 'X-WP-Nonce', wp_create_nonce( 'wp_rest' ) );
* Collects cookie authentication status.
* Collects errors from wp_validate_auth_cookie for use by rest_cookie_check_errors.
* @global mixed $wp_rest_auth_cookie
function rest_cookie_collect_status() {
global $wp_rest_auth_cookie;
$status_type = current_action();
if ( 'auth_cookie_valid' !== $status_type ) {
$wp_rest_auth_cookie = substr( $status_type, 12 );
$wp_rest_auth_cookie = true;
* Collects the status of authenticating with an application password.
* @since 5.7.0 Added the `$app_password` parameter.
* @global WP_User|WP_Error|null $wp_rest_application_password_status
* @global string|null $wp_rest_application_password_uuid
* @param WP_Error $user_or_error The authenticated user or error instance.
* @param array $app_password The Application Password used to authenticate.
function rest_application_password_collect_status( $user_or_error, $app_password = array() ) {
global $wp_rest_application_password_status, $wp_rest_application_password_uuid;
$wp_rest_application_password_status = $user_or_error;
if ( empty( $app_password['uuid'] ) ) {
$wp_rest_application_password_uuid = null;
$wp_rest_application_password_uuid = $app_password['uuid'];
* Gets the Application Password used for authenticating the request.
* @global string|null $wp_rest_application_password_uuid
* @return string|null The Application Password UUID, or null if Application Passwords was not used.
function rest_get_authenticated_app_password() {
global $wp_rest_application_password_uuid;
return $wp_rest_application_password_uuid;
* Checks for errors when using application password-based authentication.
* @global WP_User|WP_Error|null $wp_rest_application_password_status
* @param WP_Error|null|true $result Error from another authentication handler,
* null if we should handle it, or another value if not.
* @return WP_Error|null|true WP_Error if the application password is invalid, the $result, otherwise true.
function rest_application_password_check_errors( $result ) {
global $wp_rest_application_password_status;
if ( ! empty( $result ) ) {
if ( is_wp_error( $wp_rest_application_password_status ) ) {
$data = $wp_rest_application_password_status->get_error_data();
if ( ! isset( $data['status'] ) ) {
$wp_rest_application_password_status->add_data( $data );
return $wp_rest_application_password_status;
if ( $wp_rest_application_password_status instanceof WP_User ) {
* Adds Application Passwords info to the REST API index.
* @param WP_REST_Response $response The index response object.
* @return WP_REST_Response
function rest_add_application_passwords_to_index( $response ) {
if ( ! wp_is_application_passwords_available() ) {
$response->data['authentication']['application-passwords'] = array(
'authorization' => admin_url( 'authorize-application.php' ),
* Retrieves the avatar URLs in various sizes.
* @param mixed $id_or_email The avatar to retrieve a URL for. Accepts a user ID, Gravatar MD5 hash,
* user email, WP_User object, WP_Post object, or WP_Comment object.
* @return (string|false)[] Avatar URLs keyed by size. Each value can be a URL string or boolean false.
function rest_get_avatar_urls( $id_or_email ) {
$avatar_sizes = rest_get_avatar_sizes();
foreach ( $avatar_sizes as $size ) {
$urls[ $size ] = get_avatar_url( $id_or_email, array( 'size' => $size ) );
* Retrieves the pixel sizes for avatars.
* @return int[] List of pixel sizes for avatars. Default `[ 24, 48, 96 ]`.
function rest_get_avatar_sizes() {
* Filters the REST avatar sizes.
* Use this filter to adjust the array of sizes returned by the
* `rest_get_avatar_sizes` function.
* @param int[] $sizes An array of int values that are the pixel sizes for avatars.
* Default `[ 24, 48, 96 ]`.
return apply_filters( 'rest_avatar_sizes', array( 24, 48, 96 ) );
* Parses an RFC3339 time into a Unix timestamp.
* @param string $date RFC3339 timestamp.
* @param bool $force_utc Optional. Whether to force UTC timezone instead of using
* the timestamp's timezone. Default false.
* @return int|false Unix timestamp on success, false on failure.
function rest_parse_date( $date, $force_utc = false ) {
$date = preg_replace( '/[+-]\d+:?\d+$/', '+00:00', $date );
$regex = '#^\d{4}-\d{2}-\d{2}[Tt ]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}(?::\d{2})?)?$#';
if ( ! preg_match( $regex, $date, $matches ) ) {
return strtotime( $date );
* Parses a 3 or 6 digit hex color (with #).
* @param string $color 3 or 6 digit hex color (with #).
* @return string|false Color value on success, false on failure.
function rest_parse_hex_color( $color ) {
$regex = '|^#([A-Fa-f0-9]{3}){1,2}$|';
if ( ! preg_match( $regex, $color, $matches ) ) {
* Parses a date into both its local and UTC equivalent, in MySQL datetime format.
* @param string $date RFC3339 timestamp.
* @param bool $is_utc Whether the provided date should be interpreted as UTC. Default false.
* Local and UTC datetime strings, in MySQL datetime format (Y-m-d H:i:s),
* @type string $0 Local datetime string.
* @type string $1 UTC datetime string.
function rest_get_date_with_gmt( $date, $is_utc = false ) {
* Whether or not the original date actually has a timezone string
* changes the way we need to do timezone conversion.
* Store this info before parsing the date, and use it later.
$has_timezone = preg_match( '#(Z|[+-]\d{2}(:\d{2})?)$#', $date );
$date = rest_parse_date( $date );
* At this point $date could either be a local date (if we were passed
* a *local* date without a timezone offset) or a UTC date (otherwise).
* Timezone conversion needs to be handled differently between these two cases.
if ( ! $is_utc && ! $has_timezone ) {
$local = gmdate( 'Y-m-d H:i:s', $date );
$utc = get_gmt_from_date( $local );
$utc = gmdate( 'Y-m-d H:i:s', $date );
$local = get_date_from_gmt( $utc );
return array( $local, $utc );
* Returns a contextual HTTP error code for authorization failure.
* @return int 401 if the user is not logged in, 403 if the user is logged in.
function rest_authorization_required_code() {
return is_user_logged_in() ? 403 : 401;
* Validate a request argument based on details registered to the route.
* @param WP_REST_Request $request
function rest_validate_request_arg( $value, $request, $param ) {
$attributes = $request->get_attributes();
if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) {
$args = $attributes['args'][ $param ];
return rest_validate_value_from_schema( $value, $args, $param );
* Sanitize a request argument based on details registered to the route.
* @param WP_REST_Request $request
function rest_sanitize_request_arg( $value, $request, $param ) {
$attributes = $request->get_attributes();
if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) {
$args = $attributes['args'][ $param ];
return rest_sanitize_value_from_schema( $value, $args, $param );
* Parse a request argument based on details registered to the route.
* Runs a validation check and sanitizes the value, primarily to be used via
* the `sanitize_callback` arguments in the endpoint args registration.
* @param WP_REST_Request $request
function rest_parse_request_arg( $value, $request, $param ) {
$is_valid = rest_validate_request_arg( $value, $request, $param );
if ( is_wp_error( $is_valid ) ) {
$value = rest_sanitize_request_arg( $value, $request, $param );
* Determines if an IP address is valid.
* Handles both IPv4 and IPv6 addresses.
* @param string $ip IP address.
* @return string|false The valid IP address, otherwise false.
function rest_is_ip_address( $ip ) {
$ipv4_pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/';
if ( ! preg_match( $ipv4_pattern, $ip ) && ! WpOrg\Requests\Ipv6::check_ipv6( $ip ) ) {
* Changes a boolean-like value into the proper boolean value.
* @param bool|string|int $value The value being evaluated.
* @return bool Returns the proper associated boolean value.
function rest_sanitize_boolean( $value ) {
// String values are translated to `true`; make sure 'false' is false.
if ( is_string( $value ) ) {
$value = strtolower( $value );
if ( in_array( $value, array( 'false', '0' ), true ) ) {
// Everything else will map nicely to boolean.
* Determines if a given value is boolean-like.
* @param bool|string $maybe_bool The value being evaluated.
* @return bool True if a boolean, otherwise false.
function rest_is_boolean( $maybe_bool ) {
if ( is_bool( $maybe_bool ) ) {
if ( is_string( $maybe_bool ) ) {
$maybe_bool = strtolower( $maybe_bool );
$valid_boolean_values = array(