| 52 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
| 53 | ), |
| 54 | 'schema' => array( $this, 'get_public_item_schema' ), |
| 55 | ) |
| 56 | ); |
| 57 | |
| 58 | register_rest_route( |
| 59 | $this->namespace, |
| 60 | '/' . $this->rest_base . '/(?P<option>.+)', |
| 61 | array( |
| 62 | 'args' => array( |
| 63 | 'id' => array( |
| 64 | 'description' => __( 'The option to fetch.' ), |
| 65 | 'type' => 'string', |
| 66 | ), |
| 67 | ), |
| 68 | array( |
| 69 | 'methods' => WP_REST_Server::READABLE, |
| 70 | 'callback' => array( $this, 'get_item' ), |
| 123 | * Filters the value of a setting recognized by the REST API. |
| 124 | * |
| 125 | * Allow hijacking the setting value and overriding the built-in behavior by returning a |
| 126 | * non-null value. The returned value will be presented as the setting value instead. |
| 127 | * |
| 128 | * @since 4.7.0 |
| 129 | * |
| 130 | * @param mixed $result Value to use for the requested setting. Can be a scalar |
| 131 | * matching the registered schema for the setting, or null to |
| 132 | * follow the default get_option() behavior. |
| 133 | * @param string $name Setting name (as shown in REST API responses). |
| 134 | * @param array $args Arguments passed to register_setting() for this setting. |
| 135 | */ |
| 136 | private function get_filtered_setting( $name, $args ) { |
| 137 | $response = apply_filters( 'rest_pre_get_setting', null, $name, $args ); |
| 138 | |
| 139 | if ( is_null( $response) ) { |
| 140 | // Default to a null value as "null" in the response means "not set". |
| 141 | $response = get_option( $args['option_name'], $args['schema']['default'] ); |
| 142 | } |
| 143 | |
| 144 | /* |
| 145 | * Because get_option() is lossy, we have to |
| 146 | * cast values to the type they are registered with. |
| 147 | */ |
| 148 | return $this->prepare_value( $response, $args['schema'] ); |
| 149 | } |
| 150 | |
| 151 | /** |
85 | | /** |
86 | | * Filters the value of a setting recognized by the REST API. |
87 | | * |
88 | | * Allow hijacking the setting value and overriding the built-in behavior by returning a |
89 | | * non-null value. The returned value will be presented as the setting value instead. |
90 | | * |
91 | | * @since 4.7.0 |
92 | | * |
93 | | * @param mixed $result Value to use for the requested setting. Can be a scalar |
94 | | * matching the registered schema for the setting, or null to |
95 | | * follow the default get_option() behavior. |
96 | | * @param string $name Setting name (as shown in REST API responses). |
97 | | * @param array $args Arguments passed to register_setting() for this setting. |
98 | | */ |
99 | | $response[ $name ] = apply_filters( 'rest_pre_get_setting', null, $name, $args ); |
100 | | |
101 | | if ( is_null( $response[ $name ] ) ) { |
102 | | // Default to a null value as "null" in the response means "not set". |
103 | | $response[ $name ] = get_option( $args['option_name'], $args['schema']['default'] ); |
104 | | } |
105 | | |
106 | | /* |
107 | | * Because get_option() is lossy, we have to |
108 | | * cast values to the type they are registered with. |
109 | | */ |
110 | | $response[ $name ] = $this->prepare_value( $response[ $name ], $args['schema'] ); |
| 164 | $response[ $name ] = $this->get_filtered_setting( $name, $args ); |
| 192 | * Filters whether to preempt a setting value update. |
| 193 | * |
| 194 | * Allows hijacking the setting update logic and overriding the built-in behavior by |
| 195 | * returning true. |
| 196 | * |
| 197 | * @since 4.7.0 |
| 198 | * |
| 199 | * @param bool $result Whether to override the default behavior for updating the |
| 200 | * value of a setting. |
| 201 | * @param string $name Setting name (as shown in REST API responses). |
| 202 | * @param mixed $value Updated setting value. |
| 203 | * @param array $args Arguments passed to register_setting() for this setting. |
| 204 | */ |
| 205 | private function filtered_update_option( $name, $value, $args ) { |
| 206 | $updated = apply_filters( 'rest_pre_update_setting', false, $name, $value, $args ); |
| 207 | |
| 208 | if ( $updated ) { |
| 209 | return; |
| 210 | } |
| 211 | |
| 212 | /* |
| 213 | * A null value for an option would have the same effect as |
| 214 | * deleting the option from the database, and relying on the |
| 215 | * default value. |
| 216 | */ |
| 217 | if ( is_null( $value ) ) { |
| 218 | /* |
| 219 | * A null value is returned in the response for any option |
| 220 | * that has a non-scalar value. |
| 221 | * |
| 222 | * To protect clients from accidentally including the null |
| 223 | * values from a response object in a request, we do not allow |
| 224 | * options with values that don't pass validation to be updated to null. |
| 225 | * Without this added protection a client could mistakenly |
| 226 | * delete all options that have invalid values from the |
| 227 | * database. |
| 228 | */ |
| 229 | if ( is_wp_error( rest_validate_value_from_schema( get_option( $args['option_name'], false ), $args['schema'] ) ) ) { |
| 230 | return new WP_Error( |
| 231 | 'rest_invalid_stored_value', |
| 232 | /* translators: %s: Property name. */ |
| 233 | sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ), |
| 234 | array( 'status' => 500 ) |
| 235 | ); |
| 236 | } |
| 237 | |
| 238 | delete_option( $args['option_name'] ); |
| 239 | } else { |
| 240 | update_option( $args['option_name'], $value ); |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | /** |
155 | | /** |
156 | | * Filters whether to preempt a setting value update. |
157 | | * |
158 | | * Allows hijacking the setting update logic and overriding the built-in behavior by |
159 | | * returning true. |
160 | | * |
161 | | * @since 4.7.0 |
162 | | * |
163 | | * @param bool $result Whether to override the default behavior for updating the |
164 | | * value of a setting. |
165 | | * @param string $name Setting name (as shown in REST API responses). |
166 | | * @param mixed $value Updated setting value. |
167 | | * @param array $args Arguments passed to register_setting() for this setting. |
168 | | */ |
169 | | $updated = apply_filters( 'rest_pre_update_setting', false, $name, $request[ $name ], $args ); |
170 | | |
171 | | if ( $updated ) { |
172 | | continue; |
173 | | } |
174 | | |
175 | | /* |
176 | | * A null value for an option would have the same effect as |
177 | | * deleting the option from the database, and relying on the |
178 | | * default value. |
179 | | */ |
180 | | if ( is_null( $request[ $name ] ) ) { |
181 | | /* |
182 | | * A null value is returned in the response for any option |
183 | | * that has a non-scalar value. |
184 | | * |
185 | | * To protect clients from accidentally including the null |
186 | | * values from a response object in a request, we do not allow |
187 | | * options with values that don't pass validation to be updated to null. |
188 | | * Without this added protection a client could mistakenly |
189 | | * delete all options that have invalid values from the |
190 | | * database. |
191 | | */ |
192 | | if ( is_wp_error( rest_validate_value_from_schema( get_option( $args['option_name'], false ), $args['schema'] ) ) ) { |
193 | | return new WP_Error( |
194 | | 'rest_invalid_stored_value', |
195 | | /* translators: %s: Property name. */ |
196 | | sprintf( __( 'The %s property has an invalid stored value, and cannot be updated to null.' ), $name ), |
197 | | array( 'status' => 500 ) |
198 | | ); |
199 | | } |
200 | | |
201 | | delete_option( $args['option_name'] ); |
202 | | } else { |
203 | | update_option( $args['option_name'], $request[ $name ] ); |
204 | | } |
| 262 | $this->filtered_update_option( $name, $request[ $name ], $args ); |
| 406 | |
| 407 | /** |
| 408 | * Retrieves a single option |
| 409 | * |
| 410 | * @since ? |
| 411 | * |
| 412 | * @param WP_REST_Request $request Full details about the request. |
| 413 | * @return array|WP_Error Array on success, or WP_Error object on failure. |
| 414 | */ |
| 415 | public function get_item( $request ) { |
| 416 | $name = $request['option']; |
| 417 | $options = $this->get_registered_options(); |
| 418 | if ( ! isset( $options[ $name ] ) ) { |
| 419 | return new WP_Error( |
| 420 | 'rest_invalid_setting', |
| 421 | /* translators: %s: Settings name. */ |
| 422 | sprintf( __( '%s is not a registered setting.' ), $name ), |
| 423 | array( 'status' => 500 ) |
| 424 | ); |
| 425 | } |
| 426 | |
| 427 | $response = array(); |
| 428 | $response[ $name ] = $this->get_filtered_setting( $name, $options[ $name ] ); |
| 429 | return $response; |
| 430 | } |
| 431 | |
| 432 | /** |
| 433 | * Updates a given setting |
| 434 | * |
| 435 | * @since 4.7.0 |
| 436 | * |
| 437 | * @param WP_REST_Request $request Full details about the request. |
| 438 | * @return array|WP_Error Array on success, or error object on failure. |
| 439 | */ |
| 440 | public function update_item( $request ) { |
| 441 | $name = $request['option']; |
| 442 | $options = $this->get_registered_options(); |
| 443 | |
| 444 | $params = $request->get_params(); |
| 445 | |
| 446 | if ( ! array_key_exists( $name, $params ) ) { |
| 447 | return new WP_Error( |
| 448 | 'rest_invalid_setting', |
| 449 | /* translators: %s: Settings name. */ |
| 450 | sprintf( __( '%s is not a registered setting.' ), $name ), |
| 451 | array( 'status' => 500 ) |
| 452 | ); |
| 453 | } |
| 454 | |
| 455 | $this->filtered_update_option( $name, $request[ $name ], $options[ $name ] ); |
| 456 | |
| 457 | return $this->get_item( $request ); |
| 458 | } |