[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * REST API: WP_REST_Settings_Controller class 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 4.7.0 8 */ 9 10 /** 11 * Core class used to manage a site's settings via the REST API. 12 * 13 * @since 4.7.0 14 * 15 * @see WP_REST_Controller 16 */ 17 class WP_REST_Settings_Controller extends WP_REST_Controller { 18 19 /** 20 * Constructor. 21 * 22 * @since 4.7.0 23 */ 24 public function __construct() { 25 $this->namespace = 'wp/v2'; 26 $this->rest_base = 'settings'; 27 } 28 29 /** 30 * Registers the routes for the site's settings. 31 * 32 * @since 4.7.0 33 * 34 * @see register_rest_route() 35 */ 36 public function register_routes() { 37 38 register_rest_route( 39 $this->namespace, 40 '/' . $this->rest_base, 41 array( 42 array( 43 'methods' => WP_REST_Server::READABLE, 44 'callback' => array( $this, 'get_item' ), 45 'args' => array(), 46 'permission_callback' => array( $this, 'get_item_permissions_check' ), 47 ), 48 array( 49 'methods' => WP_REST_Server::EDITABLE, 50 'callback' => array( $this, 'update_item' ), 51 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), 52 'permission_callback' => array( $this, 'get_item_permissions_check' ), 53 ), 54 'schema' => array( $this, 'get_public_item_schema' ), 55 ) 56 ); 57 } 58 59 /** 60 * Checks if a given request has access to read and manage settings. 61 * 62 * @since 4.7.0 63 * 64 * @param WP_REST_Request $request Full details about the request. 65 * @return bool True if the request has read access for the item, otherwise false. 66 */ 67 public function get_item_permissions_check( $request ) { 68 return current_user_can( 'manage_options' ); 69 } 70 71 /** 72 * Retrieves the settings. 73 * 74 * @since 4.7.0 75 * 76 * @param WP_REST_Request $request Full details about the request. 77 * @return array|WP_Error Array on success, or WP_Error object on failure. 78 */ 79 public function get_item( $request ) { 80 $options = $this->get_registered_options(); 81 $response = array(); 82 83 foreach ( $options as $name => $args ) { 84 /** 85 * Filters the value of a setting recognized by the REST API. 86 * 87 * Allow hijacking the setting value and overriding the built-in behavior by returning a 88 * non-null value. The returned value will be presented as the setting value instead. 89 * 90 * @since 4.7.0 91 * 92 * @param mixed $result Value to use for the requested setting. Can be a scalar 93 * matching the registered schema for the setting, or null to 94 * follow the default get_option() behavior. 95 * @param string $name Setting name (as shown in REST API responses). 96 * @param array $args Arguments passed to register_setting() for this setting. 97 */ 98 $response[ $name ] = apply_filters( 'rest_pre_get_setting', null, $name, $args ); 99 100 if ( is_null( $response[ $name ] ) ) { 101 // Default to a null value as "null" in the response means "not set". 102 $response[ $name ] = get_option( $args['option_name'], $args['schema']['default'] ); 103 } 104 105 /* 106 * Because get_option() is lossy, we have to 107 * cast values to the type they are registered with. 108 */ 109 $response[ $name ] = $this->prepare_value( $response[ $name ], $args['schema'] ); 110 } 111 112 return $response; 113 } 114 115 /** 116 * Prepares a value for output based off a schema array. 117 * 118 * @since 4.7.0 119 * 120 * @param mixed $value Value to prepare. 121 * @param array $schema Schema to match. 122 * @return mixed The prepared value. 123 */ 124 protected function prepare_value( $value, $schema ) { 125 /* 126 * If the value is not valid by the schema, set the value to null. 127 * Null values are specifically non-destructive, so this will not cause 128 * overwriting the current invalid value to null. 129 */ 130 if ( is_wp_error( rest_validate_value_from_schema( $value, $schema ) ) ) { 131 return null; 132 } 133 134 return rest_sanitize_value_from_schema( $value, $schema ); 135 } 136 137 /** 138 * Updates settings for the settings object. 139 * 140 * @since 4.7.0 141 * 142 * @param WP_REST_Request $request Full details about the request. 143 * @return array|WP_Error Array on success, or error object on failure. 144 */ 145 public function update_item( $request ) { 146 $options = $this->get_registered_options(); 147 148 $params = $request->get_params(); 149 150 if ( empty( $params ) || ! empty( array_diff_key( $params, $options ) ) ) { 151 $message = empty( $params ) 152 ? __( 'Request body cannot be empty.' ) 153 : __( 'Invalid parameter(s) provided.' ); 154 155 return new WP_Error( 156 'rest_invalid_param', 157 $message, 158 array( 'status' => 400 ) 159 ); 160 } 161 162 foreach ( $options as $name => $args ) { 163 if ( ! array_key_exists( $name, $params ) ) { 164 continue; 165 } 166 167 /** 168 * Filters whether to preempt a setting value update via the REST API. 169 * 170 * Allows hijacking the setting update logic and overriding the built-in behavior by 171 * returning true. 172 * 173 * @since 4.7.0 174 * 175 * @param bool $result Whether to override the default behavior for updating the 176 * value of a setting. 177 * @param string $name Setting name (as shown in REST API responses). 178 * @param mixed $value Updated setting value. 179 * @param array $args Arguments passed to register_setting() for this setting. 180 */ 181 $updated = apply_filters( 'rest_pre_update_setting', false, $name, $request[ $name ], $args ); 182 183 if ( $updated ) { 184 continue; 185 } 186 187 /* 188 * A null value for an option would have the same effect as 189 * deleting the option from the database, and relying on the 190 * default value. 191 */ 192 if ( is_null( $request[ $name ] ) ) { 193 /* 194 * A null value is returned in the response for any option 195 * that has a non-scalar value. 196 * 197 * To protect clients from accidentally including the null 198 * values from a response object in a request, we do not allow 199 * options with values that don't pass validation to be updated to null. 200 * Without this added protection a client could mistakenly 201 * delete all options that have invalid values from the 202 * database. 203 */ 204 if ( is_wp_error( rest_validate_value_from_schema( get_option( $args['option_name'], false ), $args['schema'] ) ) ) { 205 return new WP_Error( 206 'rest_invalid_stored_value', 207 /* translators: %s: Property name. */ 208 sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ), 209 array( 'status' => 500 ) 210 ); 211 } 212 213 delete_option( $args['option_name'] ); 214 } else { 215 update_option( $args['option_name'], $request[ $name ] ); 216 } 217 } 218 219 return $this->get_item( $request ); 220 } 221 222 /** 223 * Retrieves all of the registered options for the Settings API. 224 * 225 * @since 4.7.0 226 * 227 * @return array Array of registered options. 228 */ 229 protected function get_registered_options() { 230 $rest_options = array(); 231 232 foreach ( get_registered_settings() as $name => $args ) { 233 if ( empty( $args['show_in_rest'] ) ) { 234 continue; 235 } 236 237 $rest_args = array(); 238 239 if ( is_array( $args['show_in_rest'] ) ) { 240 $rest_args = $args['show_in_rest']; 241 } 242 243 $defaults = array( 244 'name' => ! empty( $rest_args['name'] ) ? $rest_args['name'] : $name, 245 'schema' => array(), 246 ); 247 248 $rest_args = array_merge( $defaults, $rest_args ); 249 250 $default_schema = array( 251 'type' => empty( $args['type'] ) ? null : $args['type'], 252 'title' => empty( $args['label'] ) ? '' : $args['label'], 253 'description' => empty( $args['description'] ) ? '' : $args['description'], 254 'default' => isset( $args['default'] ) ? $args['default'] : null, 255 ); 256 257 $rest_args['schema'] = array_merge( $default_schema, $rest_args['schema'] ); 258 $rest_args['option_name'] = $name; 259 260 // Skip over settings that don't have a defined type in the schema. 261 if ( empty( $rest_args['schema']['type'] ) ) { 262 continue; 263 } 264 265 /* 266 * Allow the supported types for settings, as we don't want invalid types 267 * to be updated with arbitrary values that we can't do decent sanitizing for. 268 */ 269 if ( ! in_array( $rest_args['schema']['type'], array( 'number', 'integer', 'string', 'boolean', 'array', 'object' ), true ) ) { 270 continue; 271 } 272 273 $rest_args['schema'] = rest_default_additional_properties_to_false( $rest_args['schema'] ); 274 275 $rest_options[ $rest_args['name'] ] = $rest_args; 276 } 277 278 return $rest_options; 279 } 280 281 /** 282 * Retrieves the site setting schema, conforming to JSON Schema. 283 * 284 * @since 4.7.0 285 * 286 * @return array Item schema data. 287 */ 288 public function get_item_schema() { 289 if ( $this->schema ) { 290 return $this->add_additional_fields_schema( $this->schema ); 291 } 292 293 $options = $this->get_registered_options(); 294 295 $schema = array( 296 '$schema' => 'http://json-schema.org/draft-04/schema#', 297 'title' => 'settings', 298 'type' => 'object', 299 'properties' => array(), 300 ); 301 302 foreach ( $options as $option_name => $option ) { 303 $schema['properties'][ $option_name ] = $option['schema']; 304 $schema['properties'][ $option_name ]['arg_options'] = array( 305 'sanitize_callback' => array( $this, 'sanitize_callback' ), 306 ); 307 } 308 309 $this->schema = $schema; 310 311 return $this->add_additional_fields_schema( $this->schema ); 312 } 313 314 /** 315 * Custom sanitize callback used for all options to allow the use of 'null'. 316 * 317 * By default, the schema of settings will throw an error if a value is set to 318 * `null` as it's not a valid value for something like "type => string". We 319 * provide a wrapper sanitizer to allow the use of `null`. 320 * 321 * @since 4.7.0 322 * 323 * @param mixed $value The value for the setting. 324 * @param WP_REST_Request $request The request object. 325 * @param string $param The parameter name. 326 * @return mixed|WP_Error 327 */ 328 public function sanitize_callback( $value, $request, $param ) { 329 if ( is_null( $value ) ) { 330 return $value; 331 } 332 333 return rest_parse_request_arg( $value, $request, $param ); 334 } 335 336 /** 337 * Recursively add additionalProperties = false to all objects in a schema 338 * if no additionalProperties setting is specified. 339 * 340 * This is needed to restrict properties of objects in settings values to only 341 * registered items, as the REST API will allow additional properties by 342 * default. 343 * 344 * @since 4.9.0 345 * @deprecated 6.1.0 Use {@see rest_default_additional_properties_to_false()} instead. 346 * 347 * @param array $schema The schema array. 348 * @return array 349 */ 350 protected function set_additional_properties_to_false( $schema ) { 351 _deprecated_function( __METHOD__, '6.1.0', 'rest_default_additional_properties_to_false()' ); 352 353 return rest_default_additional_properties_to_false( $schema ); 354 } 355 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Fri Jun 27 08:20:01 2025 | Cross-referenced by PHPXref |