WP_REST_Request

Core class used to implement a REST request object.

Defined (1)

The class is defined in the following location(s).

/wp-includes/rest-api/class-wp-rest-request.php  
  1. class WP_REST_Request implements ArrayAccess { 
  2.  
  3. /** 
  4. * HTTP method. 
  5. * @since 4.4.0 
  6. * @access protected 
  7. * @var string 
  8. */ 
  9. protected $method = ''; 
  10.  
  11. /** 
  12. * Parameters passed to the request. 
  13. * These typically come from the `$_GET`, `$_POST` and `$_FILES` 
  14. * superglobals when being created from the global scope. 
  15. * @since 4.4.0 
  16. * @access protected 
  17. * @var array Contains GET, POST and FILES keys mapping to arrays of data. 
  18. */ 
  19. protected $params; 
  20.  
  21. /** 
  22. * HTTP headers for the request. 
  23. * @since 4.4.0 
  24. * @access protected 
  25. * @var array Map of key to value. Key is always lowercase, as per HTTP specification. 
  26. */ 
  27. protected $headers = array(); 
  28.  
  29. /** 
  30. * Body data. 
  31. * @since 4.4.0 
  32. * @access protected 
  33. * @var string Binary data from the request. 
  34. */ 
  35. protected $body = null; 
  36.  
  37. /** 
  38. * Route matched for the request. 
  39. * @since 4.4.0 
  40. * @access protected 
  41. * @var string 
  42. */ 
  43. protected $route; 
  44.  
  45. /** 
  46. * Attributes (options) for the route that was matched. 
  47. * This is the options array used when the route was registered, typically 
  48. * containing the callback as well as the valid methods for the route. 
  49. * @since 4.4.0 
  50. * @access protected 
  51. * @var array Attributes for the request. 
  52. */ 
  53. protected $attributes = array(); 
  54.  
  55. /** 
  56. * Used to determine if the JSON data has been parsed yet. 
  57. * Allows lazy-parsing of JSON data where possible. 
  58. * @since 4.4.0 
  59. * @access protected 
  60. * @var bool 
  61. */ 
  62. protected $parsed_json = false; 
  63.  
  64. /** 
  65. * Used to determine if the body data has been parsed yet. 
  66. * @since 4.4.0 
  67. * @access protected 
  68. * @var bool 
  69. */ 
  70. protected $parsed_body = false; 
  71.  
  72. /** 
  73. * Constructor. 
  74. * @since 4.4.0 
  75. * @access public 
  76. * @param string $method Optional. Request method. Default empty. 
  77. * @param string $route Optional. Request route. Default empty. 
  78. * @param array $attributes Optional. Request attributes. Default empty array. 
  79. */ 
  80. public function __construct( $method = '', $route = '', $attributes = array() ) { 
  81. $this->params = array( 
  82. 'URL' => array(),  
  83. 'GET' => array(),  
  84. 'POST' => array(),  
  85. 'FILES' => array(),  
  86.  
  87. // See parse_json_params. 
  88. 'JSON' => null,  
  89.  
  90. 'defaults' => array(),  
  91. ); 
  92.  
  93. $this->set_method( $method ); 
  94. $this->set_route( $route ); 
  95. $this->set_attributes( $attributes ); 
  96.  
  97. /** 
  98. * Retrieves the HTTP method for the request. 
  99. * @since 4.4.0 
  100. * @access public 
  101. * @return string HTTP method. 
  102. */ 
  103. public function get_method() { 
  104. return $this->method; 
  105.  
  106. /** 
  107. * Sets HTTP method for the request. 
  108. * @since 4.4.0 
  109. * @access public 
  110. * @param string $method HTTP method. 
  111. */ 
  112. public function set_method( $method ) { 
  113. $this->method = strtoupper( $method ); 
  114.  
  115. /** 
  116. * Retrieves all headers from the request. 
  117. * @since 4.4.0 
  118. * @access public 
  119. * @return array Map of key to value. Key is always lowercase, as per HTTP specification. 
  120. */ 
  121. public function get_headers() { 
  122. return $this->headers; 
  123.  
  124. /** 
  125. * Canonicalizes the header name. 
  126. * Ensures that header names are always treated the same regardless of 
  127. * source. Header names are always case insensitive. 
  128. * Note that we treat `-` (dashes) and `_` (underscores) as the same 
  129. * character, as per header parsing rules in both Apache and nginx. 
  130. * @link http://stackoverflow.com/q/18185366 
  131. * @link http://wiki.nginx.org/Pitfalls#Missing_.28disappearing.29_HTTP_headers 
  132. * @link https://nginx.org/en/docs/http/ngx_http_core_module.html#underscores_in_headers 
  133. * @since 4.4.0 
  134. * @access public 
  135. * @static 
  136. * @param string $key Header name. 
  137. * @return string Canonicalized name. 
  138. */ 
  139. public static function canonicalize_header_name( $key ) { 
  140. $key = strtolower( $key ); 
  141. $key = str_replace( '-', '_', $key ); 
  142.  
  143. return $key; 
  144.  
  145. /** 
  146. * Retrieves the given header from the request. 
  147. * If the header has multiple values, they will be concatenated with a comma 
  148. * as per the HTTP specification. Be aware that some non-compliant headers 
  149. * (notably cookie headers) cannot be joined this way. 
  150. * @since 4.4.0 
  151. * @access public 
  152. * @param string $key Header name, will be canonicalized to lowercase. 
  153. * @return string|null String value if set, null otherwise. 
  154. */ 
  155. public function get_header( $key ) { 
  156. $key = $this->canonicalize_header_name( $key ); 
  157.  
  158. if ( ! isset( $this->headers[ $key ] ) ) { 
  159. return null; 
  160.  
  161. return implode( ', ', $this->headers[ $key ] ); 
  162.  
  163. /** 
  164. * Retrieves header values from the request. 
  165. * @since 4.4.0 
  166. * @access public 
  167. * @param string $key Header name, will be canonicalized to lowercase. 
  168. * @return array|null List of string values if set, null otherwise. 
  169. */ 
  170. public function get_header_as_array( $key ) { 
  171. $key = $this->canonicalize_header_name( $key ); 
  172.  
  173. if ( ! isset( $this->headers[ $key ] ) ) { 
  174. return null; 
  175.  
  176. return $this->headers[ $key ]; 
  177.  
  178. /** 
  179. * Sets the header on request. 
  180. * @since 4.4.0 
  181. * @access public 
  182. * @param string $key Header name. 
  183. * @param string $value Header value, or list of values. 
  184. */ 
  185. public function set_header( $key, $value ) { 
  186. $key = $this->canonicalize_header_name( $key ); 
  187. $value = (array) $value; 
  188.  
  189. $this->headers[ $key ] = $value; 
  190.  
  191. /** 
  192. * Appends a header value for the given header. 
  193. * @since 4.4.0 
  194. * @access public 
  195. * @param string $key Header name. 
  196. * @param string $value Header value, or list of values. 
  197. */ 
  198. public function add_header( $key, $value ) { 
  199. $key = $this->canonicalize_header_name( $key ); 
  200. $value = (array) $value; 
  201.  
  202. if ( ! isset( $this->headers[ $key ] ) ) { 
  203. $this->headers[ $key ] = array(); 
  204.  
  205. $this->headers[ $key ] = array_merge( $this->headers[ $key ], $value ); 
  206.  
  207. /** 
  208. * Removes all values for a header. 
  209. * @since 4.4.0 
  210. * @access public 
  211. * @param string $key Header name. 
  212. */ 
  213. public function remove_header( $key ) { 
  214. unset( $this->headers[ $key ] ); 
  215.  
  216. /** 
  217. * Sets headers on the request. 
  218. * @since 4.4.0 
  219. * @access public 
  220. * @param array $headers Map of header name to value. 
  221. * @param bool $override If true, replace the request's headers. Otherwise, merge with existing. 
  222. */ 
  223. public function set_headers( $headers, $override = true ) { 
  224. if ( true === $override ) { 
  225. $this->headers = array(); 
  226.  
  227. foreach ( $headers as $key => $value ) { 
  228. $this->set_header( $key, $value ); 
  229.  
  230. /** 
  231. * Retrieves the content-type of the request. 
  232. * @since 4.4.0 
  233. * @access public 
  234. * @return array Map containing 'value' and 'parameters' keys. 
  235. */ 
  236. public function get_content_type() { 
  237. $value = $this->get_header( 'content-type' ); 
  238. if ( empty( $value ) ) { 
  239. return null; 
  240.  
  241. $parameters = ''; 
  242. if ( strpos( $value, ';' ) ) { 
  243. list( $value, $parameters ) = explode( ';', $value, 2 ); 
  244.  
  245. $value = strtolower( $value ); 
  246. if ( strpos( $value, '/' ) === false ) { 
  247. return null; 
  248.  
  249. // Parse type and subtype out. 
  250. list( $type, $subtype ) = explode( '/', $value, 2 ); 
  251.  
  252. $data = compact( 'value', 'type', 'subtype', 'parameters' ); 
  253. $data = array_map( 'trim', $data ); 
  254.  
  255. return $data; 
  256.  
  257. /** 
  258. * Retrieves the parameter priority order. 
  259. * Used when checking parameters in get_param(). 
  260. * @since 4.4.0 
  261. * @access protected 
  262. * @return array List of types to check, in order of priority. 
  263. */ 
  264. protected function get_parameter_order() { 
  265. $order = array(); 
  266. $order[] = 'JSON'; 
  267.  
  268. $this->parse_json_params(); 
  269.  
  270. // Ensure we parse the body data. 
  271. $body = $this->get_body(); 
  272. if ( $this->method !== 'POST' && ! empty( $body ) ) { 
  273. $this->parse_body_params(); 
  274.  
  275. $accepts_body_data = array( 'POST', 'PUT', 'PATCH' ); 
  276. if ( in_array( $this->method, $accepts_body_data ) ) { 
  277. $order[] = 'POST'; 
  278.  
  279. $order[] = 'GET'; 
  280. $order[] = 'URL'; 
  281. $order[] = 'defaults'; 
  282.  
  283. /** 
  284. * Filters the parameter order. 
  285. * The order affects which parameters are checked when using get_param() and family. 
  286. * This acts similarly to PHP's `request_order` setting. 
  287. * @since 4.4.0 
  288. * @param array $order { 
  289. * An array of types to check, in order of priority. 
  290. * @param string $type The type to check. 
  291. * } 
  292. * @param WP_REST_Request $this The request object. 
  293. */ 
  294. return apply_filters( 'rest_request_parameter_order', $order, $this ); 
  295.  
  296. /** 
  297. * Retrieves a parameter from the request. 
  298. * @since 4.4.0 
  299. * @access public 
  300. * @param string $key Parameter name. 
  301. * @return mixed|null Value if set, null otherwise. 
  302. */ 
  303. public function get_param( $key ) { 
  304. $order = $this->get_parameter_order(); 
  305.  
  306. foreach ( $order as $type ) { 
  307. // Determine if we have the parameter for this type. 
  308. if ( isset( $this->params[ $type ][ $key ] ) ) { 
  309. return $this->params[ $type ][ $key ]; 
  310.  
  311. return null; 
  312.  
  313. /** 
  314. * Sets a parameter on the request. 
  315. * @since 4.4.0 
  316. * @access public 
  317. * @param string $key Parameter name. 
  318. * @param mixed $value Parameter value. 
  319. */ 
  320. public function set_param( $key, $value ) { 
  321. switch ( $this->method ) { 
  322. case 'POST': 
  323. $this->params['POST'][ $key ] = $value; 
  324. break; 
  325.  
  326. default: 
  327. $this->params['GET'][ $key ] = $value; 
  328. break; 
  329.  
  330. /** 
  331. * Retrieves merged parameters from the request. 
  332. * The equivalent of get_param(), but returns all parameters for the request. 
  333. * Handles merging all the available values into a single array. 
  334. * @since 4.4.0 
  335. * @access public 
  336. * @return array Map of key to value. 
  337. */ 
  338. public function get_params() { 
  339. $order = $this->get_parameter_order(); 
  340. $order = array_reverse( $order, true ); 
  341.  
  342. $params = array(); 
  343. foreach ( $order as $type ) { 
  344. $params = array_merge( $params, (array) $this->params[ $type ] ); 
  345.  
  346. return $params; 
  347.  
  348. /** 
  349. * Retrieves parameters from the route itself. 
  350. * These are parsed from the URL using the regex. 
  351. * @since 4.4.0 
  352. * @access public 
  353. * @return array Parameter map of key to value. 
  354. */ 
  355. public function get_url_params() { 
  356. return $this->params['URL']; 
  357.  
  358. /** 
  359. * Sets parameters from the route. 
  360. * Typically, this is set after parsing the URL. 
  361. * @since 4.4.0 
  362. * @access public 
  363. * @param array $params Parameter map of key to value. 
  364. */ 
  365. public function set_url_params( $params ) { 
  366. $this->params['URL'] = $params; 
  367.  
  368. /** 
  369. * Retrieves parameters from the query string. 
  370. * These are the parameters you'd typically find in `$_GET`. 
  371. * @since 4.4.0 
  372. * @access public 
  373. * @return array Parameter map of key to value 
  374. */ 
  375. public function get_query_params() { 
  376. return $this->params['GET']; 
  377.  
  378. /** 
  379. * Sets parameters from the query string. 
  380. * Typically, this is set from `$_GET`. 
  381. * @since 4.4.0 
  382. * @access public 
  383. * @param array $params Parameter map of key to value. 
  384. */ 
  385. public function set_query_params( $params ) { 
  386. $this->params['GET'] = $params; 
  387.  
  388. /** 
  389. * Retrieves parameters from the body. 
  390. * These are the parameters you'd typically find in `$_POST`. 
  391. * @since 4.4.0 
  392. * @access public 
  393. * @return array Parameter map of key to value. 
  394. */ 
  395. public function get_body_params() { 
  396. return $this->params['POST']; 
  397.  
  398. /** 
  399. * Sets parameters from the body. 
  400. * Typically, this is set from `$_POST`. 
  401. * @since 4.4.0 
  402. * @access public 
  403. * @param array $params Parameter map of key to value. 
  404. */ 
  405. public function set_body_params( $params ) { 
  406. $this->params['POST'] = $params; 
  407.  
  408. /** 
  409. * Retrieves multipart file parameters from the body. 
  410. * These are the parameters you'd typically find in `$_FILES`. 
  411. * @since 4.4.0 
  412. * @access public 
  413. * @return array Parameter map of key to value 
  414. */ 
  415. public function get_file_params() { 
  416. return $this->params['FILES']; 
  417.  
  418. /** 
  419. * Sets multipart file parameters from the body. 
  420. * Typically, this is set from `$_FILES`. 
  421. * @since 4.4.0 
  422. * @access public 
  423. * @param array $params Parameter map of key to value. 
  424. */ 
  425. public function set_file_params( $params ) { 
  426. $this->params['FILES'] = $params; 
  427.  
  428. /** 
  429. * Retrieves the default parameters. 
  430. * These are the parameters set in the route registration. 
  431. * @since 4.4.0 
  432. * @access public 
  433. * @return array Parameter map of key to value 
  434. */ 
  435. public function get_default_params() { 
  436. return $this->params['defaults']; 
  437.  
  438. /** 
  439. * Sets default parameters. 
  440. * These are the parameters set in the route registration. 
  441. * @since 4.4.0 
  442. * @access public 
  443. * @param array $params Parameter map of key to value. 
  444. */ 
  445. public function set_default_params( $params ) { 
  446. $this->params['defaults'] = $params; 
  447.  
  448. /** 
  449. * Retrieves the request body content. 
  450. * @since 4.4.0 
  451. * @access public 
  452. * @return string Binary data from the request body. 
  453. */ 
  454. public function get_body() { 
  455. return $this->body; 
  456.  
  457. /** 
  458. * Sets body content. 
  459. * @since 4.4.0 
  460. * @access public 
  461. * @param string $data Binary data from the request body. 
  462. */ 
  463. public function set_body( $data ) { 
  464. $this->body = $data; 
  465.  
  466. // Enable lazy parsing. 
  467. $this->parsed_json = false; 
  468. $this->parsed_body = false; 
  469. $this->params['JSON'] = null; 
  470.  
  471. /** 
  472. * Retrieves the parameters from a JSON-formatted body. 
  473. * @since 4.4.0 
  474. * @access public 
  475. * @return array Parameter map of key to value. 
  476. */ 
  477. public function get_json_params() { 
  478. // Ensure the parameters have been parsed out. 
  479. $this->parse_json_params(); 
  480.  
  481. return $this->params['JSON']; 
  482.  
  483. /** 
  484. * Parses the JSON parameters. 
  485. * Avoids parsing the JSON data until we need to access it. 
  486. * @since 4.4.0 
  487. * @access protected 
  488. */ 
  489. protected function parse_json_params() { 
  490. if ( $this->parsed_json ) { 
  491. return; 
  492.  
  493. $this->parsed_json = true; 
  494.  
  495. // Check that we actually got JSON. 
  496. $content_type = $this->get_content_type(); 
  497.  
  498. if ( empty( $content_type ) || 'application/json' !== $content_type['value'] ) { 
  499. return; 
  500.  
  501. $params = json_decode( $this->get_body(), true ); 
  502.  
  503. /** 
  504. * Check for a parsing error. 
  505. * Note that due to WP's JSON compatibility functions, json_last_error 
  506. * might not be defined: https://core.trac.wordpress.org/ticket/27799 
  507. */ 
  508. if ( null === $params && ( ! function_exists( 'json_last_error' ) || JSON_ERROR_NONE !== json_last_error() ) ) { 
  509. return; 
  510.  
  511. $this->params['JSON'] = $params; 
  512.  
  513. /** 
  514. * Parses the request body parameters. 
  515. * Parses out URL-encoded bodies for request methods that aren't supported 
  516. * natively by PHP. In PHP 5.x, only POST has these parsed automatically. 
  517. * @since 4.4.0 
  518. * @access protected 
  519. */ 
  520. protected function parse_body_params() { 
  521. if ( $this->parsed_body ) { 
  522. return; 
  523.  
  524. $this->parsed_body = true; 
  525.  
  526. /** 
  527. * Check that we got URL-encoded. Treat a missing content-type as 
  528. * URL-encoded for maximum compatibility. 
  529. */ 
  530. $content_type = $this->get_content_type(); 
  531.  
  532. if ( ! empty( $content_type ) && 'application/x-www-form-urlencoded' !== $content_type['value'] ) { 
  533. return; 
  534.  
  535. parse_str( $this->get_body(), $params ); 
  536.  
  537. /** 
  538. * Amazingly, parse_str follows magic quote rules. Sigh. 
  539. * NOTE: Do not refactor to use `wp_unslash`. 
  540. */ 
  541. if ( get_magic_quotes_gpc() ) { 
  542. $params = stripslashes_deep( $params ); 
  543.  
  544. /** 
  545. * Add to the POST parameters stored internally. If a user has already 
  546. * set these manually (via `set_body_params`), don't override them. 
  547. */ 
  548. $this->params['POST'] = array_merge( $params, $this->params['POST'] ); 
  549.  
  550. /** 
  551. * Retrieves the route that matched the request. 
  552. * @since 4.4.0 
  553. * @access public 
  554. * @return string Route matching regex. 
  555. */ 
  556. public function get_route() { 
  557. return $this->route; 
  558.  
  559. /** 
  560. * Sets the route that matched the request. 
  561. * @since 4.4.0 
  562. * @access public 
  563. * @param string $route Route matching regex. 
  564. */ 
  565. public function set_route( $route ) { 
  566. $this->route = $route; 
  567.  
  568. /** 
  569. * Retrieves the attributes for the request. 
  570. * These are the options for the route that was matched. 
  571. * @since 4.4.0 
  572. * @access public 
  573. * @return array Attributes for the request. 
  574. */ 
  575. public function get_attributes() { 
  576. return $this->attributes; 
  577.  
  578. /** 
  579. * Sets the attributes for the request. 
  580. * @since 4.4.0 
  581. * @access public 
  582. * @param array $attributes Attributes for the request. 
  583. */ 
  584. public function set_attributes( $attributes ) { 
  585. $this->attributes = $attributes; 
  586.  
  587. /** 
  588. * Sanitizes (where possible) the params on the request. 
  589. * This is primarily based off the sanitize_callback param on each registered 
  590. * argument. 
  591. * @since 4.4.0 
  592. * @access public 
  593. * @return true|null True if there are no parameters to sanitize, null otherwise. 
  594. */ 
  595. public function sanitize_params() { 
  596.  
  597. $attributes = $this->get_attributes(); 
  598.  
  599. // No arguments set, skip sanitizing. 
  600. if ( empty( $attributes['args'] ) ) { 
  601. return true; 
  602.  
  603. $order = $this->get_parameter_order(); 
  604.  
  605. foreach ( $order as $type ) { 
  606. if ( empty( $this->params[ $type ] ) ) { 
  607. continue; 
  608. foreach ( $this->params[ $type ] as $key => $value ) { 
  609. // Check if this param has a sanitize_callback added. 
  610. if ( isset( $attributes['args'][ $key ] ) && ! empty( $attributes['args'][ $key ]['sanitize_callback'] ) ) { 
  611. $this->params[ $type ][ $key ] = call_user_func( $attributes['args'][ $key ]['sanitize_callback'], $value, $this, $key ); 
  612. return null; 
  613.  
  614. /** 
  615. * Checks whether this request is valid according to its attributes. 
  616. * @since 4.4.0 
  617. * @access public 
  618. * @return bool|WP_Error True if there are no parameters to validate or if all pass validation,  
  619. * WP_Error if required parameters are missing. 
  620. */ 
  621. public function has_valid_params() { 
  622.  
  623. $attributes = $this->get_attributes(); 
  624. $required = array(); 
  625.  
  626. // No arguments set, skip validation. 
  627. if ( empty( $attributes['args'] ) ) { 
  628. return true; 
  629.  
  630. foreach ( $attributes['args'] as $key => $arg ) { 
  631.  
  632. $param = $this->get_param( $key ); 
  633. if ( isset( $arg['required'] ) && true === $arg['required'] && null === $param ) { 
  634. $required[] = $key; 
  635.  
  636. if ( ! empty( $required ) ) { 
  637. return new WP_Error( 'rest_missing_callback_param', sprintf( __( 'Missing parameter(s): %s' ), implode( ', ', $required ) ), array( 'status' => 400, 'params' => $required ) ); 
  638.  
  639. /** 
  640. * Check the validation callbacks for each registered arg. 
  641. * This is done after required checking as required checking is cheaper. 
  642. */ 
  643. $invalid_params = array(); 
  644.  
  645. foreach ( $attributes['args'] as $key => $arg ) { 
  646.  
  647. $param = $this->get_param( $key ); 
  648.  
  649. if ( null !== $param && ! empty( $arg['validate_callback'] ) ) { 
  650. $valid_check = call_user_func( $arg['validate_callback'], $param, $this, $key ); 
  651.  
  652. if ( false === $valid_check ) { 
  653. $invalid_params[ $key ] = __( 'Invalid parameter.' ); 
  654.  
  655. if ( is_wp_error( $valid_check ) ) { 
  656. $invalid_params[ $key ] = $valid_check->get_error_message(); 
  657.  
  658. if ( $invalid_params ) { 
  659. return new WP_Error( 'rest_invalid_param', sprintf( __( 'Invalid parameter(s): %s' ), implode( ', ', array_keys( $invalid_params ) ) ), array( 'status' => 400, 'params' => $invalid_params ) ); 
  660.  
  661. return true; 
  662.  
  663.  
  664. /** 
  665. * Checks if a parameter is set. 
  666. * @since 4.4.0 
  667. * @access public 
  668. * @param string $offset Parameter name. 
  669. * @return bool Whether the parameter is set. 
  670. */ 
  671. public function offsetExists( $offset ) { 
  672. $order = $this->get_parameter_order(); 
  673.  
  674. foreach ( $order as $type ) { 
  675. if ( isset( $this->params[ $type ][ $offset ] ) ) { 
  676. return true; 
  677.  
  678. return false; 
  679.  
  680. /** 
  681. * Retrieves a parameter from the request. 
  682. * @since 4.4.0 
  683. * @access public 
  684. * @param string $offset Parameter name. 
  685. * @return mixed|null Value if set, null otherwise. 
  686. */ 
  687. public function offsetGet( $offset ) { 
  688. return $this->get_param( $offset ); 
  689.  
  690. /** 
  691. * Sets a parameter on the request. 
  692. * @since 4.4.0 
  693. * @access public 
  694. * @param string $offset Parameter name. 
  695. * @param mixed $value Parameter value. 
  696. */ 
  697. public function offsetSet( $offset, $value ) { 
  698. $this->set_param( $offset, $value ); 
  699.  
  700. /** 
  701. * Removes a parameter from the request. 
  702. * @since 4.4.0 
  703. * @access public 
  704. * @param string $offset Parameter name. 
  705. */ 
  706. public function offsetUnset( $offset ) { 
  707. $order = $this->get_parameter_order(); 
  708.  
  709. // Remove the offset from every group. 
  710. foreach ( $order as $type ) { 
  711. unset( $this->params[ $type ][ $offset ] ); 
  712.  
  713. /** 
  714. * Retrieves a WP_REST_Request object from a full URL. 
  715. * @static 
  716. * @since 4.5.0 
  717. * @access public 
  718. * @param string $url URL with protocol, domain, path and query args. 
  719. * @return WP_REST_Request|false WP_REST_Request object on success, false on failure. 
  720. */ 
  721. public static function from_url( $url ) { 
  722. $bits = parse_url( $url ); 
  723. $query_params = array(); 
  724.  
  725. if ( ! empty( $bits['query'] ) ) { 
  726. wp_parse_str( $bits['query'], $query_params ); 
  727.  
  728. $api_root = rest_url(); 
  729. if ( get_option( 'permalink_structure' ) && 0 === strpos( $url, $api_root ) ) { 
  730. // Pretty permalinks on, and URL is under the API root 
  731. $api_url_part = substr( $url, strlen( untrailingslashit( $api_root ) ) ); 
  732. $route = parse_url( $api_url_part, PHP_URL_PATH ); 
  733. } elseif ( ! empty( $query_params['rest_route'] ) ) { 
  734. // ?rest_route=... set directly 
  735. $route = $query_params['rest_route']; 
  736. unset( $query_params['rest_route'] ); 
  737.  
  738. $request = false; 
  739. if ( ! empty( $route ) ) { 
  740. $request = new WP_REST_Request( 'GET', $route ); 
  741. $request->set_query_params( $query_params ); 
  742.  
  743. /** 
  744. * Filters the request generated from a URL. 
  745. * @since 4.5.0 
  746. * @param WP_REST_Request|false $request Generated request object, or false if URL 
  747. * could not be parsed. 
  748. * @param string $url URL the request was generated from. 
  749. */ 
  750. return apply_filters( 'rest_request_from_url', $request, $url );