wp/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
    68 	 *
    68 	 *
    69 	 * @since 4.7.0
    69 	 * @since 4.7.0
    70 	 *
    70 	 *
    71 	 * @param int             $object_id Object ID to fetch meta for.
    71 	 * @param int             $object_id Object ID to fetch meta for.
    72 	 * @param WP_REST_Request $request   Full details about the request.
    72 	 * @param WP_REST_Request $request   Full details about the request.
    73 	 * @return WP_Error|object Object containing the meta values by name, otherwise WP_Error object.
    73 	 * @return array Array containing the meta values keyed by name.
    74 	 */
    74 	 */
    75 	public function get_value( $object_id, $request ) {
    75 	public function get_value( $object_id, $request ) {
    76 		$fields   = $this->get_registered_fields();
    76 		$fields   = $this->get_registered_fields();
    77 		$response = array();
    77 		$response = array();
    78 
    78 
    79 		foreach ( $fields as $meta_key => $args ) {
    79 		foreach ( $fields as $meta_key => $args ) {
    80 			$name       = $args['name'];
    80 			$name       = $args['name'];
    81 			$all_values = get_metadata( $this->get_meta_type(), $object_id, $meta_key, false );
    81 			$all_values = get_metadata( $this->get_meta_type(), $object_id, $meta_key, false );
       
    82 
    82 			if ( $args['single'] ) {
    83 			if ( $args['single'] ) {
    83 				if ( empty( $all_values ) ) {
    84 				if ( empty( $all_values ) ) {
    84 					$value = $args['schema']['default'];
    85 					$value = $args['schema']['default'];
    85 				} else {
    86 				} else {
    86 					$value = $all_values[0];
    87 					$value = $all_values[0];
    87 				}
    88 				}
       
    89 
    88 				$value = $this->prepare_value_for_response( $value, $request, $args );
    90 				$value = $this->prepare_value_for_response( $value, $request, $args );
    89 			} else {
    91 			} else {
    90 				$value = array();
    92 				$value = array();
       
    93 
    91 				foreach ( $all_values as $row ) {
    94 				foreach ( $all_values as $row ) {
    92 					$value[] = $this->prepare_value_for_response( $row, $request, $args );
    95 					$value[] = $this->prepare_value_for_response( $row, $request, $args );
    93 				}
    96 				}
    94 			}
    97 			}
    95 
    98 
   124 	/**
   127 	/**
   125 	 * Updates meta values.
   128 	 * Updates meta values.
   126 	 *
   129 	 *
   127 	 * @since 4.7.0
   130 	 * @since 4.7.0
   128 	 *
   131 	 *
   129 	 * @param array           $meta      Array of meta parsed from the request.
   132 	 * @param array $meta      Array of meta parsed from the request.
   130 	 * @param int             $object_id Object ID to fetch meta for.
   133 	 * @param int   $object_id Object ID to fetch meta for.
   131 	 * @return WP_Error|null WP_Error if one occurs, null on success.
   134 	 * @return null|WP_Error Null on success, WP_Error object on failure.
   132 	 */
   135 	 */
   133 	public function update_value( $meta, $object_id ) {
   136 	public function update_value( $meta, $object_id ) {
   134 		$fields = $this->get_registered_fields();
   137 		$fields = $this->get_registered_fields();
       
   138 
   135 		foreach ( $fields as $meta_key => $args ) {
   139 		foreach ( $fields as $meta_key => $args ) {
   136 			$name = $args['name'];
   140 			$name = $args['name'];
   137 			if ( ! array_key_exists( $name, $meta ) ) {
   141 			if ( ! array_key_exists( $name, $meta ) ) {
   138 				continue;
   142 				continue;
   139 			}
   143 			}
   141 			/*
   145 			/*
   142 			 * A null value means reset the field, which is essentially deleting it
   146 			 * A null value means reset the field, which is essentially deleting it
   143 			 * from the database and then relying on the default value.
   147 			 * from the database and then relying on the default value.
   144 			 */
   148 			 */
   145 			if ( is_null( $meta[ $name ] ) ) {
   149 			if ( is_null( $meta[ $name ] ) ) {
       
   150 				$args = $this->get_registered_fields()[ $meta_key ];
       
   151 
       
   152 				if ( $args['single'] ) {
       
   153 					$current = get_metadata( $this->get_meta_type(), $object_id, $meta_key, true );
       
   154 
       
   155 					if ( is_wp_error( rest_validate_value_from_schema( $current, $args['schema'] ) ) ) {
       
   156 						return new WP_Error(
       
   157 							'rest_invalid_stored_value',
       
   158 							/* translators: %s: Custom field key. */
       
   159 							sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ),
       
   160 							array( 'status' => 500 )
       
   161 						);
       
   162 					}
       
   163 				}
       
   164 
   146 				$result = $this->delete_meta_value( $object_id, $meta_key, $name );
   165 				$result = $this->delete_meta_value( $object_id, $meta_key, $name );
   147 				if ( is_wp_error( $result ) ) {
   166 				if ( is_wp_error( $result ) ) {
   148 					return $result;
   167 					return $result;
   149 				}
   168 				}
   150 				continue;
   169 				continue;
   151 			}
   170 			}
   152 
   171 
   153 			$is_valid = rest_validate_value_from_schema( $meta[ $name ], $args['schema'], 'meta.' . $name );
   172 			$value = $meta[ $name ];
       
   173 
       
   174 			if ( ! $args['single'] && is_array( $value ) && count( array_filter( $value, 'is_null' ) ) ) {
       
   175 				return new WP_Error(
       
   176 					'rest_invalid_stored_value',
       
   177 					/* translators: %s: Custom field key. */
       
   178 					sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ),
       
   179 					array( 'status' => 500 )
       
   180 				);
       
   181 			}
       
   182 
       
   183 			$is_valid = rest_validate_value_from_schema( $value, $args['schema'], 'meta.' . $name );
   154 			if ( is_wp_error( $is_valid ) ) {
   184 			if ( is_wp_error( $is_valid ) ) {
   155 				$is_valid->add_data( array( 'status' => 400 ) );
   185 				$is_valid->add_data( array( 'status' => 400 ) );
   156 				return $is_valid;
   186 				return $is_valid;
   157 			}
   187 			}
   158 
   188 
   159 			$value = rest_sanitize_value_from_schema( $meta[ $name ], $args['schema'] );
   189 			$value = rest_sanitize_value_from_schema( $value, $args['schema'] );
   160 
   190 
   161 			if ( $args['single'] ) {
   191 			if ( $args['single'] ) {
   162 				$result = $this->update_meta_value( $object_id, $meta_key, $name, $value );
   192 				$result = $this->update_meta_value( $object_id, $meta_key, $name, $value );
   163 			} else {
   193 			} else {
   164 				$result = $this->update_multi_meta_value( $object_id, $meta_key, $name, $value );
   194 				$result = $this->update_multi_meta_value( $object_id, $meta_key, $name, $value );
   182 	 * @param string $name      Name for the field that is exposed in the REST API.
   212 	 * @param string $name      Name for the field that is exposed in the REST API.
   183 	 * @return bool|WP_Error True if meta field is deleted, WP_Error otherwise.
   213 	 * @return bool|WP_Error True if meta field is deleted, WP_Error otherwise.
   184 	 */
   214 	 */
   185 	protected function delete_meta_value( $object_id, $meta_key, $name ) {
   215 	protected function delete_meta_value( $object_id, $meta_key, $name ) {
   186 		$meta_type = $this->get_meta_type();
   216 		$meta_type = $this->get_meta_type();
       
   217 
   187 		if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $meta_key ) ) {
   218 		if ( ! current_user_can( "delete_{$meta_type}_meta", $object_id, $meta_key ) ) {
   188 			return new WP_Error(
   219 			return new WP_Error(
   189 				'rest_cannot_delete',
   220 				'rest_cannot_delete',
   190 				/* translators: %s: custom field key */
   221 				/* translators: %s: Custom field key. */
   191 				sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ),
   222 				sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ),
   192 				array(
   223 				array(
   193 					'key'    => $name,
   224 					'key'    => $name,
   194 					'status' => rest_authorization_required_code(),
   225 					'status' => rest_authorization_required_code(),
   195 				)
   226 				)
   223 	 * @param array  $values    List of values to update to.
   254 	 * @param array  $values    List of values to update to.
   224 	 * @return bool|WP_Error True if meta fields are updated, WP_Error otherwise.
   255 	 * @return bool|WP_Error True if meta fields are updated, WP_Error otherwise.
   225 	 */
   256 	 */
   226 	protected function update_multi_meta_value( $object_id, $meta_key, $name, $values ) {
   257 	protected function update_multi_meta_value( $object_id, $meta_key, $name, $values ) {
   227 		$meta_type = $this->get_meta_type();
   258 		$meta_type = $this->get_meta_type();
       
   259 
   228 		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
   260 		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
   229 			return new WP_Error(
   261 			return new WP_Error(
   230 				'rest_cannot_update',
   262 				'rest_cannot_update',
   231 				/* translators: %s: custom field key */
   263 				/* translators: %s: Custom field key. */
   232 				sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ),
   264 				sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ),
   233 				array(
   265 				array(
   234 					'key'    => $name,
   266 					'key'    => $name,
   235 					'status' => rest_authorization_required_code(),
   267 					'status' => rest_authorization_required_code(),
   236 				)
   268 				)
   237 			);
   269 			);
   238 		}
   270 		}
   239 
   271 
   240 		$current = get_metadata( $meta_type, $object_id, $meta_key, false );
   272 		$current_values = get_metadata( $meta_type, $object_id, $meta_key, false );
   241 
   273 		$subtype        = get_object_subtype( $meta_type, $object_id );
   242 		$to_remove = $current;
   274 
       
   275 		$to_remove = $current_values;
   243 		$to_add    = $values;
   276 		$to_add    = $values;
   244 
   277 
   245 		foreach ( $to_add as $add_key => $value ) {
   278 		foreach ( $to_add as $add_key => $value ) {
   246 			$remove_keys = array_keys( $to_remove, $value, true );
   279 			$remove_keys = array_keys(
       
   280 				array_filter(
       
   281 					$current_values,
       
   282 					function ( $stored_value ) use ( $meta_key, $subtype, $value ) {
       
   283 						return $this->is_meta_value_same_as_stored_value( $meta_key, $subtype, $stored_value, $value );
       
   284 					}
       
   285 				)
       
   286 			);
   247 
   287 
   248 			if ( empty( $remove_keys ) ) {
   288 			if ( empty( $remove_keys ) ) {
   249 				continue;
   289 				continue;
   250 			}
   290 			}
   251 
   291 
   258 
   298 
   259 			unset( $to_remove[ $remove_key ] );
   299 			unset( $to_remove[ $remove_key ] );
   260 			unset( $to_add[ $add_key ] );
   300 			unset( $to_add[ $add_key ] );
   261 		}
   301 		}
   262 
   302 
   263 		// `delete_metadata` removes _all_ instances of the value, so only call once.
   303 		/*
   264 		$to_remove = array_unique( $to_remove );
   304 		 * `delete_metadata` removes _all_ instances of the value, so only call once. Otherwise,
       
   305 		 * `delete_metadata` will return false for subsequent calls of the same value.
       
   306 		 * Use serialization to produce a predictable string that can be used by array_unique.
       
   307 		 */
       
   308 		$to_remove = array_map( 'maybe_unserialize', array_unique( array_map( 'maybe_serialize', $to_remove ) ) );
   265 
   309 
   266 		foreach ( $to_remove as $value ) {
   310 		foreach ( $to_remove as $value ) {
   267 			if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
   311 			if ( ! delete_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
   268 				return new WP_Error(
   312 				return new WP_Error(
   269 					'rest_meta_database_error',
   313 					'rest_meta_database_error',
   270 					__( 'Could not update meta value in database.' ),
   314 					/* translators: %s: Custom field key. */
       
   315 					sprintf( __( 'Could not update the meta value of %s in database.' ), $meta_key ),
   271 					array(
   316 					array(
   272 						'key'    => $name,
   317 						'key'    => $name,
   273 						'status' => WP_Http::INTERNAL_SERVER_ERROR,
   318 						'status' => WP_Http::INTERNAL_SERVER_ERROR,
   274 					)
   319 					)
   275 				);
   320 				);
   278 
   323 
   279 		foreach ( $to_add as $value ) {
   324 		foreach ( $to_add as $value ) {
   280 			if ( ! add_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
   325 			if ( ! add_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
   281 				return new WP_Error(
   326 				return new WP_Error(
   282 					'rest_meta_database_error',
   327 					'rest_meta_database_error',
   283 					__( 'Could not update meta value in database.' ),
   328 					/* translators: %s: Custom field key. */
       
   329 					sprintf( __( 'Could not update the meta value of %s in database.' ), $meta_key ),
   284 					array(
   330 					array(
   285 						'key'    => $name,
   331 						'key'    => $name,
   286 						'status' => WP_Http::INTERNAL_SERVER_ERROR,
   332 						'status' => WP_Http::INTERNAL_SERVER_ERROR,
   287 					)
   333 					)
   288 				);
   334 				);
   303 	 * @param mixed  $value     Updated value.
   349 	 * @param mixed  $value     Updated value.
   304 	 * @return bool|WP_Error True if the meta field was updated, WP_Error otherwise.
   350 	 * @return bool|WP_Error True if the meta field was updated, WP_Error otherwise.
   305 	 */
   351 	 */
   306 	protected function update_meta_value( $object_id, $meta_key, $name, $value ) {
   352 	protected function update_meta_value( $object_id, $meta_key, $name, $value ) {
   307 		$meta_type = $this->get_meta_type();
   353 		$meta_type = $this->get_meta_type();
       
   354 
   308 		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
   355 		if ( ! current_user_can( "edit_{$meta_type}_meta", $object_id, $meta_key ) ) {
   309 			return new WP_Error(
   356 			return new WP_Error(
   310 				'rest_cannot_update',
   357 				'rest_cannot_update',
   311 				/* translators: %s: custom field key */
   358 				/* translators: %s: Custom field key. */
   312 				sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ),
   359 				sprintf( __( 'Sorry, you are not allowed to edit the %s custom field.' ), $name ),
   313 				array(
   360 				array(
   314 					'key'    => $name,
   361 					'key'    => $name,
   315 					'status' => rest_authorization_required_code(),
   362 					'status' => rest_authorization_required_code(),
   316 				)
   363 				)
   319 
   366 
   320 		// Do the exact same check for a duplicate value as in update_metadata() to avoid update_metadata() returning false.
   367 		// Do the exact same check for a duplicate value as in update_metadata() to avoid update_metadata() returning false.
   321 		$old_value = get_metadata( $meta_type, $object_id, $meta_key );
   368 		$old_value = get_metadata( $meta_type, $object_id, $meta_key );
   322 		$subtype   = get_object_subtype( $meta_type, $object_id );
   369 		$subtype   = get_object_subtype( $meta_type, $object_id );
   323 
   370 
   324 		if ( 1 === count( $old_value ) ) {
   371 		if ( 1 === count( $old_value ) && $this->is_meta_value_same_as_stored_value( $meta_key, $subtype, $old_value[0], $value ) ) {
   325 			if ( (string) sanitize_meta( $meta_key, $value, $meta_type, $subtype ) === $old_value[0] ) {
   372 			return true;
   326 				return true;
   373 		}
   327 			}
   374 
   328 		}
   375 		if ( ! update_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash_strings_only( $value ) ) ) {
   329 
       
   330 		if ( ! update_metadata( $meta_type, $object_id, wp_slash( $meta_key ), wp_slash( $value ) ) ) {
       
   331 			return new WP_Error(
   376 			return new WP_Error(
   332 				'rest_meta_database_error',
   377 				'rest_meta_database_error',
   333 				__( 'Could not update meta value in database.' ),
   378 				/* translators: %s: Custom field key. */
       
   379 				sprintf( __( 'Could not update the meta value of %s in database.' ), $meta_key ),
   334 				array(
   380 				array(
   335 					'key'    => $name,
   381 					'key'    => $name,
   336 					'status' => WP_Http::INTERNAL_SERVER_ERROR,
   382 					'status' => WP_Http::INTERNAL_SERVER_ERROR,
   337 				)
   383 				)
   338 			);
   384 			);
   339 		}
   385 		}
   340 
   386 
   341 		return true;
   387 		return true;
       
   388 	}
       
   389 
       
   390 	/**
       
   391 	 * Checks if the user provided value is equivalent to a stored value for the given meta key.
       
   392 	 *
       
   393 	 * @since 5.5.0
       
   394 	 *
       
   395 	 * @param string $meta_key     The meta key being checked.
       
   396 	 * @param string $subtype      The object subtype.
       
   397 	 * @param mixed  $stored_value The currently stored value retrieved from get_metadata().
       
   398 	 * @param mixed  $user_value   The value provided by the user.
       
   399 	 * @return bool
       
   400 	 */
       
   401 	protected function is_meta_value_same_as_stored_value( $meta_key, $subtype, $stored_value, $user_value ) {
       
   402 		$args      = $this->get_registered_fields()[ $meta_key ];
       
   403 		$sanitized = sanitize_meta( $meta_key, $user_value, $this->get_meta_type(), $subtype );
       
   404 
       
   405 		if ( in_array( $args['type'], array( 'string', 'number', 'integer', 'boolean' ), true ) ) {
       
   406 			// The return value of get_metadata will always be a string for scalar types.
       
   407 			$sanitized = (string) $sanitized;
       
   408 		}
       
   409 
       
   410 		return $sanitized === $stored_value;
   342 	}
   411 	}
   343 
   412 
   344 	/**
   413 	/**
   345 	 * Retrieves all the registered meta fields.
   414 	 * Retrieves all the registered meta fields.
   346 	 *
   415 	 *
   388 			$rest_args['schema'] = array_merge( $default_schema, $rest_args['schema'] );
   457 			$rest_args['schema'] = array_merge( $default_schema, $rest_args['schema'] );
   389 
   458 
   390 			$type = ! empty( $rest_args['type'] ) ? $rest_args['type'] : null;
   459 			$type = ! empty( $rest_args['type'] ) ? $rest_args['type'] : null;
   391 			$type = ! empty( $rest_args['schema']['type'] ) ? $rest_args['schema']['type'] : $type;
   460 			$type = ! empty( $rest_args['schema']['type'] ) ? $rest_args['schema']['type'] : $type;
   392 
   461 
   393 			if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number' ) ) ) {
   462 			if ( null === $rest_args['schema']['default'] ) {
       
   463 				$rest_args['schema']['default'] = static::get_empty_value_for_type( $type );
       
   464 			}
       
   465 
       
   466 			$rest_args['schema'] = $this->default_additional_properties_to_false( $rest_args['schema'] );
       
   467 
       
   468 			if ( ! in_array( $type, array( 'string', 'boolean', 'integer', 'number', 'array', 'object' ), true ) ) {
   394 				continue;
   469 				continue;
   395 			}
   470 			}
   396 
   471 
   397 			if ( empty( $rest_args['single'] ) ) {
   472 			if ( empty( $rest_args['single'] ) ) {
   398 				$rest_args['schema']['items'] = array(
   473 				$rest_args['schema'] = array(
   399 					'type' => $rest_args['type'],
   474 					'type'  => 'array',
       
   475 					'items' => $rest_args['schema'],
   400 				);
   476 				);
   401 				$rest_args['schema']['type']  = 'array';
       
   402 			}
   477 			}
   403 
   478 
   404 			$registered[ $name ] = $rest_args;
   479 			$registered[ $name ] = $rest_args;
   405 		}
   480 		}
   406 
   481 
   447 	 * @param WP_REST_Request $request Request object.
   522 	 * @param WP_REST_Request $request Request object.
   448 	 * @param array           $args    REST-specific options for the meta key.
   523 	 * @param array           $args    REST-specific options for the meta key.
   449 	 * @return mixed Value prepared for output. If a non-JsonSerializable object, null.
   524 	 * @return mixed Value prepared for output. If a non-JsonSerializable object, null.
   450 	 */
   525 	 */
   451 	public static function prepare_value( $value, $request, $args ) {
   526 	public static function prepare_value( $value, $request, $args ) {
   452 		$type = $args['schema']['type'];
   527 		if ( $args['single'] ) {
   453 
   528 			$schema = $args['schema'];
   454 		// For multi-value fields, check the item type instead.
   529 		} else {
   455 		if ( 'array' === $type && ! empty( $args['schema']['items']['type'] ) ) {
   530 			$schema = $args['schema']['items'];
   456 			$type = $args['schema']['items']['type'];
   531 		}
   457 		}
   532 
   458 
   533 		if ( '' === $value && in_array( $schema['type'], array( 'boolean', 'integer', 'number' ), true ) ) {
   459 		switch ( $type ) {
   534 			$value = static::get_empty_value_for_type( $schema['type'] );
   460 			case 'string':
   535 		}
   461 				$value = (string) $value;
   536 
   462 				break;
   537 		if ( is_wp_error( rest_validate_value_from_schema( $value, $schema ) ) ) {
   463 			case 'integer':
       
   464 				$value = (int) $value;
       
   465 				break;
       
   466 			case 'number':
       
   467 				$value = (float) $value;
       
   468 				break;
       
   469 			case 'boolean':
       
   470 				$value = (bool) $value;
       
   471 				break;
       
   472 		}
       
   473 
       
   474 		// Don't allow objects to be output.
       
   475 		if ( is_object( $value ) && ! ( $value instanceof JsonSerializable ) ) {
       
   476 			return null;
   538 			return null;
   477 		}
   539 		}
   478 
   540 
   479 		return $value;
   541 		return rest_sanitize_value_from_schema( $value, $schema );
   480 	}
   542 	}
   481 
   543 
   482 	/**
   544 	/**
   483 	 * Check the 'meta' value of a request is an associative array.
   545 	 * Check the 'meta' value of a request is an associative array.
   484 	 *
   546 	 *
   485 	 * @since 4.7.0
   547 	 * @since 4.7.0
   486 	 *
   548 	 *
   487 	 * @param  mixed           $value   The meta value submitted in the request.
   549 	 * @param mixed           $value   The meta value submitted in the request.
   488 	 * @param  WP_REST_Request $request Full details about the request.
   550 	 * @param WP_REST_Request $request Full details about the request.
   489 	 * @param  string          $param   The parameter name.
   551 	 * @param string          $param   The parameter name.
   490 	 * @return WP_Error|string The meta array, if valid, otherwise an error.
   552 	 * @return array|false The meta array, if valid, false otherwise.
   491 	 */
   553 	 */
   492 	public function check_meta_is_array( $value, $request, $param ) {
   554 	public function check_meta_is_array( $value, $request, $param ) {
   493 		if ( ! is_array( $value ) ) {
   555 		if ( ! is_array( $value ) ) {
   494 			return false;
   556 			return false;
   495 		}
   557 		}
   496 
   558 
   497 		return $value;
   559 		return $value;
   498 	}
   560 	}
       
   561 
       
   562 	/**
       
   563 	 * Recursively add additionalProperties = false to all objects in a schema if no additionalProperties setting
       
   564 	 * is specified.
       
   565 	 *
       
   566 	 * 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
       
   568 	 * default.
       
   569 	 *
       
   570 	 * @since 5.3.0
       
   571 	 *
       
   572 	 * @param array $schema The schema array.
       
   573 	 * @return array
       
   574 	 */
       
   575 	protected function default_additional_properties_to_false( $schema ) {
       
   576 		switch ( $schema['type'] ) {
       
   577 			case 'object':
       
   578 				foreach ( $schema['properties'] as $key => $child_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 	}
       
   593 
       
   594 	/**
       
   595 	 * Gets the empty value for a schema type.
       
   596 	 *
       
   597 	 * @since 5.3.0
       
   598 	 *
       
   599 	 * @param string $type The schema type.
       
   600 	 * @return mixed
       
   601 	 */
       
   602 	protected static function get_empty_value_for_type( $type ) {
       
   603 		switch ( $type ) {
       
   604 			case 'string':
       
   605 				return '';
       
   606 			case 'boolean':
       
   607 				return false;
       
   608 			case 'integer':
       
   609 				return 0;
       
   610 			case 'number':
       
   611 				return 0.0;
       
   612 			case 'array':
       
   613 			case 'object':
       
   614 				return array();
       
   615 			default:
       
   616 				return null;
       
   617 		}
       
   618 	}
   499 }
   619 }