[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * REST API: WP_REST_Request class 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 4.4.0 8 */ 9 10 /** 11 * Core class used to implement a REST request object. 12 * 13 * Contains data from the request, to be passed to the callback. 14 * 15 * Note: This implements ArrayAccess, and acts as an array of parameters when 16 * used in that manner. It does not use ArrayObject (as we cannot rely on SPL), 17 * so be aware it may have non-array behavior in some cases. 18 * 19 * Note: When using features provided by ArrayAccess, be aware that WordPress deliberately 20 * does not distinguish between arguments of the same name for different request methods. 21 * For instance, in a request with `GET id=1` and `POST id=2`, `$request['id']` will equal 22 * 2 (`POST`) not 1 (`GET`). For more precision between request methods, use 23 * WP_REST_Request::get_body_params(), WP_REST_Request::get_url_params(), etc. 24 * 25 * @since 4.4.0 26 * 27 * @link https://www.php.net/manual/en/class.arrayaccess.php 28 */ 29 #[AllowDynamicProperties] 30 class WP_REST_Request implements ArrayAccess { 31 32 /** 33 * HTTP method. 34 * 35 * @since 4.4.0 36 * @var string 37 */ 38 protected $method = ''; 39 40 /** 41 * Parameters passed to the request. 42 * 43 * These typically come from the `$_GET`, `$_POST` and `$_FILES` 44 * superglobals when being created from the global scope. 45 * 46 * @since 4.4.0 47 * @var array Contains GET, POST and FILES keys mapping to arrays of data. 48 */ 49 protected $params; 50 51 /** 52 * HTTP headers for the request. 53 * 54 * @since 4.4.0 55 * @var array Map of key to value. Key is always lowercase, as per HTTP specification. 56 */ 57 protected $headers = array(); 58 59 /** 60 * Body data. 61 * 62 * @since 4.4.0 63 * @var string Binary data from the request. 64 */ 65 protected $body = null; 66 67 /** 68 * Route matched for the request. 69 * 70 * @since 4.4.0 71 * @var string 72 */ 73 protected $route; 74 75 /** 76 * Attributes (options) for the route that was matched. 77 * 78 * This is the options array used when the route was registered, typically 79 * containing the callback as well as the valid methods for the route. 80 * 81 * @since 4.4.0 82 * @var array Attributes for the request. 83 */ 84 protected $attributes = array(); 85 86 /** 87 * Used to determine if the JSON data has been parsed yet. 88 * 89 * Allows lazy-parsing of JSON data where possible. 90 * 91 * @since 4.4.0 92 * @var bool 93 */ 94 protected $parsed_json = false; 95 96 /** 97 * Used to determine if the body data has been parsed yet. 98 * 99 * @since 4.4.0 100 * @var bool 101 */ 102 protected $parsed_body = false; 103 104 /** 105 * Constructor. 106 * 107 * @since 4.4.0 108 * 109 * @param string $method Optional. Request method. Default empty. 110 * @param string $route Optional. Request route. Default empty. 111 * @param array $attributes Optional. Request attributes. Default empty array. 112 */ 113 public function __construct( $method = '', $route = '', $attributes = array() ) { 114 $this->params = array( 115 'URL' => array(), 116 'GET' => array(), 117 'POST' => array(), 118 'FILES' => array(), 119 120 // See parse_json_params. 121 'JSON' => null, 122 123 'defaults' => array(), 124 ); 125 126 $this->set_method( $method ); 127 $this->set_route( $route ); 128 $this->set_attributes( $attributes ); 129 } 130 131 /** 132 * Retrieves the HTTP method for the request. 133 * 134 * @since 4.4.0 135 * 136 * @return string HTTP method. 137 */ 138 public function get_method() { 139 return $this->method; 140 } 141 142 /** 143 * Sets HTTP method for the request. 144 * 145 * @since 4.4.0 146 * 147 * @param string $method HTTP method. 148 */ 149 public function set_method( $method ) { 150 $this->method = strtoupper( $method ); 151 } 152 153 /** 154 * Retrieves all headers from the request. 155 * 156 * @since 4.4.0 157 * 158 * @return array Map of key to value. Key is always lowercase, as per HTTP specification. 159 */ 160 public function get_headers() { 161 return $this->headers; 162 } 163 164 /** 165 * Canonicalizes the header name. 166 * 167 * Ensures that header names are always treated the same regardless of 168 * source. Header names are always case-insensitive. 169 * 170 * Note that we treat `-` (dashes) and `_` (underscores) as the same 171 * character, as per header parsing rules in both Apache and nginx. 172 * 173 * @link https://stackoverflow.com/q/18185366 174 * @link https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/#missing-disappearing-http-headers 175 * @link https://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers 176 * 177 * @since 4.4.0 178 * 179 * @param string $key Header name. 180 * @return string Canonicalized name. 181 */ 182 public static function canonicalize_header_name( $key ) { 183 $key = strtolower( $key ); 184 $key = str_replace( '-', '_', $key ); 185 186 return $key; 187 } 188 189 /** 190 * Retrieves the given header from the request. 191 * 192 * If the header has multiple values, they will be concatenated with a comma 193 * as per the HTTP specification. Be aware that some non-compliant headers 194 * (notably cookie headers) cannot be joined this way. 195 * 196 * @since 4.4.0 197 * 198 * @param string $key Header name, will be canonicalized to lowercase. 199 * @return string|null String value if set, null otherwise. 200 */ 201 public function get_header( $key ) { 202 $key = $this->canonicalize_header_name( $key ); 203 204 if ( ! isset( $this->headers[ $key ] ) ) { 205 return null; 206 } 207 208 return implode( ',', $this->headers[ $key ] ); 209 } 210 211 /** 212 * Retrieves header values from the request. 213 * 214 * @since 4.4.0 215 * 216 * @param string $key Header name, will be canonicalized to lowercase. 217 * @return array|null List of string values if set, null otherwise. 218 */ 219 public function get_header_as_array( $key ) { 220 $key = $this->canonicalize_header_name( $key ); 221 222 if ( ! isset( $this->headers[ $key ] ) ) { 223 return null; 224 } 225 226 return $this->headers[ $key ]; 227 } 228 229 /** 230 * Sets the header on request. 231 * 232 * @since 4.4.0 233 * 234 * @param string $key Header name. 235 * @param string $value Header value, or list of values. 236 */ 237 public function set_header( $key, $value ) { 238 $key = $this->canonicalize_header_name( $key ); 239 $value = (array) $value; 240 241 $this->headers[ $key ] = $value; 242 } 243 244 /** 245 * Appends a header value for the given header. 246 * 247 * @since 4.4.0 248 * 249 * @param string $key Header name. 250 * @param string $value Header value, or list of values. 251 */ 252 public function add_header( $key, $value ) { 253 $key = $this->canonicalize_header_name( $key ); 254 $value = (array) $value; 255 256 if ( ! isset( $this->headers[ $key ] ) ) { 257 $this->headers[ $key ] = array(); 258 } 259 260 $this->headers[ $key ] = array_merge( $this->headers[ $key ], $value ); 261 } 262 263 /** 264 * Removes all values for a header. 265 * 266 * @since 4.4.0 267 * 268 * @param string $key Header name. 269 */ 270 public function remove_header( $key ) { 271 $key = $this->canonicalize_header_name( $key ); 272 unset( $this->headers[ $key ] ); 273 } 274 275 /** 276 * Sets headers on the request. 277 * 278 * @since 4.4.0 279 * 280 * @param array $headers Map of header name to value. 281 * @param bool $override If true, replace the request's headers. Otherwise, merge with existing. 282 */ 283 public function set_headers( $headers, $override = true ) { 284 if ( true === $override ) { 285 $this->headers = array(); 286 } 287 288 foreach ( $headers as $key => $value ) { 289 $this->set_header( $key, $value ); 290 } 291 } 292 293 /** 294 * Retrieves the Content-Type of the request. 295 * 296 * @since 4.4.0 297 * 298 * @return array|null Map containing 'value' and 'parameters' keys 299 * or null when no valid Content-Type header was 300 * available. 301 */ 302 public function get_content_type() { 303 $value = $this->get_header( 'Content-Type' ); 304 if ( empty( $value ) ) { 305 return null; 306 } 307 308 $parameters = ''; 309 if ( strpos( $value, ';' ) ) { 310 list( $value, $parameters ) = explode( ';', $value, 2 ); 311 } 312 313 $value = strtolower( $value ); 314 if ( ! str_contains( $value, '/' ) ) { 315 return null; 316 } 317 318 // Parse type and subtype out. 319 list( $type, $subtype ) = explode( '/', $value, 2 ); 320 321 $data = compact( 'value', 'type', 'subtype', 'parameters' ); 322 $data = array_map( 'trim', $data ); 323 324 return $data; 325 } 326 327 /** 328 * Checks if the request has specified a JSON Content-Type. 329 * 330 * @since 5.6.0 331 * 332 * @return bool True if the Content-Type header is JSON. 333 */ 334 public function is_json_content_type() { 335 $content_type = $this->get_content_type(); 336 337 return isset( $content_type['value'] ) && wp_is_json_media_type( $content_type['value'] ); 338 } 339 340 /** 341 * Retrieves the parameter priority order. 342 * 343 * Used when checking parameters in WP_REST_Request::get_param(). 344 * 345 * @since 4.4.0 346 * 347 * @return string[] Array of types to check, in order of priority. 348 */ 349 protected function get_parameter_order() { 350 $order = array(); 351 352 if ( $this->is_json_content_type() ) { 353 $order[] = 'JSON'; 354 } 355 356 $this->parse_json_params(); 357 358 // Ensure we parse the body data. 359 $body = $this->get_body(); 360 361 if ( 'POST' !== $this->method && ! empty( $body ) ) { 362 $this->parse_body_params(); 363 } 364 365 $accepts_body_data = array( 'POST', 'PUT', 'PATCH', 'DELETE' ); 366 if ( in_array( $this->method, $accepts_body_data, true ) ) { 367 $order[] = 'POST'; 368 } 369 370 $order[] = 'GET'; 371 $order[] = 'URL'; 372 $order[] = 'defaults'; 373 374 /** 375 * Filters the parameter priority order for a REST API request. 376 * 377 * The order affects which parameters are checked when using WP_REST_Request::get_param() 378 * and family. This acts similarly to PHP's `request_order` setting. 379 * 380 * @since 4.4.0 381 * 382 * @param string[] $order Array of types to check, in order of priority. 383 * @param WP_REST_Request $request The request object. 384 */ 385 return apply_filters( 'rest_request_parameter_order', $order, $this ); 386 } 387 388 /** 389 * Retrieves a parameter from the request. 390 * 391 * @since 4.4.0 392 * 393 * @param string $key Parameter name. 394 * @return mixed|null Value if set, null otherwise. 395 */ 396 public function get_param( $key ) { 397 $order = $this->get_parameter_order(); 398 399 foreach ( $order as $type ) { 400 // Determine if we have the parameter for this type. 401 if ( isset( $this->params[ $type ][ $key ] ) ) { 402 return $this->params[ $type ][ $key ]; 403 } 404 } 405 406 return null; 407 } 408 409 /** 410 * Checks if a parameter exists in the request. 411 * 412 * This allows distinguishing between an omitted parameter, 413 * and a parameter specifically set to null. 414 * 415 * @since 5.3.0 416 * 417 * @param string $key Parameter name. 418 * @return bool True if a param exists for the given key. 419 */ 420 public function has_param( $key ) { 421 $order = $this->get_parameter_order(); 422 423 foreach ( $order as $type ) { 424 if ( is_array( $this->params[ $type ] ) && array_key_exists( $key, $this->params[ $type ] ) ) { 425 return true; 426 } 427 } 428 429 return false; 430 } 431 432 /** 433 * Sets a parameter on the request. 434 * 435 * If the given parameter key exists in any parameter type an update will take place, 436 * otherwise a new param will be created in the first parameter type (respecting 437 * get_parameter_order()). 438 * 439 * @since 4.4.0 440 * 441 * @param string $key Parameter name. 442 * @param mixed $value Parameter value. 443 */ 444 public function set_param( $key, $value ) { 445 $order = $this->get_parameter_order(); 446 $found_key = false; 447 448 foreach ( $order as $type ) { 449 if ( 'defaults' !== $type && is_array( $this->params[ $type ] ) && array_key_exists( $key, $this->params[ $type ] ) ) { 450 $this->params[ $type ][ $key ] = $value; 451 $found_key = true; 452 } 453 } 454 455 if ( ! $found_key ) { 456 $this->params[ $order[0] ][ $key ] = $value; 457 } 458 } 459 460 /** 461 * Retrieves merged parameters from the request. 462 * 463 * The equivalent of get_param(), but returns all parameters for the request. 464 * Handles merging all the available values into a single array. 465 * 466 * @since 4.4.0 467 * 468 * @return array Map of key to value. 469 */ 470 public function get_params() { 471 $order = $this->get_parameter_order(); 472 $order = array_reverse( $order, true ); 473 474 $params = array(); 475 foreach ( $order as $type ) { 476 /* 477 * array_merge() / the "+" operator will mess up 478 * numeric keys, so instead do a manual foreach. 479 */ 480 foreach ( (array) $this->params[ $type ] as $key => $value ) { 481 $params[ $key ] = $value; 482 } 483 } 484 485 return $params; 486 } 487 488 /** 489 * Retrieves parameters from the route itself. 490 * 491 * These are parsed from the URL using the regex. 492 * 493 * @since 4.4.0 494 * 495 * @return array Parameter map of key to value. 496 */ 497 public function get_url_params() { 498 return $this->params['URL']; 499 } 500 501 /** 502 * Sets parameters from the route. 503 * 504 * Typically, this is set after parsing the URL. 505 * 506 * @since 4.4.0 507 * 508 * @param array $params Parameter map of key to value. 509 */ 510 public function set_url_params( $params ) { 511 $this->params['URL'] = $params; 512 } 513 514 /** 515 * Retrieves parameters from the query string. 516 * 517 * These are the parameters you'd typically find in `$_GET`. 518 * 519 * @since 4.4.0 520 * 521 * @return array Parameter map of key to value 522 */ 523 public function get_query_params() { 524 return $this->params['GET']; 525 } 526 527 /** 528 * Sets parameters from the query string. 529 * 530 * Typically, this is set from `$_GET`. 531 * 532 * @since 4.4.0 533 * 534 * @param array $params Parameter map of key to value. 535 */ 536 public function set_query_params( $params ) { 537 $this->params['GET'] = $params; 538 } 539 540 /** 541 * Retrieves parameters from the body. 542 * 543 * These are the parameters you'd typically find in `$_POST`. 544 * 545 * @since 4.4.0 546 * 547 * @return array Parameter map of key to value. 548 */ 549 public function get_body_params() { 550 return $this->params['POST']; 551 } 552 553 /** 554 * Sets parameters from the body. 555 * 556 * Typically, this is set from `$_POST`. 557 * 558 * @since 4.4.0 559 * 560 * @param array $params Parameter map of key to value. 561 */ 562 public function set_body_params( $params ) { 563 $this->params['POST'] = $params; 564 } 565 566 /** 567 * Retrieves multipart file parameters from the body. 568 * 569 * These are the parameters you'd typically find in `$_FILES`. 570 * 571 * @since 4.4.0 572 * 573 * @return array Parameter map of key to value 574 */ 575 public function get_file_params() { 576 return $this->params['FILES']; 577 } 578 579 /** 580 * Sets multipart file parameters from the body. 581 * 582 * Typically, this is set from `$_FILES`. 583 * 584 * @since 4.4.0 585 * 586 * @param array $params Parameter map of key to value. 587 */ 588 public function set_file_params( $params ) { 589 $this->params['FILES'] = $params; 590 } 591 592 /** 593 * Retrieves the default parameters. 594 * 595 * These are the parameters set in the route registration. 596 * 597 * @since 4.4.0 598 * 599 * @return array Parameter map of key to value 600 */ 601 public function get_default_params() { 602 return $this->params['defaults']; 603 } 604 605 /** 606 * Sets default parameters. 607 * 608 * These are the parameters set in the route registration. 609 * 610 * @since 4.4.0 611 * 612 * @param array $params Parameter map of key to value. 613 */ 614 public function set_default_params( $params ) { 615 $this->params['defaults'] = $params; 616 } 617 618 /** 619 * Retrieves the request body content. 620 * 621 * @since 4.4.0 622 * 623 * @return string Binary data from the request body. 624 */ 625 public function get_body() { 626 return $this->body; 627 } 628 629 /** 630 * Sets body content. 631 * 632 * @since 4.4.0 633 * 634 * @param string $data Binary data from the request body. 635 */ 636 public function set_body( $data ) { 637 $this->body = $data; 638 639 // Enable lazy parsing. 640 $this->parsed_json = false; 641 $this->parsed_body = false; 642 $this->params['JSON'] = null; 643 } 644 645 /** 646 * Retrieves the parameters from a JSON-formatted body. 647 * 648 * @since 4.4.0 649 * 650 * @return array Parameter map of key to value. 651 */ 652 public function get_json_params() { 653 // Ensure the parameters have been parsed out. 654 $this->parse_json_params(); 655 656 return $this->params['JSON']; 657 } 658 659 /** 660 * Parses the JSON parameters. 661 * 662 * Avoids parsing the JSON data until we need to access it. 663 * 664 * @since 4.4.0 665 * @since 4.7.0 Returns error instance if value cannot be decoded. 666 * @return true|WP_Error True if the JSON data was passed or no JSON data was provided, WP_Error if invalid JSON was passed. 667 */ 668 protected function parse_json_params() { 669 if ( $this->parsed_json ) { 670 return true; 671 } 672 673 $this->parsed_json = true; 674 675 // Check that we actually got JSON. 676 if ( ! $this->is_json_content_type() ) { 677 return true; 678 } 679 680 $body = $this->get_body(); 681 if ( empty( $body ) ) { 682 return true; 683 } 684 685 $params = json_decode( $body, true ); 686 687 /* 688 * Check for a parsing error. 689 */ 690 if ( null === $params && JSON_ERROR_NONE !== json_last_error() ) { 691 // Ensure subsequent calls receive error instance. 692 $this->parsed_json = false; 693 694 $error_data = array( 695 'status' => WP_Http::BAD_REQUEST, 696 'json_error_code' => json_last_error(), 697 'json_error_message' => json_last_error_msg(), 698 ); 699 700 return new WP_Error( 'rest_invalid_json', __( 'Invalid JSON body passed.' ), $error_data ); 701 } 702 703 $this->params['JSON'] = $params; 704 705 return true; 706 } 707 708 /** 709 * Parses the request body parameters. 710 * 711 * Parses out URL-encoded bodies for request methods that aren't supported 712 * natively by PHP. 713 * 714 * @since 4.4.0 715 */ 716 protected function parse_body_params() { 717 if ( $this->parsed_body ) { 718 return; 719 } 720 721 $this->parsed_body = true; 722 723 /* 724 * Check that we got URL-encoded. Treat a missing Content-Type as 725 * URL-encoded for maximum compatibility. 726 */ 727 $content_type = $this->get_content_type(); 728 729 if ( ! empty( $content_type ) && 'application/x-www-form-urlencoded' !== $content_type['value'] ) { 730 return; 731 } 732 733 parse_str( $this->get_body(), $params ); 734 735 /* 736 * Add to the POST parameters stored internally. If a user has already 737 * set these manually (via `set_body_params`), don't override them. 738 */ 739 $this->params['POST'] = array_merge( $params, $this->params['POST'] ); 740 } 741 742 /** 743 * Retrieves the route that matched the request. 744 * 745 * @since 4.4.0 746 * 747 * @return string Route matching regex. 748 */ 749 public function get_route() { 750 return $this->route; 751 } 752 753 /** 754 * Sets the route that matched the request. 755 * 756 * @since 4.4.0 757 * 758 * @param string $route Route matching regex. 759 */ 760 public function set_route( $route ) { 761 $this->route = $route; 762 } 763 764 /** 765 * Retrieves the attributes for the request. 766 * 767 * These are the options for the route that was matched. 768 * 769 * @since 4.4.0 770 * 771 * @return array Attributes for the request. 772 */ 773 public function get_attributes() { 774 return $this->attributes; 775 } 776 777 /** 778 * Sets the attributes for the request. 779 * 780 * @since 4.4.0 781 * 782 * @param array $attributes Attributes for the request. 783 */ 784 public function set_attributes( $attributes ) { 785 $this->attributes = $attributes; 786 } 787 788 /** 789 * Sanitizes (where possible) the params on the request. 790 * 791 * This is primarily based off the sanitize_callback param on each registered 792 * argument. 793 * 794 * @since 4.4.0 795 * 796 * @return true|WP_Error True if parameters were sanitized, WP_Error if an error occurred during sanitization. 797 */ 798 public function sanitize_params() { 799 $attributes = $this->get_attributes(); 800 801 // No arguments set, skip sanitizing. 802 if ( empty( $attributes['args'] ) ) { 803 return true; 804 } 805 806 $order = $this->get_parameter_order(); 807 808 $invalid_params = array(); 809 $invalid_details = array(); 810 811 foreach ( $order as $type ) { 812 if ( empty( $this->params[ $type ] ) ) { 813 continue; 814 } 815 816 foreach ( $this->params[ $type ] as $key => $value ) { 817 if ( ! isset( $attributes['args'][ $key ] ) ) { 818 continue; 819 } 820 821 $param_args = $attributes['args'][ $key ]; 822 823 // If the arg has a type but no sanitize_callback attribute, default to rest_parse_request_arg. 824 if ( ! array_key_exists( 'sanitize_callback', $param_args ) && ! empty( $param_args['type'] ) ) { 825 $param_args['sanitize_callback'] = 'rest_parse_request_arg'; 826 } 827 // If there's still no sanitize_callback, nothing to do here. 828 if ( empty( $param_args['sanitize_callback'] ) ) { 829 continue; 830 } 831 832 /** @var mixed|WP_Error $sanitized_value */ 833 $sanitized_value = call_user_func( $param_args['sanitize_callback'], $value, $this, $key ); 834 835 if ( is_wp_error( $sanitized_value ) ) { 836 $invalid_params[ $key ] = implode( ' ', $sanitized_value->get_error_messages() ); 837 $invalid_details[ $key ] = rest_convert_error_to_response( $sanitized_value )->get_data(); 838 } else { 839 $this->params[ $type ][ $key ] = $sanitized_value; 840 } 841 } 842 } 843 844 if ( $invalid_params ) { 845 return new WP_Error( 846 'rest_invalid_param', 847 /* translators: %s: List of invalid parameters. */ 848 sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), 849 array( 850 'status' => 400, 851 'params' => $invalid_params, 852 'details' => $invalid_details, 853 ) 854 ); 855 } 856 857 return true; 858 } 859 860 /** 861 * Checks whether this request is valid according to its attributes. 862 * 863 * @since 4.4.0 864 * 865 * @return true|WP_Error True if there are no parameters to validate or if all pass validation, 866 * WP_Error if required parameters are missing. 867 */ 868 public function has_valid_params() { 869 // If JSON data was passed, check for errors. 870 $json_error = $this->parse_json_params(); 871 if ( is_wp_error( $json_error ) ) { 872 return $json_error; 873 } 874 875 $attributes = $this->get_attributes(); 876 $required = array(); 877 878 $args = empty( $attributes['args'] ) ? array() : $attributes['args']; 879 880 foreach ( $args as $key => $arg ) { 881 $param = $this->get_param( $key ); 882 if ( isset( $arg['required'] ) && true === $arg['required'] && null === $param ) { 883 $required[] = $key; 884 } 885 } 886 887 if ( ! empty( $required ) ) { 888 return new WP_Error( 889 'rest_missing_callback_param', 890 /* translators: %s: List of required parameters. */ 891 sprintf( __( 'Missing parameter(s): %s' ), implode( ', ', $required ) ), 892 array( 893 'status' => 400, 894 'params' => $required, 895 ) 896 ); 897 } 898 899 /* 900 * Check the validation callbacks for each registered arg. 901 * 902 * This is done after required checking as required checking is cheaper. 903 */ 904 $invalid_params = array(); 905 $invalid_details = array(); 906 907 foreach ( $args as $key => $arg ) { 908 909 $param = $this->get_param( $key ); 910 911 if ( null !== $param && ! empty( $arg['validate_callback'] ) ) { 912 /** @var bool|\WP_Error $valid_check */ 913 $valid_check = call_user_func( $arg['validate_callback'], $param, $this, $key ); 914 915 if ( false === $valid_check ) { 916 $invalid_params[ $key ] = __( 'Invalid parameter.' ); 917 } 918 919 if ( is_wp_error( $valid_check ) ) { 920 $invalid_params[ $key ] = implode( ' ', $valid_check->get_error_messages() ); 921 $invalid_details[ $key ] = rest_convert_error_to_response( $valid_check )->get_data(); 922 } 923 } 924 } 925 926 if ( $invalid_params ) { 927 return new WP_Error( 928 'rest_invalid_param', 929 /* translators: %s: List of invalid parameters. */ 930 sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), 931 array( 932 'status' => 400, 933 'params' => $invalid_params, 934 'details' => $invalid_details, 935 ) 936 ); 937 } 938 939 if ( isset( $attributes['validate_callback'] ) ) { 940 $valid_check = call_user_func( $attributes['validate_callback'], $this ); 941 942 if ( is_wp_error( $valid_check ) ) { 943 return $valid_check; 944 } 945 946 if ( false === $valid_check ) { 947 // A WP_Error instance is preferred, but false is supported for parity with the per-arg validate_callback. 948 return new WP_Error( 'rest_invalid_params', __( 'Invalid parameters.' ), array( 'status' => 400 ) ); 949 } 950 } 951 952 return true; 953 } 954 955 /** 956 * Checks if a parameter is set. 957 * 958 * @since 4.4.0 959 * 960 * @param string $offset Parameter name. 961 * @return bool Whether the parameter is set. 962 */ 963 #[ReturnTypeWillChange] 964 public function offsetExists( $offset ) { 965 $order = $this->get_parameter_order(); 966 967 foreach ( $order as $type ) { 968 if ( isset( $this->params[ $type ][ $offset ] ) ) { 969 return true; 970 } 971 } 972 973 return false; 974 } 975 976 /** 977 * Retrieves a parameter from the request. 978 * 979 * @since 4.4.0 980 * 981 * @param string $offset Parameter name. 982 * @return mixed|null Value if set, null otherwise. 983 */ 984 #[ReturnTypeWillChange] 985 public function offsetGet( $offset ) { 986 return $this->get_param( $offset ); 987 } 988 989 /** 990 * Sets a parameter on the request. 991 * 992 * @since 4.4.0 993 * 994 * @param string $offset Parameter name. 995 * @param mixed $value Parameter value. 996 */ 997 #[ReturnTypeWillChange] 998 public function offsetSet( $offset, $value ) { 999 $this->set_param( $offset, $value ); 1000 } 1001 1002 /** 1003 * Removes a parameter from the request. 1004 * 1005 * @since 4.4.0 1006 * 1007 * @param string $offset Parameter name. 1008 */ 1009 #[ReturnTypeWillChange] 1010 public function offsetUnset( $offset ) { 1011 $order = $this->get_parameter_order(); 1012 1013 // Remove the offset from every group. 1014 foreach ( $order as $type ) { 1015 unset( $this->params[ $type ][ $offset ] ); 1016 } 1017 } 1018 1019 /** 1020 * Retrieves a WP_REST_Request object from a full URL. 1021 * 1022 * @since 4.5.0 1023 * 1024 * @param string $url URL with protocol, domain, path and query args. 1025 * @return WP_REST_Request|false WP_REST_Request object on success, false on failure. 1026 */ 1027 public static function from_url( $url ) { 1028 $bits = parse_url( $url ); 1029 $query_params = array(); 1030 1031 if ( ! empty( $bits['query'] ) ) { 1032 wp_parse_str( $bits['query'], $query_params ); 1033 } 1034 1035 $api_root = rest_url(); 1036 if ( get_option( 'permalink_structure' ) && str_starts_with( $url, $api_root ) ) { 1037 // Pretty permalinks on, and URL is under the API root. 1038 $api_url_part = substr( $url, strlen( untrailingslashit( $api_root ) ) ); 1039 $route = parse_url( $api_url_part, PHP_URL_PATH ); 1040 } elseif ( ! empty( $query_params['rest_route'] ) ) { 1041 // ?rest_route=... set directly. 1042 $route = $query_params['rest_route']; 1043 unset( $query_params['rest_route'] ); 1044 } 1045 1046 $request = false; 1047 if ( ! empty( $route ) ) { 1048 $request = new WP_REST_Request( 'GET', $route ); 1049 $request->set_query_params( $query_params ); 1050 } 1051 1052 /** 1053 * Filters the REST API request generated from a URL. 1054 * 1055 * @since 4.5.0 1056 * 1057 * @param WP_REST_Request|false $request Generated request object, or false if URL 1058 * could not be parsed. 1059 * @param string $url URL the request was generated from. 1060 */ 1061 return apply_filters( 'rest_request_from_url', $request, $url ); 1062 } 1063 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Sat Dec 21 08:20:01 2024 | Cross-referenced by PHPXref |