WordPress.org

Make WordPress Core

Ticket #38531: 38531.3.diff

File 38531.3.diff, 15.5 KB (added by rachelbaker, 5 years ago)

Removed var_dump() uses and fixed typo in the header of tests/phpunit/tests/rest-api/rest-schema-validation.php

  • src/wp-includes/rest-api/endpoints/class-wp-rest-controller.php

     
    559559                                $endpoint_args[ $field_id ]['required'] = true;
    560560                        }
    561561
    562                         foreach ( array( 'type', 'format', 'enum' ) as $schema_prop ) {
     562                        foreach ( array( 'type', 'format', 'enum', 'items' ) as $schema_prop ) {
    563563                                if ( isset( $params[ $schema_prop ] ) ) {
    564564                                        $endpoint_args[ $field_id ][ $schema_prop ] = $params[ $schema_prop ];
    565565                                }
  • src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php

     
    19711971                        $schema['properties'][ $base ] = array(
    19721972                                'description' => sprintf( __( 'The terms assigned to the object in the %s taxonomy.' ), $taxonomy->name ),
    19731973                                'type'        => 'array',
     1974                                'items'       => array(
     1975                                        'type'    => 'integer',
     1976                                ),
    19741977                                'context'     => array( 'view', 'edit' ),
    19751978                        );
    19761979                        $schema['properties'][ $base . '_exclude' ] = array(
  • src/wp-includes/rest-api/endpoints/class-wp-rest-settings-controller.php

     
    288288
    289289                foreach ( $options as $option_name => $option ) {
    290290                        $schema['properties'][ $option_name ] = $option['schema'];
     291                        $schema['properties'][ $option_name ]['arg_options'] = array(
     292                                'sanitize_callback' => array( $this, 'sanitize_callback' ),
     293                        );
    291294                }
    292295
    293296                return $this->add_additional_fields_schema( $schema );
    294297        }
     298
     299        /**
     300         * Custom sanitize callback used for all options to allow the use of 'null'.
     301         *
     302         * By default, the schema of settings will throw an error if a value is set to
     303         * `null` as it's not a valid value for something like "type => string". We
     304         * provide a wrapper sanitizer to whitelist the use of `null`.
     305         *
     306         * @param  mixed           $value   The value for the setting.
     307         * @param  WP_REST_Request $request The request object.
     308         * @param  string          $param   The parameter name.
     309         * @return mixed|WP_Error
     310         */
     311        public function sanitize_callback( $value, $request, $param ) {
     312                if ( is_null( $value ) ) {
     313                        return $value;
     314                }
     315                return rest_parse_request_arg( $value, $request, $param );
     316        }
    295317}
  • src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php

     
    10061006                                'roles'           => array(
    10071007                                        'description' => __( 'Roles assigned to the resource.' ),
    10081008                                        'type'        => 'array',
     1009                                        'items'       => array(
     1010                                                'type'    => 'string',
     1011                                        ),
    10091012                                        'context'     => array( 'edit' ),
    10101013                                ),
    10111014                                'password'        => array(
  • src/wp-includes/rest-api.php

     
    820820        }
    821821        $args = $attributes['args'][ $param ];
    822822
    823         if ( ! empty( $args['enum'] ) ) {
    824                 if ( ! in_array( $value, $args['enum'], true ) ) {
    825                         return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: list of valid values */ __( '%1$s is not one of %2$s.' ), $param, implode( ', ', $args['enum'] ) ) );
    826                 }
    827         }
    828 
    829         if ( 'integer' === $args['type'] && ! is_numeric( $value ) ) {
    830                 return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $param, 'integer' ) );
    831         }
    832 
    833         if ( 'boolean' === $args['type'] && ! rest_is_boolean( $value ) ) {
    834                 return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $value, 'boolean' ) );
    835         }
    836 
    837         if ( 'string' === $args['type'] && ! is_string( $value ) ) {
    838                 return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $param, 'string' ) );
    839         }
    840 
    841         if ( isset( $args['format'] ) ) {
    842                 switch ( $args['format'] ) {
    843                         case 'date-time' :
    844                                 if ( ! rest_parse_date( $value ) ) {
    845                                         return new WP_Error( 'rest_invalid_date', __( 'The date you provided is invalid.' ) );
    846                                 }
    847                                 break;
    848 
    849                         case 'email' :
    850                                 if ( ! is_email( $value ) ) {
    851                                         return new WP_Error( 'rest_invalid_email', __( 'The email address you provided is invalid.' ) );
    852                                 }
    853                                 break;
    854                         case 'ipv4' :
    855                                 if ( ! rest_is_ip_address( $value ) ) {
    856                                         return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.' ), $value ) );
    857                                 }
    858                                 break;
    859                 }
    860         }
    861 
    862         if ( in_array( $args['type'], array( 'numeric', 'integer' ), true ) && ( isset( $args['minimum'] ) || isset( $args['maximum'] ) ) ) {
    863                 if ( isset( $args['minimum'] ) && ! isset( $args['maximum'] ) ) {
    864                         if ( ! empty( $args['exclusiveMinimum'] ) && $value <= $args['minimum'] ) {
    865                                 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d (exclusive)' ), $param, $args['minimum'] ) );
    866                         } elseif ( empty( $args['exclusiveMinimum'] ) && $value < $args['minimum'] ) {
    867                                 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d (inclusive)' ), $param, $args['minimum'] ) );
    868                         }
    869                 } elseif ( isset( $args['maximum'] ) && ! isset( $args['minimum'] ) ) {
    870                         if ( ! empty( $args['exclusiveMaximum'] ) && $value >= $args['maximum'] ) {
    871                                 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d (exclusive)' ), $param, $args['maximum'] ) );
    872                         } elseif ( empty( $args['exclusiveMaximum'] ) && $value > $args['maximum'] ) {
    873                                 return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d (inclusive)' ), $param, $args['maximum'] ) );
    874                         }
    875                 } elseif ( isset( $args['maximum'] ) && isset( $args['minimum'] ) ) {
    876                         if ( ! empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
    877                                 if ( $value >= $args['maximum'] || $value <= $args['minimum'] ) {
    878                                         return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (exclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
    879                                 }
    880                         } elseif ( empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
    881                                 if ( $value >= $args['maximum'] || $value < $args['minimum'] ) {
    882                                         return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (inclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
    883                                 }
    884                         } elseif ( ! empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
    885                                 if ( $value > $args['maximum'] || $value <= $args['minimum'] ) {
    886                                         return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (exclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
    887                                 }
    888                         } elseif ( empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
    889                                 if ( $value > $args['maximum'] || $value < $args['minimum'] ) {
    890                                         return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (inclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
    891                                 }
    892                         }
    893                 }
    894         }
    895 
    896         return true;
     823        return rest_validate_value_from_schema( $value, $args, $param );
    897824}
    898825
    899826/**
     
    913840        }
    914841        $args = $attributes['args'][ $param ];
    915842
    916         if ( 'integer' === $args['type'] ) {
    917                 return (int) $value;
    918         }
    919 
    920         if ( 'boolean' === $args['type'] ) {
    921                 return rest_sanitize_boolean( $value );
    922         }
    923 
    924         if ( isset( $args['format'] ) ) {
    925                 switch ( $args['format'] ) {
    926                         case 'date-time' :
    927                                 return sanitize_text_field( $value );
    928 
    929                         case 'email' :
    930                                 /*
    931                                  * sanitize_email() validates, which would be unexpected
    932                                  */
    933                                 return sanitize_text_field( $value );
    934 
    935                         case 'uri' :
    936                                 return esc_url_raw( $value );
    937 
    938                         case 'ipv4' :
    939                                 return sanitize_text_field( $value );
    940                 }
    941         }
    942 
    943         return $value;
     843        return rest_sanitize_value_from_schema( $value, $args, $param );
    944844}
    945845
    946846/**
     
    1084984         */
    1085985        return apply_filters( 'rest_avatar_sizes', array( 24, 48, 96 ) );
    1086986}
     987
     988/**
     989 * Validate a value based on a schema.
     990 *
     991 * @param mixed  $value The value to validate.
     992 * @param array  $args  Schema array to use for validation.
     993 * @param string $param The parameter name, used in error messages.
     994 * @return true|WP_Error
     995 */
     996function rest_validate_value_from_schema( $value, $args, $param = '' ) {
     997        if ( 'array' === $args['type'] ) {
     998                if ( ! is_array( $value ) ) {
     999                        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $param, 'array' ) );
     1000                }
     1001                foreach ( $value as $index => $v ) {
     1002                        $is_valid = rest_validate_value_from_schema( $v, $args['items'], $param . '[' . $index . ']' );
     1003                        if ( is_wp_error( $is_valid ) ) {
     1004                                return $is_valid;
     1005                        }
     1006                }
     1007        }
     1008        if ( ! empty( $args['enum'] ) ) {
     1009                if ( ! in_array( $value, $args['enum'], true ) ) {
     1010                        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: list of valid values */ __( '%1$s is not one of %2$s.' ), $param, implode( ', ', $args['enum'] ) ) );
     1011                }
     1012        }
     1013
     1014        if ( in_array( $args['type'], array( 'integer', 'number' ) ) && ! is_numeric( $value ) ) {
     1015                return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $param, $args['type'] ) );
     1016        }
     1017
     1018        if ( 'integer' === $args['type'] && round( floatval( $value ) ) !== floatval( $value ) ) {
     1019                return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $param, 'integer' ) );
     1020        }
     1021
     1022        if ( 'boolean' === $args['type'] && ! rest_is_boolean( $value ) ) {
     1023                return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $value, 'boolean' ) );
     1024        }
     1025
     1026        if ( 'string' === $args['type'] && ! is_string( $value ) ) {
     1027                return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: type name */ __( '%1$s is not of type %2$s.' ), $param, 'string' ) );
     1028        }
     1029
     1030        if ( isset( $args['format'] ) ) {
     1031                switch ( $args['format'] ) {
     1032                        case 'date-time' :
     1033                                if ( ! rest_parse_date( $value ) ) {
     1034                                        return new WP_Error( 'rest_invalid_date', __( 'The date you provided is invalid.' ) );
     1035                                }
     1036                                break;
     1037
     1038                        case 'email' :
     1039                                if ( ! is_email( $value ) ) {
     1040                                        return new WP_Error( 'rest_invalid_email', __( 'The email address you provided is invalid.' ) );
     1041                                }
     1042                                break;
     1043                        case 'ipv4' :
     1044                                if ( ! rest_is_ip_address( $value ) ) {
     1045                                        return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.' ), $value ) );
     1046                                }
     1047                                break;
     1048                }
     1049        }
     1050
     1051        if ( in_array( $args['type'], array( 'number', 'integer' ), true ) && ( isset( $args['minimum'] ) || isset( $args['maximum'] ) ) ) {
     1052                if ( isset( $args['minimum'] ) && ! isset( $args['maximum'] ) ) {
     1053                        if ( ! empty( $args['exclusiveMinimum'] ) && $value <= $args['minimum'] ) {
     1054                                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d (exclusive)' ), $param, $args['minimum'] ) );
     1055                        } elseif ( empty( $args['exclusiveMinimum'] ) && $value < $args['minimum'] ) {
     1056                                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d (inclusive)' ), $param, $args['minimum'] ) );
     1057                        }
     1058                } elseif ( isset( $args['maximum'] ) && ! isset( $args['minimum'] ) ) {
     1059                        if ( ! empty( $args['exclusiveMaximum'] ) && $value >= $args['maximum'] ) {
     1060                                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d (exclusive)' ), $param, $args['maximum'] ) );
     1061                        } elseif ( empty( $args['exclusiveMaximum'] ) && $value > $args['maximum'] ) {
     1062                                return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d (inclusive)' ), $param, $args['maximum'] ) );
     1063                        }
     1064                } elseif ( isset( $args['maximum'] ) && isset( $args['minimum'] ) ) {
     1065                        if ( ! empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
     1066                                if ( $value >= $args['maximum'] || $value <= $args['minimum'] ) {
     1067                                        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (exclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
     1068                                }
     1069                        } elseif ( empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
     1070                                if ( $value >= $args['maximum'] || $value < $args['minimum'] ) {
     1071                                        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (inclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
     1072                                }
     1073                        } elseif ( ! empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
     1074                                if ( $value > $args['maximum'] || $value <= $args['minimum'] ) {
     1075                                        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (exclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
     1076                                }
     1077                        } elseif ( empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
     1078                                if ( $value > $args['maximum'] || $value < $args['minimum'] ) {
     1079                                        return new WP_Error( 'rest_invalid_param', sprintf( /* translators: 1: parameter, 2: minimum number, 3: maximum number */ __( '%1$s must be between %2$d (inclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
     1080                                }
     1081                        }
     1082                }
     1083        }
     1084
     1085        return true;
     1086}
     1087
     1088/**
     1089 * Sanitize a value based on a schema.
     1090 *
     1091 * @param mixed $value The value to sanitize.
     1092 * @param array $args  Schema array to use for sanitization.
     1093 * @return true|WP_Error
     1094 */
     1095function rest_sanitize_value_from_schema( $value, $args ) {
     1096        if ( 'array' === $args['type'] ) {
     1097                if ( empty( $args['items'] ) ) {
     1098                        return (array) $value;
     1099                }
     1100                foreach ( $value as $index => $v ) {
     1101                        $value[ $index ] = rest_sanitize_value_from_schema( $v, $args['items'] );
     1102                }
     1103                return $value;
     1104        }
     1105        if ( 'integer' === $args['type'] ) {
     1106                return (int) $value;
     1107        }
     1108
     1109        if ( 'number' === $args['type'] ) {
     1110                return (float) $value;
     1111        }
     1112
     1113        if ( 'boolean' === $args['type'] ) {
     1114                return rest_sanitize_boolean( $value );
     1115        }
     1116
     1117        if ( isset( $args['format'] ) ) {
     1118                switch ( $args['format'] ) {
     1119                        case 'date-time' :
     1120                                return sanitize_text_field( $value );
     1121
     1122                        case 'email' :
     1123                                /*
     1124                                 * sanitize_email() validates, which would be unexpected.
     1125                                 */
     1126                                return sanitize_text_field( $value );
     1127
     1128                        case 'uri' :
     1129                                return esc_url_raw( $value );
     1130
     1131                        case 'ipv4' :
     1132                                return sanitize_text_field( $value );
     1133                }
     1134        }
     1135
     1136        return $value;
     1137}