wp/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php
changeset 18 be944660c56a
parent 16 a86126ab1dd4
child 21 48c4eec2b7e6
equal deleted inserted replaced
17:34716fd837a4 18:be944660c56a
    46 
    46 
    47 	/**
    47 	/**
    48 	 * Registers the meta field.
    48 	 * Registers the meta field.
    49 	 *
    49 	 *
    50 	 * @since 4.7.0
    50 	 * @since 4.7.0
       
    51 	 * @deprecated 5.6.0
    51 	 *
    52 	 *
    52 	 * @see register_rest_field()
    53 	 * @see register_rest_field()
    53 	 */
    54 	 */
    54 	public function register_field() {
    55 	public function register_field() {
       
    56 		_deprecated_function( __METHOD__, '5.6.0' );
       
    57 
    55 		register_rest_field(
    58 		register_rest_field(
    56 			$this->get_rest_field_type(),
    59 			$this->get_rest_field_type(),
    57 			'meta',
    60 			'meta',
    58 			array(
    61 			array(
    59 				'get_callback'    => array( $this, 'get_value' ),
    62 				'get_callback'    => array( $this, 'get_value' ),
    89 
    92 
    90 				$value = $this->prepare_value_for_response( $value, $request, $args );
    93 				$value = $this->prepare_value_for_response( $value, $request, $args );
    91 			} else {
    94 			} else {
    92 				$value = array();
    95 				$value = array();
    93 
    96 
    94 				foreach ( $all_values as $row ) {
    97 				if ( is_array( $all_values ) ) {
    95 					$value[] = $this->prepare_value_for_response( $row, $request, $args );
    98 					foreach ( $all_values as $row ) {
       
    99 						$value[] = $this->prepare_value_for_response( $row, $request, $args );
       
   100 					}
    96 				}
   101 				}
    97 			}
   102 			}
    98 
   103 
    99 			$response[ $name ] = $value;
   104 			$response[ $name ] = $value;
   100 		}
   105 		}
   140 			$name = $args['name'];
   145 			$name = $args['name'];
   141 			if ( ! array_key_exists( $name, $meta ) ) {
   146 			if ( ! array_key_exists( $name, $meta ) ) {
   142 				continue;
   147 				continue;
   143 			}
   148 			}
   144 
   149 
       
   150 			$value = $meta[ $name ];
       
   151 
   145 			/*
   152 			/*
   146 			 * A null value means reset the field, which is essentially deleting it
   153 			 * A null value means reset the field, which is essentially deleting it
   147 			 * from the database and then relying on the default value.
   154 			 * from the database and then relying on the default value.
       
   155 			 *
       
   156 			 * Non-single meta can also be removed by passing an empty array.
   148 			 */
   157 			 */
   149 			if ( is_null( $meta[ $name ] ) ) {
   158 			if ( is_null( $value ) || ( array() === $value && ! $args['single'] ) ) {
   150 				$args = $this->get_registered_fields()[ $meta_key ];
   159 				$args = $this->get_registered_fields()[ $meta_key ];
   151 
   160 
   152 				if ( $args['single'] ) {
   161 				if ( $args['single'] ) {
   153 					$current = get_metadata( $this->get_meta_type(), $object_id, $meta_key, true );
   162 					$current = get_metadata( $this->get_meta_type(), $object_id, $meta_key, true );
   154 
   163 
   167 					return $result;
   176 					return $result;
   168 				}
   177 				}
   169 				continue;
   178 				continue;
   170 			}
   179 			}
   171 
   180 
   172 			$value = $meta[ $name ];
       
   173 
       
   174 			if ( ! $args['single'] && is_array( $value ) && count( array_filter( $value, 'is_null' ) ) ) {
   181 			if ( ! $args['single'] && is_array( $value ) && count( array_filter( $value, 'is_null' ) ) ) {
   175 				return new WP_Error(
   182 				return new WP_Error(
   176 					'rest_invalid_stored_value',
   183 					'rest_invalid_stored_value',
   177 					/* translators: %s: Custom field key. */
   184 					/* translators: %s: Custom field key. */
   178 					sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ),
   185 					sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ),
   208 	 * @since 4.7.0
   215 	 * @since 4.7.0
   209 	 *
   216 	 *
   210 	 * @param int    $object_id Object ID the field belongs to.
   217 	 * @param int    $object_id Object ID the field belongs to.
   211 	 * @param string $meta_key  Key for the field.
   218 	 * @param string $meta_key  Key for the field.
   212 	 * @param string $name      Name for the field that is exposed in the REST API.
   219 	 * @param string $name      Name for the field that is exposed in the REST API.
   213 	 * @return bool|WP_Error True if meta field is deleted, WP_Error otherwise.
   220 	 * @return true|WP_Error True if meta field is deleted, WP_Error otherwise.
   214 	 */
   221 	 */
   215 	protected function delete_meta_value( $object_id, $meta_key, $name ) {
   222 	protected function delete_meta_value( $object_id, $meta_key, $name ) {
   216 		$meta_type = $this->get_meta_type();
   223 		$meta_type = $this->get_meta_type();
   217 
   224 
   218 		if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $meta_key ) ) {
   225 		if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $meta_key ) ) {
   225 					'status' => rest_authorization_required_code(),
   232 					'status' => rest_authorization_required_code(),
   226 				)
   233 				)
   227 			);
   234 			);
   228 		}
   235 		}
   229 
   236 
       
   237 		if ( null === get_metadata_raw( $meta_type, $object_id, wp_slash( $meta_key ) ) ) {
       
   238 			return true;
       
   239 		}
       
   240 
   230 		if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ) ) ) {
   241 		if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ) ) ) {
   231 			return new WP_Error(
   242 			return new WP_Error(
   232 				'rest_meta_database_error',
   243 				'rest_meta_database_error',
   233 				__( 'Could not delete meta value from database.' ),
   244 				__( 'Could not delete meta value from database.' ),
   234 				array(
   245 				array(
   250 	 *
   261 	 *
   251 	 * @param int    $object_id Object ID to update.
   262 	 * @param int    $object_id Object ID to update.
   252 	 * @param string $meta_key  Key for the custom field.
   263 	 * @param string $meta_key  Key for the custom field.
   253 	 * @param string $name      Name for the field that is exposed in the REST API.
   264 	 * @param string $name      Name for the field that is exposed in the REST API.
   254 	 * @param array  $values    List of values to update to.
   265 	 * @param array  $values    List of values to update to.
   255 	 * @return bool|WP_Error True if meta fields are updated, WP_Error otherwise.
   266 	 * @return true|WP_Error True if meta fields are updated, WP_Error otherwise.
   256 	 */
   267 	 */
   257 	protected function update_multi_meta_value( $object_id, $meta_key, $name, $values ) {
   268 	protected function update_multi_meta_value( $object_id, $meta_key, $name, $values ) {
   258 		$meta_type = $this->get_meta_type();
   269 		$meta_type = $this->get_meta_type();
   259 
   270 
   260 		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
   271 		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
   269 			);
   280 			);
   270 		}
   281 		}
   271 
   282 
   272 		$current_values = get_metadata( $meta_type, $object_id, $meta_key, false );
   283 		$current_values = get_metadata( $meta_type, $object_id, $meta_key, false );
   273 		$subtype        = get_object_subtype( $meta_type, $object_id );
   284 		$subtype        = get_object_subtype( $meta_type, $object_id );
       
   285 
       
   286 		if ( ! is_array( $current_values ) ) {
       
   287 			$current_values = array();
       
   288 		}
   274 
   289 
   275 		$to_remove = $current_values;
   290 		$to_remove = $current_values;
   276 		$to_add    = $values;
   291 		$to_add    = $values;
   277 
   292 
   278 		foreach ( $to_add as $add_key => $value ) {
   293 		foreach ( $to_add as $add_key => $value ) {
   345 	 *
   360 	 *
   346 	 * @param int    $object_id Object ID to update.
   361 	 * @param int    $object_id Object ID to update.
   347 	 * @param string $meta_key  Key for the custom field.
   362 	 * @param string $meta_key  Key for the custom field.
   348 	 * @param string $name      Name for the field that is exposed in the REST API.
   363 	 * @param string $name      Name for the field that is exposed in the REST API.
   349 	 * @param mixed  $value     Updated value.
   364 	 * @param mixed  $value     Updated value.
   350 	 * @return bool|WP_Error True if the meta field was updated, WP_Error otherwise.
   365 	 * @return true|WP_Error True if the meta field was updated, WP_Error otherwise.
   351 	 */
   366 	 */
   352 	protected function update_meta_value( $object_id, $meta_key, $name, $value ) {
   367 	protected function update_meta_value( $object_id, $meta_key, $name, $value ) {
   353 		$meta_type = $this->get_meta_type();
   368 		$meta_type = $this->get_meta_type();
   354 
   369 
   355 		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
   370 		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
   366 
   381 
   367 		// Do the exact same check for a duplicate value as in update_metadata() to avoid update_metadata() returning false.
   382 		// Do the exact same check for a duplicate value as in update_metadata() to avoid update_metadata() returning false.
   368 		$old_value = get_metadata( $meta_type, $object_id, $meta_key );
   383 		$old_value = get_metadata( $meta_type, $object_id, $meta_key );
   369 		$subtype   = get_object_subtype( $meta_type, $object_id );
   384 		$subtype   = get_object_subtype( $meta_type, $object_id );
   370 
   385 
   371 		if ( 1 === count( $old_value ) && $this->is_meta_value_same_as_stored_value( $meta_key, $subtype, $old_value[0], $value ) ) {
   386 		if ( is_array( $old_value ) && 1 === count( $old_value )
       
   387 			&& $this->is_meta_value_same_as_stored_value( $meta_key, $subtype, $old_value[0], $value )
       
   388 		) {
   372 			return true;
   389 			return true;
   373 		}
   390 		}
   374 
   391 
   375 		if ( ! update_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash_strings_only( $value ) ) ) {
   392 		if ( ! update_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
   376 			return new WP_Error(
   393 			return new WP_Error(
   377 				'rest_meta_database_error',
   394 				'rest_meta_database_error',
   378 				/* translators: %s: Custom field key. */
   395 				/* translators: %s: Custom field key. */
   379 				sprintf( __( 'Could not update the meta value of %s in database.' ), $meta_key ),
   396 				sprintf( __( 'Could not update the meta value of %s in database.' ), $meta_key ),
   380 				array(
   397 				array(
   461 
   478 
   462 			if ( null === $rest_args['schema']['default'] ) {
   479 			if ( null === $rest_args['schema']['default'] ) {
   463 				$rest_args['schema']['default'] = static::get_empty_value_for_type( $type );
   480 				$rest_args['schema']['default'] = static::get_empty_value_for_type( $type );
   464 			}
   481 			}
   465 
   482 
   466 			$rest_args['schema'] = $this->default_additional_properties_to_false( $rest_args['schema'] );
   483 			$rest_args['schema'] = rest_default_additional_properties_to_false( $rest_args['schema'] );
   467 
   484 
   468 			if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number', 'array', 'object' ), true ) ) {
   485 			if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number', 'array', 'object' ), true ) ) {
   469 				continue;
   486 				continue;
   470 			}
   487 			}
   471 
   488 
   566 	 * This is needed to restrict properties of objects in meta values to only
   583 	 * This is needed to restrict properties of objects in meta values to only
   567 	 * registered items, as the REST API will allow additional properties by
   584 	 * registered items, as the REST API will allow additional properties by
   568 	 * default.
   585 	 * default.
   569 	 *
   586 	 *
   570 	 * @since 5.3.0
   587 	 * @since 5.3.0
       
   588 	 * @deprecated 5.6.0 Use rest_default_additional_properties_to_false() instead.
   571 	 *
   589 	 *
   572 	 * @param array $schema The schema array.
   590 	 * @param array $schema The schema array.
   573 	 * @return array
   591 	 * @return array
   574 	 */
   592 	 */
   575 	protected function default_additional_properties_to_false( $schema ) {
   593 	protected function default_additional_properties_to_false( $schema ) {
   576 		switch ( $schema['type'] ) {
   594 		_deprecated_function( __METHOD__, '5.6.0', 'rest_default_additional_properties_to_false()' );
   577 			case 'object':
   595 
   578 				foreach ( $schema['properties'] as $key => $child_schema ) {
   596 		return rest_default_additional_properties_to_false( $schema );
   579 					$schema['properties'][ $key ] = $this->default_additional_properties_to_false( $child_schema );
       
   580 				}
       
   581 
       
   582 				if ( ! isset( $schema['additionalProperties'] ) ) {
       
   583 					$schema['additionalProperties'] = false;
       
   584 				}
       
   585 				break;
       
   586 			case 'array':
       
   587 				$schema['items'] = $this->default_additional_properties_to_false( $schema['items'] );
       
   588 				break;
       
   589 		}
       
   590 
       
   591 		return $schema;
       
   592 	}
   597 	}
   593 
   598 
   594 	/**
   599 	/**
   595 	 * Gets the empty value for a schema type.
   600 	 * Gets the empty value for a schema type.
   596 	 *
   601 	 *