From b15c0d410ea5bda4ec09af7f105a755f9e31cd21 Mon Sep 17 00:00:00 2001 From: "K. Adam White" Date: Mon, 23 Sep 2019 17:25:57 +0000 Subject: [PATCH] REST API: Pass "null" as the post date property to reset post to initial "floating" date value. Props TimothyBlynJacobs, adamsilverstein, jnylen0, mnelson4. Fixes #44975. Built from https://develop.svn.wordpress.org/trunk@46249 git-svn-id: http://core.svn.wordpress.org/trunk@46061 1a063a9b-81f0-0310-95a4-ce76da25c4cd --- wp-includes/rest-api.php | 48 +++++++++++++++++++ .../rest-api/class-wp-rest-request.php | 24 ++++++++++ .../class-wp-rest-posts-controller.php | 14 +++++- wp-includes/version.php | 2 +- 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/wp-includes/rest-api.php b/wp-includes/rest-api.php index 8c809c89ba..a0bb8fba3a 100644 --- a/wp-includes/rest-api.php +++ b/wp-includes/rest-api.php @@ -1209,6 +1209,20 @@ function rest_get_avatar_sizes() { * @return true|WP_Error */ function rest_validate_value_from_schema( $value, $args, $param = '' ) { + if ( is_array( $args['type'] ) ) { + foreach ( $args['type'] as $type ) { + $type_args = $args; + $type_args['type'] = $type; + + if ( true === rest_validate_value_from_schema( $value, $type_args, $param ) ) { + return true; + } + } + + /* translators: 1: Parameter, 2: List of types. */ + return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s' ), $param, implode( ',', $args['type'] ) ) ); + } + if ( 'array' === $args['type'] ) { if ( ! is_null( $value ) ) { $value = wp_parse_list( $value ); @@ -1261,6 +1275,15 @@ function rest_validate_value_from_schema( $value, $args, $param = '' ) { } } + if ( 'null' === $args['type'] ) { + if ( null !== $value ) { + /* translators: 1: Parameter, 2: Type name. */ + return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'null' ) ); + } + + return true; + } + if ( ! empty( $args['enum'] ) ) { if ( ! in_array( $value, $args['enum'], true ) ) { /* translators: 1: Parameter, 2: List of valid values. */ @@ -1365,6 +1388,27 @@ function rest_validate_value_from_schema( $value, $args, $param = '' ) { * @return true|WP_Error */ function rest_sanitize_value_from_schema( $value, $args ) { + if ( is_array( $args['type'] ) ) { + // Determine which type the value was validated against, and use that type when performing sanitization + $validated_type = ''; + + foreach ( $args['type'] as $type ) { + $type_args = $args; + $type_args['type'] = $type; + + if ( ! is_wp_error( rest_validate_value_from_schema( $value, $type_args ) ) ) { + $validated_type = $type; + break; + } + } + + if ( ! $validated_type ) { + return null; + } + + $args['type'] = $validated_type; + } + if ( 'array' === $args['type'] ) { if ( empty( $args['items'] ) ) { return (array) $value; @@ -1407,6 +1451,10 @@ function rest_sanitize_value_from_schema( $value, $args ) { return $value; } + if ( 'null' === $args['type'] ) { + return null; + } + if ( 'integer' === $args['type'] ) { return (int) $value; } diff --git a/wp-includes/rest-api/class-wp-rest-request.php b/wp-includes/rest-api/class-wp-rest-request.php index 81a5564464..0910ff6f28 100644 --- a/wp-includes/rest-api/class-wp-rest-request.php +++ b/wp-includes/rest-api/class-wp-rest-request.php @@ -397,6 +397,30 @@ class WP_REST_Request implements ArrayAccess { return null; } + /** + * Checks if a parameter exists in the request. + * + * This allows distinguishing between an omitted parameter, + * and a parameter specifically set to null. + * + * @since 5.3.0 + * + * @param string $key Parameter name. + * + * @return bool True if a param exists for the given key. + */ + public function has_param( $key ) { + $order = $this->get_parameter_order(); + + foreach ( $order as $type ) { + if ( array_key_exists( $key, $this->params[ $type ] ) ) { + return true; + } + } + + return false; + } + /** * Sets a parameter on the request. * diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php index 883e9b31fe..b1e2836af2 100644 --- a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php +++ b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php @@ -1036,6 +1036,16 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { } } + // Sending a null date or date_gmt value resets date and date_gmt to their + // default values (`0000-00-00 00:00:00`). + if ( + ( ! empty( $schema['properties']['date_gmt'] ) && $request->has_param( 'date_gmt' ) && null === $request['date_gmt'] ) || + ( ! empty( $schema['properties']['date'] ) && $request->has_param( 'date' ) && null === $request['date'] ) + ) { + $prepared_post->post_date_gmt = null; + $prepared_post->post_date = null; + } + // Post slug. if ( ! empty( $schema['properties']['slug'] ) && isset( $request['slug'] ) ) { $prepared_post->post_name = $request['slug']; @@ -1891,13 +1901,13 @@ class WP_REST_Posts_Controller extends WP_REST_Controller { 'properties' => array( 'date' => array( 'description' => __( "The date the object was published, in the site's timezone." ), - 'type' => 'string', + 'type' => array( 'string', 'null' ), 'format' => 'date-time', 'context' => array( 'view', 'edit', 'embed' ), ), 'date_gmt' => array( 'description' => __( 'The date the object was published, as GMT.' ), - 'type' => 'string', + 'type' => array( 'string', 'null' ), 'format' => 'date-time', 'context' => array( 'view', 'edit' ), ), diff --git a/wp-includes/version.php b/wp-includes/version.php index d83f5bcc20..e8ed926479 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -13,7 +13,7 @@ * * @global string $wp_version */ -$wp_version = '5.3-alpha-46248'; +$wp_version = '5.3-alpha-46249'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.