Version Description
Download this release
Release Info
| Developer | danielbachhuber |
| Plugin | |
| Version | 2.0-beta12 |
| Comparing to | |
| See all releases | |
Code changes from version 2.0-beta11 to 2.0-beta12
- CHANGELOG.md +147 -11
- core-integration.php +15 -0
- lib/endpoints/class-wp-rest-attachments-controller.php +76 -20
- lib/endpoints/class-wp-rest-comments-controller.php +117 -113
- lib/endpoints/class-wp-rest-controller.php +30 -104
- lib/endpoints/class-wp-rest-meta-controller.php +0 -468
- lib/endpoints/class-wp-rest-meta-posts-controller.php +0 -115
- lib/endpoints/class-wp-rest-post-statuses-controller.php +104 -39
- lib/endpoints/class-wp-rest-post-types-controller.php +55 -19
- lib/endpoints/class-wp-rest-posts-controller.php +65 -52
- lib/endpoints/class-wp-rest-revisions-controller.php +30 -29
- lib/endpoints/class-wp-rest-taxonomies-controller.php +66 -22
- lib/endpoints/class-wp-rest-terms-controller.php +93 -75
- lib/endpoints/class-wp-rest-users-controller.php +142 -113
- plugin.php +130 -20
- readme.txt +151 -13
CHANGELOG.md
CHANGED
|
@@ -1,6 +1,142 @@
|
|
| 1 |
# Changelog
|
| 2 |
|
| 3 |
-
## 2.0 Beta
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
- BREAKING CHANGE: Moves Post->Term relations to the Post Resource
|
| 6 |
|
|
@@ -147,7 +283,7 @@ unnecessary call to `get_item()`.
|
|
| 147 |
|
| 148 |
(props @danielbachhuber, [#1990](https://github.com/WP-API/WP-API/pull/1990))
|
| 149 |
|
| 150 |
-
## 2.0 Beta 10.0
|
| 151 |
|
| 152 |
- SECURITY: Ensure media of private posts are private too.
|
| 153 |
|
|
@@ -279,7 +415,7 @@ unnecessary call to `get_item()`.
|
|
| 279 |
|
| 280 |
(props @danielbachhuber, [#1852](https://github.com/WP-API/WP-API/pull/1852))
|
| 281 |
|
| 282 |
-
## 2.0 Beta 9.0
|
| 283 |
|
| 284 |
- BREAKING CHANGE: Move tags and categories to top-level endpoints.
|
| 285 |
|
|
@@ -393,7 +529,7 @@ unnecessary call to `get_item()`.
|
|
| 393 |
|
| 394 |
(props @danielbachhuber, [#1833](https://github.com/WP-API/WP-API/pull/1833))
|
| 395 |
|
| 396 |
-
## 2.0 Beta 8.0
|
| 397 |
|
| 398 |
- Prevent fatals when uploading attachment by including admin utilities.
|
| 399 |
|
|
@@ -429,7 +565,7 @@ unnecessary call to `get_item()`.
|
|
| 429 |
|
| 430 |
(props @wpsmith, [#1759](https://github.com/WP-API/WP-API/pull/1759))
|
| 431 |
|
| 432 |
-
## 2.0 Beta 7.0
|
| 433 |
|
| 434 |
- Sync infrastructure from WordPress core as of r35691.
|
| 435 |
|
|
@@ -461,7 +597,7 @@ unnecessary call to `get_item()`.
|
|
| 461 |
(props @danielbachhuber, [#1726](https://github.com/WP-API/WP-API/pull/1726))
|
| 462 |
|
| 463 |
|
| 464 |
-
## 2.0 Beta 6.0
|
| 465 |
|
| 466 |
- Remove global inclusion of wp-admin/includes/admin.php
|
| 467 |
|
|
@@ -557,7 +693,7 @@ unnecessary call to `get_item()`.
|
|
| 557 |
|
| 558 |
(props @rachelbaker, [#1497](https://github.com/WP-API/WP-API/pull/1497))
|
| 559 |
|
| 560 |
-
## 2.0 Beta 5.0
|
| 561 |
|
| 562 |
- Load api-core as a compatibility library
|
| 563 |
|
|
@@ -592,7 +728,7 @@ unnecessary call to `get_item()`.
|
|
| 592 |
|
| 593 |
(props @joehoyle)
|
| 594 |
|
| 595 |
-
## 2.0 Beta 4.0
|
| 596 |
|
| 597 |
- Show public user information through the user controller.
|
| 598 |
|
|
@@ -825,7 +961,7 @@ unnecessary call to `get_item()`.
|
|
| 825 |
[gh-1467]: https://github.com/WP-API/WP-API/issues/1467
|
| 826 |
[gh-1472]: https://github.com/WP-API/WP-API/issues/1472
|
| 827 |
|
| 828 |
-
## 2.0 Beta 3.0
|
| 829 |
|
| 830 |
- Add ability to declare sanitization and default options for schema fields.
|
| 831 |
|
|
@@ -890,7 +1026,7 @@ unnecessary call to `get_item()`.
|
|
| 890 |
[gh-1347]: https://github.com/WP-API/WP-API/issues/1347
|
| 891 |
[gh-1348]: https://github.com/WP-API/WP-API/issues/1348
|
| 892 |
|
| 893 |
-
## 2.0 Beta 2.0
|
| 894 |
|
| 895 |
- Load the WP REST API before the main query runs.
|
| 896 |
|
|
@@ -1111,7 +1247,7 @@ unnecessary call to `get_item()`.
|
|
| 1111 |
Reported by @kacperszurek on 2015-05-16.
|
| 1112 |
|
| 1113 |
|
| 1114 |
-
## 2.0 Beta 1
|
| 1115 |
|
| 1116 |
- Avoid passing server to the controller each time
|
| 1117 |
|
| 1 |
# Changelog
|
| 2 |
|
| 3 |
+
## 2.0 Beta 12.0 (February 9, 2016)
|
| 4 |
+
|
| 5 |
+
- BREAKING CHANGE: Removes meta endpoints from primary plugin.
|
| 6 |
+
|
| 7 |
+
If your project depends on post meta endpoints, please install [WP REST API Meta Endpoints](https://wordpress.org/plugins/rest-api-meta-endpoints/). For the gory history of meta, read [#1425](https://github.com/WP-API/WP-API/issues/1425) and linked issues. At this time, we recommend using `register_rest_field()` to expose meta ([docs](http://v2.wp-api.org/extending/modifying/)).
|
| 8 |
+
|
| 9 |
+
(props @danielbachhuber, [#2172](https://github.com/WP-API/WP-API/pull/2172))
|
| 10 |
+
|
| 11 |
+
- BREAKING CHANGE: Returns original resource when deleting PTCU.
|
| 12 |
+
|
| 13 |
+
Now that all resources require the `force` param, we don't need to wrap delete responses with the `trash` state.
|
| 14 |
+
|
| 15 |
+
(props @danielbachhuber, [#2163](https://github.com/WP-API/WP-API/pull/2163))
|
| 16 |
+
|
| 17 |
+
- BREAKING CHANGE: Uses `roles` rather than `role` in the Users controller.
|
| 18 |
+
|
| 19 |
+
Building the REST API gives us the opportunity to standardize on `roles`, instead of having both `roles` and `role`.
|
| 20 |
+
|
| 21 |
+
(props @joehoyle, [#2177](https://github.com/WP-API/WP-API/pull/2177))
|
| 22 |
+
|
| 23 |
+
- BREAKING CHANGES: Moves to consistent use of `context` throughout controllers.
|
| 24 |
+
|
| 25 |
+
Contexts limit the data present in the response. Here's how to think of them: `embed` correlates with sidebar representation, `view` represents the primary public view, and `edit` is the data expected for an editor.
|
| 26 |
+
|
| 27 |
+
(props @danielbachhuber, [#2205](https://github.com/WP-API/WP-API/pull/2205), [#2204](https://github.com/WP-API/WP-API/pull/2204), [#2203](https://github.com/WP-API/WP-API/pull/2203), [#2218](https://github.com/WP-API/WP-API/pull/2218), [#2216](https://github.com/WP-API/WP-API/pull/2216), [#2230](https://github.com/WP-API/WP-API/pull/2230), [#2184](https://github.com/WP-API/WP-API/pull/2184), [#2235](https://github.com/WP-API/WP-API/pull/2235))
|
| 28 |
+
|
| 29 |
+
- BREAKING CHANGE: Removes `post_*` query param support for `GET /wp/v2/comments`.
|
| 30 |
+
|
| 31 |
+
The proper pattern is to use `GET /wp/v2/posts` to fetch the post IDs to limit the request to.
|
| 32 |
+
|
| 33 |
+
(props @danielbachhuber, [#2165](https://github.com/WP-API/WP-API/pull/2165))
|
| 34 |
+
|
| 35 |
+
- BREAKING CHANGE: Introduces `rest_validate_request_arg()`/`rest_sanitize_request_arg()`.
|
| 36 |
+
|
| 37 |
+
Dedicated functions means we can use them for validating / sanitizing query args too. Removes `WP_REST_Controller::validate_schema_property()` and `WP_REST_Controller::sanitize_schema_property()`.
|
| 38 |
+
|
| 39 |
+
(props @danielbachhuber, [#2166](https://github.com/WP-API/WP-API/pull/2166), [#2213](https://github.com/WP-API/WP-API/pull/2213))
|
| 40 |
+
|
| 41 |
+
- Requires minimum value of 1 for `page` param.
|
| 42 |
+
|
| 43 |
+
(props @danielbachhuber, [#2241](https://github.com/WP-API/WP-API/pull/2241))
|
| 44 |
+
|
| 45 |
+
- Introduces `media_type` and `mime_type` params for `GET /wp/v2/media`.
|
| 46 |
+
|
| 47 |
+
(props @danielbachhuber, [#2231](https://github.com/WP-API/WP-API/pull/2231))
|
| 48 |
+
|
| 49 |
+
- Uses the term cache for post data.
|
| 50 |
+
|
| 51 |
+
(props @rmccue, [#2234](https://github.com/WP-API/WP-API/pull/2234))
|
| 52 |
+
|
| 53 |
+
- Supports for querying comments where `post=0`.
|
| 54 |
+
|
| 55 |
+
(props @danielbachhuber, [#1865](https://github.com/WP-API/WP-API/pull/1865))
|
| 56 |
+
|
| 57 |
+
- Exposes taxonomy and post type capabilities in `context=edit`.
|
| 58 |
+
|
| 59 |
+
(props @danielbachhuber, [#2216](https://github.com/WP-API/WP-API/pull/2216))
|
| 60 |
+
|
| 61 |
+
- Errors early when user can't GET types or taxonomies when `context=edit`.
|
| 62 |
+
|
| 63 |
+
(props @danielbachhuber, [#2218](https://github.com/WP-API/WP-API/pull/2218))
|
| 64 |
+
|
| 65 |
+
- Passes original $request context to `prepare_items_query`.
|
| 66 |
+
|
| 67 |
+
(props @danielbachhuber, [#2211](https://github.com/WP-API/WP-API/pull/2211))
|
| 68 |
+
|
| 69 |
+
- Adds `parent` and `parent_exclude` params to GET Comments.
|
| 70 |
+
|
| 71 |
+
(props @danielbachhuber, [#2206](https://github.com/WP-API/WP-API/pull/2206))
|
| 72 |
+
|
| 73 |
+
- Enforces minimum 1 and maximum 100 values for `per_page` parameter.
|
| 74 |
+
|
| 75 |
+
(props @danielbachhuber, [#2209](https://github.com/WP-API/WP-API/pull/2209))
|
| 76 |
+
|
| 77 |
+
- Adds `author` and `author_exclude` params to GET Posts and Comments.
|
| 78 |
+
|
| 79 |
+
(props @danielbachhuber, [#2200](https://github.com/WP-API/WP-API/pull/2202), [#2200](https://github.com/WP-API/WP-API/pull/2202))
|
| 80 |
+
|
| 81 |
+
- Adds `menu_order` param for `GET` Pages; support `menu_order` orderby.
|
| 82 |
+
|
| 83 |
+
(props @danielbachhuber, [#2193](https://github.com/WP-API/WP-API/pull/2193))
|
| 84 |
+
|
| 85 |
+
- Only calls `sanitize_text_field()` when sanitizing `type=string,format=email`.
|
| 86 |
+
|
| 87 |
+
(props @danielbachhuber, [#2185](https://github.com/WP-API/WP-API/pull/2185))
|
| 88 |
+
|
| 89 |
+
- Validates `GET /wp/v2/comments` private query params.
|
| 90 |
+
|
| 91 |
+
Returns an error when user doesn't have permission to use them, instead of silently discarding.
|
| 92 |
+
|
| 93 |
+
(props @danielbachhuber, [#2178](https://github.com/WP-API/WP-API/pull/2178))
|
| 94 |
+
|
| 95 |
+
- Explicitly prevents uploading attachments to other attachments or revisions.
|
| 96 |
+
|
| 97 |
+
(props @danielbachhuber, [#2180](https://github.com/WP-API/WP-API/pull/2180))
|
| 98 |
+
|
| 99 |
+
- Permits user urls to be edited through the API.
|
| 100 |
+
|
| 101 |
+
(props @danielbachhuber, [#2182](https://github.com/WP-API/WP-API/pull/2182))
|
| 102 |
+
|
| 103 |
+
- Marks all Status, Type and Taxonomy fields as `readonly`.
|
| 104 |
+
|
| 105 |
+
(props @danielbachhuber, [#2181](https://github.com/WP-API/WP-API/pull/2181))
|
| 106 |
+
|
| 107 |
+
- Adds validation callbacks to collection query params.
|
| 108 |
+
|
| 109 |
+
(props @danielbachhuber, [#2170](https://github.com/WP-API/WP-API/pull/2170), [#2171](https://github.com/WP-API/WP-API/pull/2171), [#2176](https://github.com/WP-API/WP-API/pull/2176), [#2174](https://github.com/WP-API/WP-API/pull/2174), [#2175](https://github.com/WP-API/WP-API/pull/2175))
|
| 110 |
+
|
| 111 |
+
- Links taxonomy terms to the post type collections they support.
|
| 112 |
+
|
| 113 |
+
(props @danielbachhuber, [#2167](https://github.com/WP-API/WP-API/pull/2167))
|
| 114 |
+
|
| 115 |
+
- Returns error when making a `GET` request with invalid context.
|
| 116 |
+
|
| 117 |
+
(props @danielbachhuber, [#2169](https://github.com/WP-API/WP-API/pull/2169))
|
| 118 |
+
|
| 119 |
+
- Adds `trash` status to `GET /wp/v2/statuses`.
|
| 120 |
+
|
| 121 |
+
(props @danielbachhuber, [#2158](https://github.com/WP-API/WP-API/pull/2158))
|
| 122 |
+
|
| 123 |
+
- Indicates when fields have HTML in schema.
|
| 124 |
+
|
| 125 |
+
(props @joehoyle, [#2159](https://github.com/WP-API/WP-API/pull/2159))
|
| 126 |
+
|
| 127 |
+
- Permits viewing of User who has published any Public posts.
|
| 128 |
+
|
| 129 |
+
(props @danielbachhuber, [#2155](https://github.com/WP-API/WP-API/pull/2155))
|
| 130 |
+
|
| 131 |
+
- Respects `show_avatars` option when adding avatars to Users.
|
| 132 |
+
|
| 133 |
+
(props @nullvariable, [#2151](https://github.com/WP-API/WP-API/pull/2151))
|
| 134 |
+
|
| 135 |
+
- Controllers use `$namespace` and `$rest_base` class variables for easier subclassing.
|
| 136 |
+
|
| 137 |
+
(props @danielbachhuber, [#2119](https://github.com/WP-API/WP-API/pull/2119), [#2130](https://github.com/WP-API/WP-API/pull/2130), [#2131](https://github.com/WP-API/WP-API/pull/2131), [#2132](https://github.com/WP-API/WP-API/pull/2132), [#2133](https://github.com/WP-API/WP-API/pull/2133), [#2134](https://github.com/WP-API/WP-API/pull/2134), [#2139](https://github.com/WP-API/WP-API/pull/2139), [#2141](https://github.com/WP-API/WP-API/pull/2141), [#2142](https://github.com/WP-API/WP-API/pull/2142))
|
| 138 |
+
|
| 139 |
+
## 2.0 Beta 11.0 (January 25, 2016)
|
| 140 |
|
| 141 |
- BREAKING CHANGE: Moves Post->Term relations to the Post Resource
|
| 142 |
|
| 283 |
|
| 284 |
(props @danielbachhuber, [#1990](https://github.com/WP-API/WP-API/pull/1990))
|
| 285 |
|
| 286 |
+
## 2.0 Beta 10.0 (January 11, 2016)
|
| 287 |
|
| 288 |
- SECURITY: Ensure media of private posts are private too.
|
| 289 |
|
| 415 |
|
| 416 |
(props @danielbachhuber, [#1852](https://github.com/WP-API/WP-API/pull/1852))
|
| 417 |
|
| 418 |
+
## 2.0 Beta 9.0 (December 11, 2015)
|
| 419 |
|
| 420 |
- BREAKING CHANGE: Move tags and categories to top-level endpoints.
|
| 421 |
|
| 529 |
|
| 530 |
(props @danielbachhuber, [#1833](https://github.com/WP-API/WP-API/pull/1833))
|
| 531 |
|
| 532 |
+
## 2.0 Beta 8.0 (December 1, 2015)
|
| 533 |
|
| 534 |
- Prevent fatals when uploading attachment by including admin utilities.
|
| 535 |
|
| 565 |
|
| 566 |
(props @wpsmith, [#1759](https://github.com/WP-API/WP-API/pull/1759))
|
| 567 |
|
| 568 |
+
## 2.0 Beta 7.0 (November 17, 2015)
|
| 569 |
|
| 570 |
- Sync infrastructure from WordPress core as of r35691.
|
| 571 |
|
| 597 |
(props @danielbachhuber, [#1726](https://github.com/WP-API/WP-API/pull/1726))
|
| 598 |
|
| 599 |
|
| 600 |
+
## 2.0 Beta 6.0 (November 12, 2015)
|
| 601 |
|
| 602 |
- Remove global inclusion of wp-admin/includes/admin.php
|
| 603 |
|
| 693 |
|
| 694 |
(props @rachelbaker, [#1497](https://github.com/WP-API/WP-API/pull/1497))
|
| 695 |
|
| 696 |
+
## 2.0 Beta 5.0 (October 23, 2015)
|
| 697 |
|
| 698 |
- Load api-core as a compatibility library
|
| 699 |
|
| 728 |
|
| 729 |
(props @joehoyle)
|
| 730 |
|
| 731 |
+
## 2.0 Beta 4.0 (August 14, 2015)
|
| 732 |
|
| 733 |
- Show public user information through the user controller.
|
| 734 |
|
| 961 |
[gh-1467]: https://github.com/WP-API/WP-API/issues/1467
|
| 962 |
[gh-1472]: https://github.com/WP-API/WP-API/issues/1472
|
| 963 |
|
| 964 |
+
## 2.0 Beta 3.0 (July 1, 2015)
|
| 965 |
|
| 966 |
- Add ability to declare sanitization and default options for schema fields.
|
| 967 |
|
| 1026 |
[gh-1347]: https://github.com/WP-API/WP-API/issues/1347
|
| 1027 |
[gh-1348]: https://github.com/WP-API/WP-API/issues/1348
|
| 1028 |
|
| 1029 |
+
## 2.0 Beta 2.0 (May 28, 2015)
|
| 1030 |
|
| 1031 |
- Load the WP REST API before the main query runs.
|
| 1032 |
|
| 1247 |
Reported by @kacperszurek on 2015-05-16.
|
| 1248 |
|
| 1249 |
|
| 1250 |
+
## 2.0 Beta 1 (April 28, 2015)
|
| 1251 |
|
| 1252 |
- Avoid passing server to the controller each time
|
| 1253 |
|
core-integration.php
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<?php
|
| 2 |
+
/**
|
| 3 |
+
* Integration points with WordPress core that won't ever be committed
|
| 4 |
+
*/
|
| 5 |
+
|
| 6 |
+
/**
|
| 7 |
+
* Inject `parent__in` and `parent__not_in` vars to avoid bad cache
|
| 8 |
+
*
|
| 9 |
+
* @see https://core.trac.wordpress.org/ticket/35677
|
| 10 |
+
*/
|
| 11 |
+
function wp_api_comment_query_vars( $query ) {
|
| 12 |
+
$query->query_var_defaults['parent__in'] = array();
|
| 13 |
+
$query->query_var_defaults['parent__not_in'] = array();
|
| 14 |
+
}
|
| 15 |
+
add_action( 'pre_get_comments', 'wp_api_comment_query_vars' );
|
lib/endpoints/class-wp-rest-attachments-controller.php
CHANGED
|
@@ -6,14 +6,25 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 6 |
* Determine the allowed query_vars for a get_items() response and
|
| 7 |
* prepare for WP_Query.
|
| 8 |
*
|
| 9 |
-
* @param array
|
| 10 |
-
* @
|
|
|
|
| 11 |
*/
|
| 12 |
-
protected function prepare_items_query( $prepared_args = array() ) {
|
| 13 |
-
$query_args = parent::prepare_items_query( $prepared_args );
|
| 14 |
if ( empty( $query_args['post_status'] ) || ! in_array( $query_args['post_status'], array( 'inherit', 'private', 'trash' ) ) ) {
|
| 15 |
$query_args['post_status'] = 'inherit';
|
| 16 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
return $query_args;
|
| 18 |
}
|
| 19 |
|
|
@@ -40,7 +51,7 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 40 |
$parent = get_post( (int) $request['post'] );
|
| 41 |
$post_parent_type = get_post_type_object( $parent->post_type );
|
| 42 |
if ( ! current_user_can( $post_parent_type->cap->edit_post, $request['post'] ) ) {
|
| 43 |
-
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to upload media to this
|
| 44 |
}
|
| 45 |
}
|
| 46 |
|
|
@@ -55,6 +66,10 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 55 |
*/
|
| 56 |
public function create_item( $request ) {
|
| 57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
// Get the file via $_FILES or raw data
|
| 59 |
$files = $request->get_file_params();
|
| 60 |
$headers = $request->get_headers();
|
|
@@ -120,7 +135,7 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 120 |
$response = $this->prepare_item_for_response( $attachment, $request );
|
| 121 |
$response = rest_ensure_response( $response );
|
| 122 |
$response->set_status( 201 );
|
| 123 |
-
$response->header( 'Location', rest_url( '
|
| 124 |
|
| 125 |
/**
|
| 126 |
* Fires after a single attachment is created or updated via the REST API.
|
|
@@ -142,6 +157,9 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 142 |
* @return WP_Error|WP_REST_Response
|
| 143 |
*/
|
| 144 |
public function update_item( $request ) {
|
|
|
|
|
|
|
|
|
|
| 145 |
$response = parent::update_item( $request );
|
| 146 |
if ( is_wp_error( $response ) ) {
|
| 147 |
return $response;
|
|
@@ -204,6 +222,7 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 204 |
$data['caption'] = $post->post_excerpt;
|
| 205 |
$data['description'] = $post->post_content;
|
| 206 |
$data['media_type'] = wp_attachment_is_image( $post->ID ) ? 'image' : 'file';
|
|
|
|
| 207 |
$data['media_details'] = wp_get_attachment_metadata( $post->ID );
|
| 208 |
$data['post'] = ! empty( $post->post_parent ) ? (int) $post->post_parent : null;
|
| 209 |
$data['source_url'] = wp_get_attachment_url( $post->ID );
|
|
@@ -275,54 +294,60 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 275 |
$schema = parent::get_item_schema();
|
| 276 |
|
| 277 |
$schema['properties']['alt_text'] = array(
|
| 278 |
-
'description' => __( 'Alternative text to display when
|
| 279 |
'type' => 'string',
|
| 280 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 281 |
'arg_options' => array(
|
| 282 |
'sanitize_callback' => 'sanitize_text_field',
|
| 283 |
),
|
| 284 |
-
|
| 285 |
$schema['properties']['caption'] = array(
|
| 286 |
-
'description' => __( 'The caption for the
|
| 287 |
'type' => 'string',
|
| 288 |
'context' => array( 'view', 'edit' ),
|
| 289 |
'arg_options' => array(
|
| 290 |
'sanitize_callback' => 'wp_filter_post_kses',
|
| 291 |
),
|
| 292 |
-
|
| 293 |
$schema['properties']['description'] = array(
|
| 294 |
-
'description' => __( 'The description for the
|
| 295 |
'type' => 'string',
|
| 296 |
'context' => array( 'view', 'edit' ),
|
| 297 |
'arg_options' => array(
|
| 298 |
'sanitize_callback' => 'wp_filter_post_kses',
|
| 299 |
),
|
| 300 |
-
|
| 301 |
$schema['properties']['media_type'] = array(
|
| 302 |
-
'description' => __( 'Type of
|
| 303 |
'type' => 'string',
|
| 304 |
'enum' => array( 'image', 'file' ),
|
| 305 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 306 |
'readonly' => true,
|
| 307 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
$schema['properties']['media_details'] = array(
|
| 309 |
-
'description' => __( 'Details about the
|
| 310 |
'type' => 'object',
|
| 311 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 312 |
'readonly' => true,
|
| 313 |
-
|
| 314 |
$schema['properties']['post'] = array(
|
| 315 |
-
'description' => __( 'The id for the associated post of the
|
| 316 |
'type' => 'integer',
|
| 317 |
'context' => array( 'view', 'edit' ),
|
| 318 |
-
|
| 319 |
$schema['properties']['source_url'] = array(
|
| 320 |
-
'description' => __( 'URL to the original
|
| 321 |
'type' => 'string',
|
| 322 |
'format' => 'uri',
|
| 323 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 324 |
'readonly' => true,
|
| 325 |
-
|
| 326 |
return $schema;
|
| 327 |
}
|
| 328 |
|
|
@@ -423,6 +448,19 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 423 |
$params = parent::get_collection_params();
|
| 424 |
$params['status']['default'] = 'inherit';
|
| 425 |
$params['status']['enum'] = array( 'inherit', 'private', 'trash' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 426 |
return $params;
|
| 427 |
}
|
| 428 |
|
|
@@ -483,4 +521,22 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
|
|
| 483 |
return $file;
|
| 484 |
}
|
| 485 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 486 |
}
|
| 6 |
* Determine the allowed query_vars for a get_items() response and
|
| 7 |
* prepare for WP_Query.
|
| 8 |
*
|
| 9 |
+
* @param array $prepared_args
|
| 10 |
+
* @param WP_REST_Request $request
|
| 11 |
+
* @return array $query_args
|
| 12 |
*/
|
| 13 |
+
protected function prepare_items_query( $prepared_args = array(), $request = null ) {
|
| 14 |
+
$query_args = parent::prepare_items_query( $prepared_args, $request );
|
| 15 |
if ( empty( $query_args['post_status'] ) || ! in_array( $query_args['post_status'], array( 'inherit', 'private', 'trash' ) ) ) {
|
| 16 |
$query_args['post_status'] = 'inherit';
|
| 17 |
}
|
| 18 |
+
$media_types = $this->get_media_types();
|
| 19 |
+
if ( ! empty( $request['media_type'] ) && in_array( $request['media_type'], array_keys( $media_types ) ) ) {
|
| 20 |
+
$query_args['post_mime_type'] = $media_types[ $request['media_type'] ];
|
| 21 |
+
}
|
| 22 |
+
if ( ! empty( $request['mime_type'] ) ) {
|
| 23 |
+
$parts = explode( '/', $request['mime_type'] );
|
| 24 |
+
if ( isset( $media_types[ $parts[0] ] ) && in_array( $request['mime_type'], $media_types[ $parts[0] ] ) ) {
|
| 25 |
+
$query_args['post_mime_type'] = $request['mime_type'];
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
return $query_args;
|
| 29 |
}
|
| 30 |
|
| 51 |
$parent = get_post( (int) $request['post'] );
|
| 52 |
$post_parent_type = get_post_type_object( $parent->post_type );
|
| 53 |
if ( ! current_user_can( $post_parent_type->cap->edit_post, $request['post'] ) ) {
|
| 54 |
+
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to upload media to this resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 55 |
}
|
| 56 |
}
|
| 57 |
|
| 66 |
*/
|
| 67 |
public function create_item( $request ) {
|
| 68 |
|
| 69 |
+
if ( ! empty( $request['post'] ) && in_array( get_post_type( $request['post'] ), array( 'revision', 'attachment' ) ) ) {
|
| 70 |
+
return new WP_Error( 'rest_invalid_param', __( 'Invalid parent type.' ), array( 'status' => 400 ) );
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
// Get the file via $_FILES or raw data
|
| 74 |
$files = $request->get_file_params();
|
| 75 |
$headers = $request->get_headers();
|
| 135 |
$response = $this->prepare_item_for_response( $attachment, $request );
|
| 136 |
$response = rest_ensure_response( $response );
|
| 137 |
$response->set_status( 201 );
|
| 138 |
+
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $id ) ) );
|
| 139 |
|
| 140 |
/**
|
| 141 |
* Fires after a single attachment is created or updated via the REST API.
|
| 157 |
* @return WP_Error|WP_REST_Response
|
| 158 |
*/
|
| 159 |
public function update_item( $request ) {
|
| 160 |
+
if ( ! empty( $request['post'] ) && in_array( get_post_type( $request['post'] ), array( 'revision', 'attachment' ) ) ) {
|
| 161 |
+
return new WP_Error( 'rest_invalid_param', __( 'Invalid parent type.' ), array( 'status' => 400 ) );
|
| 162 |
+
}
|
| 163 |
$response = parent::update_item( $request );
|
| 164 |
if ( is_wp_error( $response ) ) {
|
| 165 |
return $response;
|
| 222 |
$data['caption'] = $post->post_excerpt;
|
| 223 |
$data['description'] = $post->post_content;
|
| 224 |
$data['media_type'] = wp_attachment_is_image( $post->ID ) ? 'image' : 'file';
|
| 225 |
+
$data['mime_type'] = $post->post_mime_type;
|
| 226 |
$data['media_details'] = wp_get_attachment_metadata( $post->ID );
|
| 227 |
$data['post'] = ! empty( $post->post_parent ) ? (int) $post->post_parent : null;
|
| 228 |
$data['source_url'] = wp_get_attachment_url( $post->ID );
|
| 294 |
$schema = parent::get_item_schema();
|
| 295 |
|
| 296 |
$schema['properties']['alt_text'] = array(
|
| 297 |
+
'description' => __( 'Alternative text to display when resource is not displayed.' ),
|
| 298 |
'type' => 'string',
|
| 299 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 300 |
'arg_options' => array(
|
| 301 |
'sanitize_callback' => 'sanitize_text_field',
|
| 302 |
),
|
| 303 |
+
);
|
| 304 |
$schema['properties']['caption'] = array(
|
| 305 |
+
'description' => __( 'The caption for the resource.' ),
|
| 306 |
'type' => 'string',
|
| 307 |
'context' => array( 'view', 'edit' ),
|
| 308 |
'arg_options' => array(
|
| 309 |
'sanitize_callback' => 'wp_filter_post_kses',
|
| 310 |
),
|
| 311 |
+
);
|
| 312 |
$schema['properties']['description'] = array(
|
| 313 |
+
'description' => __( 'The description for the resource.' ),
|
| 314 |
'type' => 'string',
|
| 315 |
'context' => array( 'view', 'edit' ),
|
| 316 |
'arg_options' => array(
|
| 317 |
'sanitize_callback' => 'wp_filter_post_kses',
|
| 318 |
),
|
| 319 |
+
);
|
| 320 |
$schema['properties']['media_type'] = array(
|
| 321 |
+
'description' => __( 'Type of resource.' ),
|
| 322 |
'type' => 'string',
|
| 323 |
'enum' => array( 'image', 'file' ),
|
| 324 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 325 |
'readonly' => true,
|
| 326 |
+
);
|
| 327 |
+
$schema['properties']['mime_type'] = array(
|
| 328 |
+
'description' => __( 'Mime type of resource.' ),
|
| 329 |
+
'type' => 'string',
|
| 330 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 331 |
+
'readonly' => true,
|
| 332 |
+
);
|
| 333 |
$schema['properties']['media_details'] = array(
|
| 334 |
+
'description' => __( 'Details about the resource file, specific to its type.' ),
|
| 335 |
'type' => 'object',
|
| 336 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 337 |
'readonly' => true,
|
| 338 |
+
);
|
| 339 |
$schema['properties']['post'] = array(
|
| 340 |
+
'description' => __( 'The id for the associated post of the resource.' ),
|
| 341 |
'type' => 'integer',
|
| 342 |
'context' => array( 'view', 'edit' ),
|
| 343 |
+
);
|
| 344 |
$schema['properties']['source_url'] = array(
|
| 345 |
+
'description' => __( 'URL to the original resource file.' ),
|
| 346 |
'type' => 'string',
|
| 347 |
'format' => 'uri',
|
| 348 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 349 |
'readonly' => true,
|
| 350 |
+
);
|
| 351 |
return $schema;
|
| 352 |
}
|
| 353 |
|
| 448 |
$params = parent::get_collection_params();
|
| 449 |
$params['status']['default'] = 'inherit';
|
| 450 |
$params['status']['enum'] = array( 'inherit', 'private', 'trash' );
|
| 451 |
+
$media_types = $this->get_media_types();
|
| 452 |
+
$params['media_type'] = array(
|
| 453 |
+
'default' => null,
|
| 454 |
+
'description' => __( 'Limit result set to attachments of a particular media type.' ),
|
| 455 |
+
'type' => 'string',
|
| 456 |
+
'enum' => array_keys( $media_types ),
|
| 457 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 458 |
+
);
|
| 459 |
+
$params['mime_type'] = array(
|
| 460 |
+
'default' => null,
|
| 461 |
+
'description' => __( 'Limit result set to attachments of a particular mime type.' ),
|
| 462 |
+
'type' => 'string',
|
| 463 |
+
);
|
| 464 |
return $params;
|
| 465 |
}
|
| 466 |
|
| 521 |
return $file;
|
| 522 |
}
|
| 523 |
|
| 524 |
+
/**
|
| 525 |
+
* Get the supported media types.
|
| 526 |
+
* Media types are considered the mime type category
|
| 527 |
+
*
|
| 528 |
+
* @return array
|
| 529 |
+
*/
|
| 530 |
+
protected function get_media_types() {
|
| 531 |
+
$media_types = array();
|
| 532 |
+
foreach ( get_allowed_mime_types() as $mime_type ) {
|
| 533 |
+
$parts = explode( '/', $mime_type );
|
| 534 |
+
if ( ! isset( $media_types[ $parts[0] ] ) ) {
|
| 535 |
+
$media_types[ $parts[0] ] = array();
|
| 536 |
+
}
|
| 537 |
+
$media_types[ $parts[0] ][] = $mime_type;
|
| 538 |
+
}
|
| 539 |
+
return $media_types;
|
| 540 |
+
}
|
| 541 |
+
|
| 542 |
}
|
lib/endpoints/class-wp-rest-comments-controller.php
CHANGED
|
@@ -5,12 +5,17 @@
|
|
| 5 |
*/
|
| 6 |
class WP_REST_Comments_Controller extends WP_REST_Controller {
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
/**
|
| 9 |
* Register the routes for the objects of the controller.
|
| 10 |
*/
|
| 11 |
public function register_routes() {
|
| 12 |
|
| 13 |
-
register_rest_route(
|
| 14 |
array(
|
| 15 |
'methods' => WP_REST_Server::READABLE,
|
| 16 |
'callback' => array( $this, 'get_items' ),
|
|
@@ -23,11 +28,10 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 23 |
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
| 24 |
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
| 25 |
),
|
| 26 |
-
|
| 27 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 28 |
) );
|
| 29 |
|
| 30 |
-
register_rest_route( '
|
| 31 |
array(
|
| 32 |
'methods' => WP_REST_Server::READABLE,
|
| 33 |
'callback' => array( $this, 'get_item' ),
|
|
@@ -53,7 +57,6 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 53 |
),
|
| 54 |
),
|
| 55 |
),
|
| 56 |
-
|
| 57 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 58 |
) );
|
| 59 |
}
|
|
@@ -66,12 +69,14 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 66 |
*/
|
| 67 |
public function get_items_permissions_check( $request ) {
|
| 68 |
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
|
|
|
|
|
|
| 75 |
}
|
| 76 |
}
|
| 77 |
|
|
@@ -79,6 +84,27 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 79 |
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you cannot view comments with edit context.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 80 |
}
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
return true;
|
| 83 |
}
|
| 84 |
|
|
@@ -90,41 +116,29 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 90 |
*/
|
| 91 |
public function get_items( $request ) {
|
| 92 |
$prepared_args = array(
|
|
|
|
| 93 |
'comment__in' => $request['include'],
|
| 94 |
'comment__not_in' => $request['exclude'],
|
|
|
|
| 95 |
'number' => $request['per_page'],
|
| 96 |
-
'
|
| 97 |
-
'
|
|
|
|
| 98 |
'search' => $request['search'],
|
| 99 |
'offset' => $request['offset'],
|
| 100 |
'orderby' => $this->normalize_query_param( $request['orderby'] ),
|
| 101 |
'order' => $request['order'],
|
| 102 |
-
'status' => '
|
| 103 |
-
'type' => '
|
| 104 |
'no_found_rows' => false,
|
|
|
|
|
|
|
| 105 |
);
|
| 106 |
|
| 107 |
if ( empty( $request['offset'] ) ) {
|
| 108 |
$prepared_args['offset'] = $prepared_args['number'] * ( absint( $request['page'] ) - 1 );
|
| 109 |
}
|
| 110 |
|
| 111 |
-
if ( current_user_can( 'edit_posts' ) ) {
|
| 112 |
-
$protected_args = array(
|
| 113 |
-
'user_id' => $request['author'] ? $request['author'] : '',
|
| 114 |
-
'status' => $request['status'],
|
| 115 |
-
'type' => isset( $request['type'] ) ? $request['type'] : '',
|
| 116 |
-
'author_email' => isset( $request['author_email'] ) ? $request['author_email'] : '',
|
| 117 |
-
'karma' => isset( $request['karma'] ) ? $request['karma'] : '',
|
| 118 |
-
'post_author' => isset( $request['post_author'] ) ? $request['post_author'] : '',
|
| 119 |
-
'post_name' => isset( $request['post_slug'] ) ? $request['post_slug'] : '',
|
| 120 |
-
'post_parent' => isset( $request['post_parent'] ) ? $request['post_parent'] : '',
|
| 121 |
-
'post_status' => isset( $request['post_status'] ) ? $request['post_status'] : '',
|
| 122 |
-
'post_type' => isset( $request['post_type'] ) ? $request['post_type'] : '',
|
| 123 |
-
);
|
| 124 |
-
|
| 125 |
-
$prepared_args = array_merge( $prepared_args, $protected_args );
|
| 126 |
-
}
|
| 127 |
-
|
| 128 |
/**
|
| 129 |
* Filter arguments, before passing to WP_Comment_Query, when querying comments via the REST API.
|
| 130 |
*
|
|
@@ -140,8 +154,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 140 |
|
| 141 |
$comments = array();
|
| 142 |
foreach ( $query_result as $comment ) {
|
| 143 |
-
|
| 144 |
-
if ( ! $this->check_read_post_permission( $post ) || ! $this->check_read_permission( $comment ) ) {
|
| 145 |
continue;
|
| 146 |
}
|
| 147 |
|
|
@@ -166,7 +179,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 166 |
$response->header( 'X-WP-Total', $total_comments );
|
| 167 |
$response->header( 'X-WP-TotalPages', $max_pages );
|
| 168 |
|
| 169 |
-
$base = add_query_arg( $request->get_query_params(), rest_url( '
|
| 170 |
if ( $request['page'] > 1 ) {
|
| 171 |
$prev_page = $request['page'] - 1;
|
| 172 |
if ( $prev_page > $max_pages ) {
|
|
@@ -343,19 +356,15 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 343 |
$this->handle_status_param( $request['status'], $comment );
|
| 344 |
}
|
| 345 |
|
| 346 |
-
$
|
|
|
|
| 347 |
|
| 348 |
$context = current_user_can( 'moderate_comments' ) ? 'edit' : 'view';
|
| 349 |
-
$
|
| 350 |
-
$
|
| 351 |
-
$get_request->set_param( 'context', $context );
|
| 352 |
-
$response = $this->get_item( $get_request );
|
| 353 |
$response = rest_ensure_response( $response );
|
| 354 |
-
if ( is_wp_error( $response ) ) {
|
| 355 |
-
return $response;
|
| 356 |
-
}
|
| 357 |
$response->set_status( 201 );
|
| 358 |
-
$response->header( 'Location', rest_url( '
|
| 359 |
|
| 360 |
/**
|
| 361 |
* Fires after a comment is created or updated via the REST API.
|
|
@@ -482,14 +491,11 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 482 |
*/
|
| 483 |
$supports_trash = apply_filters( 'rest_comment_trashable', ( EMPTY_TRASH_DAYS > 0 ), $comment );
|
| 484 |
|
| 485 |
-
$
|
| 486 |
-
$
|
| 487 |
-
$get_request->set_param( 'context', 'edit' );
|
| 488 |
-
$response = $this->prepare_item_for_response( $comment, $get_request );
|
| 489 |
|
| 490 |
if ( $force ) {
|
| 491 |
$result = wp_delete_comment( $comment->comment_ID, true );
|
| 492 |
-
$status = 'deleted';
|
| 493 |
} else {
|
| 494 |
// If we don't support trashing for this type, error out
|
| 495 |
if ( ! $supports_trash ) {
|
|
@@ -501,16 +507,8 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 501 |
}
|
| 502 |
|
| 503 |
$result = wp_trash_comment( $comment->comment_ID );
|
| 504 |
-
$status = 'trashed';
|
| 505 |
}
|
| 506 |
|
| 507 |
-
$data = $response->get_data();
|
| 508 |
-
$data = array(
|
| 509 |
-
'data' => $data,
|
| 510 |
-
$status => true,
|
| 511 |
-
);
|
| 512 |
-
$response->set_data( $data );
|
| 513 |
-
|
| 514 |
if ( ! $result ) {
|
| 515 |
return new WP_Error( 'rest_cannot_delete', __( 'The comment cannot be deleted.' ), array( 'status' => 500 ) );
|
| 516 |
}
|
|
@@ -518,11 +516,11 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 518 |
/**
|
| 519 |
* Fires after a comment is deleted via the REST API.
|
| 520 |
*
|
| 521 |
-
* @param object
|
| 522 |
-
* @param
|
| 523 |
-
* @param WP_REST_Request
|
| 524 |
*/
|
| 525 |
-
do_action( 'rest_delete_comment', $comment, $
|
| 526 |
|
| 527 |
return $response;
|
| 528 |
}
|
|
@@ -588,10 +586,10 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 588 |
protected function prepare_links( $comment ) {
|
| 589 |
$links = array(
|
| 590 |
'self' => array(
|
| 591 |
-
'href' => rest_url( '
|
| 592 |
),
|
| 593 |
'collection' => array(
|
| 594 |
-
'href' => rest_url( '
|
| 595 |
),
|
| 596 |
);
|
| 597 |
|
|
@@ -605,8 +603,8 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 605 |
if ( 0 !== (int) $comment->comment_post_ID ) {
|
| 606 |
$post = get_post( $comment->comment_post_ID );
|
| 607 |
if ( ! empty( $post->ID ) ) {
|
| 608 |
-
$
|
| 609 |
-
$base = $
|
| 610 |
|
| 611 |
$links['up'] = array(
|
| 612 |
'href' => rest_url( '/wp/v2/' . $base . '/' . $comment->comment_post_ID ),
|
|
@@ -618,7 +616,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 618 |
|
| 619 |
if ( 0 !== (int) $comment->comment_parent ) {
|
| 620 |
$links['in-reply-to'] = array(
|
| 621 |
-
'href' => rest_url( sprintf( '
|
| 622 |
'embeddable' => true,
|
| 623 |
);
|
| 624 |
}
|
|
@@ -832,7 +830,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 832 |
'context' => array( 'edit' ),
|
| 833 |
),
|
| 834 |
'rendered' => array(
|
| 835 |
-
'description' => __( '
|
| 836 |
'type' => 'string',
|
| 837 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 838 |
),
|
|
@@ -914,11 +912,24 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 914 |
|
| 915 |
$query_params['context']['default'] = 'view';
|
| 916 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 917 |
$query_params['author_email'] = array(
|
| 918 |
'default' => null,
|
| 919 |
-
'description' => __( 'Limit result set to that from a specific author email.' ),
|
| 920 |
'format' => 'email',
|
| 921 |
'sanitize_callback' => 'sanitize_email',
|
|
|
|
| 922 |
'type' => 'string',
|
| 923 |
);
|
| 924 |
$query_params['exclude'] = array(
|
|
@@ -926,28 +937,33 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 926 |
'type' => 'array',
|
| 927 |
'default' => array(),
|
| 928 |
'sanitize_callback' => 'wp_parse_id_list',
|
|
|
|
| 929 |
);
|
| 930 |
$query_params['include'] = array(
|
| 931 |
'description' => __( 'Limit result set to specific ids.' ),
|
| 932 |
'type' => 'array',
|
| 933 |
'default' => array(),
|
| 934 |
'sanitize_callback' => 'wp_parse_id_list',
|
|
|
|
| 935 |
);
|
| 936 |
$query_params['karma'] = array(
|
| 937 |
'default' => null,
|
| 938 |
-
'description' => __( 'Limit result set to that of a particular comment karma.' ),
|
| 939 |
'sanitize_callback' => 'absint',
|
| 940 |
'type' => 'integer',
|
|
|
|
| 941 |
);
|
| 942 |
$query_params['offset'] = array(
|
| 943 |
'description' => __( 'Offset the result set by a specific number of comments.' ),
|
| 944 |
'type' => 'integer',
|
| 945 |
'sanitize_callback' => 'absint',
|
|
|
|
| 946 |
);
|
| 947 |
$query_params['order'] = array(
|
| 948 |
'description' => __( 'Order sort attribute ascending or descending.' ),
|
| 949 |
'type' => 'string',
|
| 950 |
'sanitize_callback' => 'sanitize_key',
|
|
|
|
| 951 |
'default' => 'asc',
|
| 952 |
'enum' => array(
|
| 953 |
'asc',
|
|
@@ -958,6 +974,7 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 958 |
'description' => __( 'Sort collection by object attribute.' ),
|
| 959 |
'type' => 'string',
|
| 960 |
'sanitize_callback' => 'sanitize_key',
|
|
|
|
| 961 |
'default' => 'date_gmt',
|
| 962 |
'enum' => array(
|
| 963 |
'date',
|
|
@@ -970,63 +987,39 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 970 |
),
|
| 971 |
);
|
| 972 |
$query_params['parent'] = array(
|
| 973 |
-
'default' =>
|
| 974 |
-
'description' => __( 'Limit result set to
|
| 975 |
-
'sanitize_callback' => '
|
| 976 |
-
'type' => '
|
|
|
|
| 977 |
);
|
| 978 |
-
$query_params['
|
| 979 |
-
'default' =>
|
| 980 |
-
'description' => __( '
|
| 981 |
-
'sanitize_callback' => '
|
| 982 |
-
'type' => '
|
| 983 |
-
|
| 984 |
-
$query_params['post_author'] = array(
|
| 985 |
-
'default' => null,
|
| 986 |
-
'description' => __( 'Limit result set to comments associated with posts of a specific post author id.' ),
|
| 987 |
-
'sanitize_callback' => 'absint',
|
| 988 |
-
'type' => 'integer',
|
| 989 |
-
);
|
| 990 |
-
$query_params['post_slug'] = array(
|
| 991 |
-
'default' => null,
|
| 992 |
-
'description' => __( 'Limit result set to comments associated with posts of a specific post slug.' ),
|
| 993 |
-
'sanitize_callback' => 'sanitize_title',
|
| 994 |
-
'type' => 'string',
|
| 995 |
-
);
|
| 996 |
-
$query_params['post_parent'] = array(
|
| 997 |
-
'default' => null,
|
| 998 |
-
'description' => __( 'Limit result set to comments associated with posts of a specific post parent id.' ),
|
| 999 |
-
'sanitize_callback' => 'absint',
|
| 1000 |
-
'type' => 'integer',
|
| 1001 |
-
);
|
| 1002 |
-
$query_params['post_status'] = array(
|
| 1003 |
-
'default' => null,
|
| 1004 |
-
'description' => __( 'Limit result set to comments associated with posts of a specific post status.' ),
|
| 1005 |
-
'sanitize_callback' => 'sanitize_key',
|
| 1006 |
-
'type' => 'string',
|
| 1007 |
);
|
| 1008 |
-
$query_params['
|
| 1009 |
-
'default' =>
|
| 1010 |
-
'description' => __( 'Limit result set to
|
| 1011 |
-
'
|
| 1012 |
-
'
|
|
|
|
| 1013 |
);
|
| 1014 |
$query_params['status'] = array(
|
| 1015 |
'default' => 'approve',
|
| 1016 |
-
'description' => __( 'Limit result set to comments assigned a specific status.' ),
|
| 1017 |
'sanitize_callback' => 'sanitize_key',
|
| 1018 |
'type' => 'string',
|
|
|
|
| 1019 |
);
|
| 1020 |
$query_params['type'] = array(
|
| 1021 |
'default' => 'comment',
|
| 1022 |
-
'description' => __( 'Limit result set to comments assigned a specific type.' ),
|
| 1023 |
'sanitize_callback' => 'sanitize_key',
|
| 1024 |
'type' => 'string',
|
| 1025 |
-
|
| 1026 |
-
$query_params['author'] = array(
|
| 1027 |
-
'description' => __( 'Limit result set to comments assigned to a specific user id.' ),
|
| 1028 |
-
'sanitize_callback' => 'absint',
|
| 1029 |
-
'type' => 'integer',
|
| 1030 |
);
|
| 1031 |
return $query_params;
|
| 1032 |
}
|
|
@@ -1105,6 +1098,17 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
|
|
| 1105 |
return false;
|
| 1106 |
}
|
| 1107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1108 |
if ( ! empty( $comment->user_id ) && get_current_user_id() === (int) $comment->user_id ) {
|
| 1109 |
return true;
|
| 1110 |
}
|
| 5 |
*/
|
| 6 |
class WP_REST_Comments_Controller extends WP_REST_Controller {
|
| 7 |
|
| 8 |
+
public function __construct() {
|
| 9 |
+
$this->namespace = 'wp/v2';
|
| 10 |
+
$this->rest_base = 'comments';
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
/**
|
| 14 |
* Register the routes for the objects of the controller.
|
| 15 |
*/
|
| 16 |
public function register_routes() {
|
| 17 |
|
| 18 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
|
| 19 |
array(
|
| 20 |
'methods' => WP_REST_Server::READABLE,
|
| 21 |
'callback' => array( $this, 'get_items' ),
|
| 28 |
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
| 29 |
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
| 30 |
),
|
|
|
|
| 31 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 32 |
) );
|
| 33 |
|
| 34 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
|
| 35 |
array(
|
| 36 |
'methods' => WP_REST_Server::READABLE,
|
| 37 |
'callback' => array( $this, 'get_item' ),
|
| 57 |
),
|
| 58 |
),
|
| 59 |
),
|
|
|
|
| 60 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 61 |
) );
|
| 62 |
}
|
| 69 |
*/
|
| 70 |
public function get_items_permissions_check( $request ) {
|
| 71 |
|
| 72 |
+
if ( ! empty( $request['post'] ) ) {
|
| 73 |
+
foreach ( $request['post'] as $post_id ) {
|
| 74 |
+
$post = get_post( $post_id );
|
| 75 |
+
if ( ! empty( $post_id ) && $post && ! $this->check_read_post_permission( $post ) ) {
|
| 76 |
+
return new WP_Error( 'rest_cannot_read_post', __( 'Sorry, you cannot read the post for this comment.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 77 |
+
} else if ( 0 === $post_id && ! current_user_can( 'moderate_comments' ) ) {
|
| 78 |
+
return new WP_Error( 'rest_cannot_read', __( 'Sorry, you cannot read comments without a post.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 79 |
+
}
|
| 80 |
}
|
| 81 |
}
|
| 82 |
|
| 84 |
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you cannot view comments with edit context.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 85 |
}
|
| 86 |
|
| 87 |
+
if ( ! current_user_can( 'edit_posts' ) ) {
|
| 88 |
+
$protected_params = array( 'author', 'author_exclude', 'karma', 'author_email', 'type', 'status' );
|
| 89 |
+
$forbidden_params = array();
|
| 90 |
+
foreach ( $protected_params as $param ) {
|
| 91 |
+
if ( 'status' === $param ) {
|
| 92 |
+
if ( 'approve' !== $request[ $param ] ) {
|
| 93 |
+
$forbidden_params[] = $param;
|
| 94 |
+
}
|
| 95 |
+
} else if ( 'type' === $param ) {
|
| 96 |
+
if ( 'comment' !== $request[ $param ] ) {
|
| 97 |
+
$forbidden_params[] = $param;
|
| 98 |
+
}
|
| 99 |
+
} else if ( ! empty( $request[ $param ] ) ) {
|
| 100 |
+
$forbidden_params[] = $param;
|
| 101 |
+
}
|
| 102 |
+
}
|
| 103 |
+
if ( ! empty( $forbidden_params ) ) {
|
| 104 |
+
return new WP_Error( 'rest_forbidden_param', sprintf( __( 'Query parameter not permitted: %s' ), implode( ', ', $forbidden_params ) ), array( 'status' => rest_authorization_required_code() ) );
|
| 105 |
+
}
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
return true;
|
| 109 |
}
|
| 110 |
|
| 116 |
*/
|
| 117 |
public function get_items( $request ) {
|
| 118 |
$prepared_args = array(
|
| 119 |
+
'author_email' => isset( $request['author_email'] ) ? $request['author_email'] : '',
|
| 120 |
'comment__in' => $request['include'],
|
| 121 |
'comment__not_in' => $request['exclude'],
|
| 122 |
+
'karma' => isset( $request['karma'] ) ? $request['karma'] : '',
|
| 123 |
'number' => $request['per_page'],
|
| 124 |
+
'post__in' => $request['post'],
|
| 125 |
+
'parent__in' => $request['parent'],
|
| 126 |
+
'parent__not_in' => $request['parent_exclude'],
|
| 127 |
'search' => $request['search'],
|
| 128 |
'offset' => $request['offset'],
|
| 129 |
'orderby' => $this->normalize_query_param( $request['orderby'] ),
|
| 130 |
'order' => $request['order'],
|
| 131 |
+
'status' => $request['status'],
|
| 132 |
+
'type' => $request['type'],
|
| 133 |
'no_found_rows' => false,
|
| 134 |
+
'author__in' => $request['author'],
|
| 135 |
+
'author__not_in' => $request['author_exclude'],
|
| 136 |
);
|
| 137 |
|
| 138 |
if ( empty( $request['offset'] ) ) {
|
| 139 |
$prepared_args['offset'] = $prepared_args['number'] * ( absint( $request['page'] ) - 1 );
|
| 140 |
}
|
| 141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
/**
|
| 143 |
* Filter arguments, before passing to WP_Comment_Query, when querying comments via the REST API.
|
| 144 |
*
|
| 154 |
|
| 155 |
$comments = array();
|
| 156 |
foreach ( $query_result as $comment ) {
|
| 157 |
+
if ( ! $this->check_read_permission( $comment ) ) {
|
|
|
|
| 158 |
continue;
|
| 159 |
}
|
| 160 |
|
| 179 |
$response->header( 'X-WP-Total', $total_comments );
|
| 180 |
$response->header( 'X-WP-TotalPages', $max_pages );
|
| 181 |
|
| 182 |
+
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
|
| 183 |
if ( $request['page'] > 1 ) {
|
| 184 |
$prev_page = $request['page'] - 1;
|
| 185 |
if ( $prev_page > $max_pages ) {
|
| 356 |
$this->handle_status_param( $request['status'], $comment );
|
| 357 |
}
|
| 358 |
|
| 359 |
+
$comment = get_comment( $comment_id );
|
| 360 |
+
$this->update_additional_fields_for_object( $comment, $request );
|
| 361 |
|
| 362 |
$context = current_user_can( 'moderate_comments' ) ? 'edit' : 'view';
|
| 363 |
+
$request->set_param( 'context', $context );
|
| 364 |
+
$response = $this->prepare_item_for_response( $comment, $request );
|
|
|
|
|
|
|
| 365 |
$response = rest_ensure_response( $response );
|
|
|
|
|
|
|
|
|
|
| 366 |
$response->set_status( 201 );
|
| 367 |
+
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $comment_id ) ) );
|
| 368 |
|
| 369 |
/**
|
| 370 |
* Fires after a comment is created or updated via the REST API.
|
| 491 |
*/
|
| 492 |
$supports_trash = apply_filters( 'rest_comment_trashable', ( EMPTY_TRASH_DAYS > 0 ), $comment );
|
| 493 |
|
| 494 |
+
$request->set_param( 'context', 'edit' );
|
| 495 |
+
$response = $this->prepare_item_for_response( $comment, $request );
|
|
|
|
|
|
|
| 496 |
|
| 497 |
if ( $force ) {
|
| 498 |
$result = wp_delete_comment( $comment->comment_ID, true );
|
|
|
|
| 499 |
} else {
|
| 500 |
// If we don't support trashing for this type, error out
|
| 501 |
if ( ! $supports_trash ) {
|
| 507 |
}
|
| 508 |
|
| 509 |
$result = wp_trash_comment( $comment->comment_ID );
|
|
|
|
| 510 |
}
|
| 511 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 512 |
if ( ! $result ) {
|
| 513 |
return new WP_Error( 'rest_cannot_delete', __( 'The comment cannot be deleted.' ), array( 'status' => 500 ) );
|
| 514 |
}
|
| 516 |
/**
|
| 517 |
* Fires after a comment is deleted via the REST API.
|
| 518 |
*
|
| 519 |
+
* @param object $comment The deleted comment data.
|
| 520 |
+
* @param WP_REST_Response $response The response returned from the API.
|
| 521 |
+
* @param WP_REST_Request $request The request sent to the API.
|
| 522 |
*/
|
| 523 |
+
do_action( 'rest_delete_comment', $comment, $response, $request );
|
| 524 |
|
| 525 |
return $response;
|
| 526 |
}
|
| 586 |
protected function prepare_links( $comment ) {
|
| 587 |
$links = array(
|
| 588 |
'self' => array(
|
| 589 |
+
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $comment->comment_ID ) ),
|
| 590 |
),
|
| 591 |
'collection' => array(
|
| 592 |
+
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
| 593 |
),
|
| 594 |
);
|
| 595 |
|
| 603 |
if ( 0 !== (int) $comment->comment_post_ID ) {
|
| 604 |
$post = get_post( $comment->comment_post_ID );
|
| 605 |
if ( ! empty( $post->ID ) ) {
|
| 606 |
+
$obj = get_post_type_object( $post->post_type );
|
| 607 |
+
$base = ! empty( $obj->rest_base ) ? $obj->rest_base : $obj->name;
|
| 608 |
|
| 609 |
$links['up'] = array(
|
| 610 |
'href' => rest_url( '/wp/v2/' . $base . '/' . $comment->comment_post_ID ),
|
| 616 |
|
| 617 |
if ( 0 !== (int) $comment->comment_parent ) {
|
| 618 |
$links['in-reply-to'] = array(
|
| 619 |
+
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $comment->comment_parent ) ),
|
| 620 |
'embeddable' => true,
|
| 621 |
);
|
| 622 |
}
|
| 830 |
'context' => array( 'edit' ),
|
| 831 |
),
|
| 832 |
'rendered' => array(
|
| 833 |
+
'description' => __( 'HTML content for the object, transformed for display.' ),
|
| 834 |
'type' => 'string',
|
| 835 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 836 |
),
|
| 912 |
|
| 913 |
$query_params['context']['default'] = 'view';
|
| 914 |
|
| 915 |
+
$query_params['author'] = array(
|
| 916 |
+
'description' => __( 'Limit result set to comments assigned to specific user ids. Requires authorization.' ),
|
| 917 |
+
'sanitize_callback' => 'wp_parse_id_list',
|
| 918 |
+
'type' => 'array',
|
| 919 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 920 |
+
);
|
| 921 |
+
$query_params['author_exclude'] = array(
|
| 922 |
+
'description' => __( 'Ensure result set excludes comments assigned to specific user ids. Requires authorization.' ),
|
| 923 |
+
'sanitize_callback' => 'wp_parse_id_list',
|
| 924 |
+
'type' => 'array',
|
| 925 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 926 |
+
);
|
| 927 |
$query_params['author_email'] = array(
|
| 928 |
'default' => null,
|
| 929 |
+
'description' => __( 'Limit result set to that from a specific author email. Requires authorization.' ),
|
| 930 |
'format' => 'email',
|
| 931 |
'sanitize_callback' => 'sanitize_email',
|
| 932 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 933 |
'type' => 'string',
|
| 934 |
);
|
| 935 |
$query_params['exclude'] = array(
|
| 937 |
'type' => 'array',
|
| 938 |
'default' => array(),
|
| 939 |
'sanitize_callback' => 'wp_parse_id_list',
|
| 940 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 941 |
);
|
| 942 |
$query_params['include'] = array(
|
| 943 |
'description' => __( 'Limit result set to specific ids.' ),
|
| 944 |
'type' => 'array',
|
| 945 |
'default' => array(),
|
| 946 |
'sanitize_callback' => 'wp_parse_id_list',
|
| 947 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 948 |
);
|
| 949 |
$query_params['karma'] = array(
|
| 950 |
'default' => null,
|
| 951 |
+
'description' => __( 'Limit result set to that of a particular comment karma. Requires authorization.' ),
|
| 952 |
'sanitize_callback' => 'absint',
|
| 953 |
'type' => 'integer',
|
| 954 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 955 |
);
|
| 956 |
$query_params['offset'] = array(
|
| 957 |
'description' => __( 'Offset the result set by a specific number of comments.' ),
|
| 958 |
'type' => 'integer',
|
| 959 |
'sanitize_callback' => 'absint',
|
| 960 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 961 |
);
|
| 962 |
$query_params['order'] = array(
|
| 963 |
'description' => __( 'Order sort attribute ascending or descending.' ),
|
| 964 |
'type' => 'string',
|
| 965 |
'sanitize_callback' => 'sanitize_key',
|
| 966 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 967 |
'default' => 'asc',
|
| 968 |
'enum' => array(
|
| 969 |
'asc',
|
| 974 |
'description' => __( 'Sort collection by object attribute.' ),
|
| 975 |
'type' => 'string',
|
| 976 |
'sanitize_callback' => 'sanitize_key',
|
| 977 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 978 |
'default' => 'date_gmt',
|
| 979 |
'enum' => array(
|
| 980 |
'date',
|
| 987 |
),
|
| 988 |
);
|
| 989 |
$query_params['parent'] = array(
|
| 990 |
+
'default' => array(),
|
| 991 |
+
'description' => __( 'Limit result set to resources of specific parent ids.' ),
|
| 992 |
+
'sanitize_callback' => 'wp_parse_id_list',
|
| 993 |
+
'type' => 'array',
|
| 994 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 995 |
);
|
| 996 |
+
$query_params['parent_exclude'] = array(
|
| 997 |
+
'default' => array(),
|
| 998 |
+
'description' => __( 'Ensure result set excludes specific parent ids.' ),
|
| 999 |
+
'sanitize_callback' => 'wp_parse_id_list',
|
| 1000 |
+
'type' => 'array',
|
| 1001 |
+
'validate_callback' => 'rest_validate_request_arg',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1002 |
);
|
| 1003 |
+
$query_params['post'] = array(
|
| 1004 |
+
'default' => array(),
|
| 1005 |
+
'description' => __( 'Limit result set to resources assigned to specific post ids.' ),
|
| 1006 |
+
'type' => 'array',
|
| 1007 |
+
'sanitize_callback' => 'wp_parse_id_list',
|
| 1008 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1009 |
);
|
| 1010 |
$query_params['status'] = array(
|
| 1011 |
'default' => 'approve',
|
| 1012 |
+
'description' => __( 'Limit result set to comments assigned a specific status. Requires authorization.' ),
|
| 1013 |
'sanitize_callback' => 'sanitize_key',
|
| 1014 |
'type' => 'string',
|
| 1015 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1016 |
);
|
| 1017 |
$query_params['type'] = array(
|
| 1018 |
'default' => 'comment',
|
| 1019 |
+
'description' => __( 'Limit result set to comments assigned a specific type. Requires authorization.' ),
|
| 1020 |
'sanitize_callback' => 'sanitize_key',
|
| 1021 |
'type' => 'string',
|
| 1022 |
+
'validate_callback' => 'rest_validate_request_arg',
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1023 |
);
|
| 1024 |
return $query_params;
|
| 1025 |
}
|
| 1098 |
return false;
|
| 1099 |
}
|
| 1100 |
|
| 1101 |
+
if ( empty( $comment->comment_post_ID ) && ! current_user_can( 'moderate_comments' ) ) {
|
| 1102 |
+
return false;
|
| 1103 |
+
}
|
| 1104 |
+
|
| 1105 |
+
$post = get_post( $comment->comment_post_ID );
|
| 1106 |
+
if ( $comment->comment_post_ID && $post ) {
|
| 1107 |
+
if ( ! $this->check_read_post_permission( $post ) ) {
|
| 1108 |
+
return false;
|
| 1109 |
+
}
|
| 1110 |
+
}
|
| 1111 |
+
|
| 1112 |
if ( ! empty( $comment->user_id ) && get_current_user_id() === (int) $comment->user_id ) {
|
| 1113 |
return true;
|
| 1114 |
}
|
lib/endpoints/class-wp-rest-controller.php
CHANGED
|
@@ -3,6 +3,20 @@
|
|
| 3 |
|
| 4 |
abstract class WP_REST_Controller {
|
| 5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
/**
|
| 7 |
* Register the routes for the objects of the controller.
|
| 8 |
*/
|
|
@@ -225,17 +239,23 @@ abstract class WP_REST_Controller {
|
|
| 225 |
'type' => 'integer',
|
| 226 |
'default' => 1,
|
| 227 |
'sanitize_callback' => 'absint',
|
|
|
|
|
|
|
| 228 |
),
|
| 229 |
'per_page' => array(
|
| 230 |
'description' => __( 'Maximum number of items to be returned in result set.' ),
|
| 231 |
'type' => 'integer',
|
| 232 |
'default' => 10,
|
|
|
|
|
|
|
| 233 |
'sanitize_callback' => 'absint',
|
|
|
|
| 234 |
),
|
| 235 |
'search' => array(
|
| 236 |
'description' => __( 'Limit results to those matching a string.' ),
|
| 237 |
'type' => 'string',
|
| 238 |
'sanitize_callback' => 'sanitize_text_field',
|
|
|
|
| 239 |
),
|
| 240 |
);
|
| 241 |
}
|
|
@@ -252,6 +272,8 @@ abstract class WP_REST_Controller {
|
|
| 252 |
$param_details = array(
|
| 253 |
'description' => __( 'Scope under which the request is made; determines fields present in response.' ),
|
| 254 |
'type' => 'string',
|
|
|
|
|
|
|
| 255 |
);
|
| 256 |
$schema = $this->get_item_schema();
|
| 257 |
if ( empty( $schema['properties'] ) ) {
|
|
@@ -412,8 +434,8 @@ abstract class WP_REST_Controller {
|
|
| 412 |
}
|
| 413 |
|
| 414 |
$endpoint_args[ $field_id ] = array(
|
| 415 |
-
'validate_callback' =>
|
| 416 |
-
'sanitize_callback' =>
|
| 417 |
);
|
| 418 |
|
| 419 |
if ( WP_REST_Server::CREATABLE === $method && isset( $params['default'] ) ) {
|
|
@@ -424,6 +446,12 @@ abstract class WP_REST_Controller {
|
|
| 424 |
$endpoint_args[ $field_id ]['required'] = true;
|
| 425 |
}
|
| 426 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 427 |
// Merge in any options provided by the schema property.
|
| 428 |
if ( isset( $params['arg_options'] ) ) {
|
| 429 |
|
|
@@ -439,106 +467,4 @@ abstract class WP_REST_Controller {
|
|
| 439 |
return $endpoint_args;
|
| 440 |
}
|
| 441 |
|
| 442 |
-
/**
|
| 443 |
-
* Validate a parameter value that's based on a property from the item schema.
|
| 444 |
-
*
|
| 445 |
-
* @param mixed $value
|
| 446 |
-
* @param WP_REST_Request $request
|
| 447 |
-
* @param string $parameter
|
| 448 |
-
* @return WP_Error|boolean
|
| 449 |
-
*/
|
| 450 |
-
public function validate_schema_property( $value, $request, $parameter ) {
|
| 451 |
-
|
| 452 |
-
/**
|
| 453 |
-
* We don't currently validate against empty values, as lots of checks
|
| 454 |
-
* can unintentionally fail, as the callback will often handle an empty
|
| 455 |
-
* value it's self.
|
| 456 |
-
*/
|
| 457 |
-
if ( ! $value ) {
|
| 458 |
-
return true;
|
| 459 |
-
}
|
| 460 |
-
|
| 461 |
-
$schema = $this->get_item_schema();
|
| 462 |
-
|
| 463 |
-
if ( ! isset( $schema['properties'][ $parameter ] ) ) {
|
| 464 |
-
return true;
|
| 465 |
-
}
|
| 466 |
-
|
| 467 |
-
$property = $schema['properties'][ $parameter ];
|
| 468 |
-
|
| 469 |
-
if ( ! empty( $property['enum'] ) ) {
|
| 470 |
-
if ( ! in_array( $value, $property['enum'] ) ) {
|
| 471 |
-
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not one of %s' ), $parameter, implode( ', ', $property['enum'] ) ) );
|
| 472 |
-
}
|
| 473 |
-
}
|
| 474 |
-
|
| 475 |
-
if ( 'integer' === $property['type'] && ! is_numeric( $value ) ) {
|
| 476 |
-
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not of type %s' ), $parameter, 'integer' ) );
|
| 477 |
-
}
|
| 478 |
-
|
| 479 |
-
if ( 'string' === $property['type'] && ! is_string( $value ) ) {
|
| 480 |
-
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not of type %s' ), $parameter, 'string' ) );
|
| 481 |
-
}
|
| 482 |
-
|
| 483 |
-
if ( isset( $property['format'] ) ) {
|
| 484 |
-
switch ( $property['format'] ) {
|
| 485 |
-
case 'date-time' :
|
| 486 |
-
if ( ! rest_parse_date( $value ) ) {
|
| 487 |
-
return new WP_Error( 'rest_invalid_date', __( 'The date you provided is invalid.' ) );
|
| 488 |
-
}
|
| 489 |
-
break;
|
| 490 |
-
|
| 491 |
-
case 'email' :
|
| 492 |
-
if ( ! is_email( $value ) ) {
|
| 493 |
-
return new WP_Error( 'rest_invalid_email', __( 'The email address you provided is invalid.' ) );
|
| 494 |
-
}
|
| 495 |
-
break;
|
| 496 |
-
}
|
| 497 |
-
}
|
| 498 |
-
|
| 499 |
-
return true;
|
| 500 |
-
}
|
| 501 |
-
|
| 502 |
-
/**
|
| 503 |
-
* Sanitize a parameter value that's based on a property from the item schema.
|
| 504 |
-
*
|
| 505 |
-
* @param mixed $value
|
| 506 |
-
* @param WP_REST_Request $request
|
| 507 |
-
* @param string $parameter
|
| 508 |
-
* @return mixed
|
| 509 |
-
*/
|
| 510 |
-
public function sanitize_schema_property( $value, $request, $parameter ) {
|
| 511 |
-
|
| 512 |
-
$schema = $this->get_item_schema();
|
| 513 |
-
|
| 514 |
-
if ( ! isset( $schema['properties'][ $parameter ] ) ) {
|
| 515 |
-
return true;
|
| 516 |
-
}
|
| 517 |
-
|
| 518 |
-
$property = $schema['properties'][ $parameter ];
|
| 519 |
-
|
| 520 |
-
if ( 'integer' === $property['type'] ) {
|
| 521 |
-
return (int) $value;
|
| 522 |
-
}
|
| 523 |
-
|
| 524 |
-
if ( isset( $property['format'] ) ) {
|
| 525 |
-
switch ( $property['format'] ) {
|
| 526 |
-
case 'date-time' :
|
| 527 |
-
return sanitize_text_field( $value );
|
| 528 |
-
|
| 529 |
-
case 'email' :
|
| 530 |
-
// as sanitize_email is very lossy, we just want to
|
| 531 |
-
// make sure the string is safe.
|
| 532 |
-
if ( sanitize_email( $value ) ) {
|
| 533 |
-
return sanitize_email( $value );
|
| 534 |
-
}
|
| 535 |
-
return sanitize_text_field( $value );
|
| 536 |
-
|
| 537 |
-
case 'uri' :
|
| 538 |
-
return esc_url_raw( $value );
|
| 539 |
-
}
|
| 540 |
-
}
|
| 541 |
-
|
| 542 |
-
return $value;
|
| 543 |
-
}
|
| 544 |
}
|
| 3 |
|
| 4 |
abstract class WP_REST_Controller {
|
| 5 |
|
| 6 |
+
/**
|
| 7 |
+
* The namespace of this controller's route.
|
| 8 |
+
*
|
| 9 |
+
* @var string
|
| 10 |
+
*/
|
| 11 |
+
protected $namespace;
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* The base of this controller's route.
|
| 15 |
+
*
|
| 16 |
+
* @var string
|
| 17 |
+
*/
|
| 18 |
+
protected $rest_base;
|
| 19 |
+
|
| 20 |
/**
|
| 21 |
* Register the routes for the objects of the controller.
|
| 22 |
*/
|
| 239 |
'type' => 'integer',
|
| 240 |
'default' => 1,
|
| 241 |
'sanitize_callback' => 'absint',
|
| 242 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 243 |
+
'minimum' => 1,
|
| 244 |
),
|
| 245 |
'per_page' => array(
|
| 246 |
'description' => __( 'Maximum number of items to be returned in result set.' ),
|
| 247 |
'type' => 'integer',
|
| 248 |
'default' => 10,
|
| 249 |
+
'minimum' => 1,
|
| 250 |
+
'maximum' => 100,
|
| 251 |
'sanitize_callback' => 'absint',
|
| 252 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 253 |
),
|
| 254 |
'search' => array(
|
| 255 |
'description' => __( 'Limit results to those matching a string.' ),
|
| 256 |
'type' => 'string',
|
| 257 |
'sanitize_callback' => 'sanitize_text_field',
|
| 258 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 259 |
),
|
| 260 |
);
|
| 261 |
}
|
| 272 |
$param_details = array(
|
| 273 |
'description' => __( 'Scope under which the request is made; determines fields present in response.' ),
|
| 274 |
'type' => 'string',
|
| 275 |
+
'sanitize_callback' => 'sanitize_key',
|
| 276 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 277 |
);
|
| 278 |
$schema = $this->get_item_schema();
|
| 279 |
if ( empty( $schema['properties'] ) ) {
|
| 434 |
}
|
| 435 |
|
| 436 |
$endpoint_args[ $field_id ] = array(
|
| 437 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 438 |
+
'sanitize_callback' => 'rest_sanitize_request_arg',
|
| 439 |
);
|
| 440 |
|
| 441 |
if ( WP_REST_Server::CREATABLE === $method && isset( $params['default'] ) ) {
|
| 446 |
$endpoint_args[ $field_id ]['required'] = true;
|
| 447 |
}
|
| 448 |
|
| 449 |
+
foreach ( array( 'type', 'format', 'enum' ) as $schema_prop ) {
|
| 450 |
+
if ( isset( $params[ $schema_prop ] ) ) {
|
| 451 |
+
$endpoint_args[ $field_id ][ $schema_prop ] = $params[ $schema_prop ];
|
| 452 |
+
}
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
// Merge in any options provided by the schema property.
|
| 456 |
if ( isset( $params['arg_options'] ) ) {
|
| 457 |
|
| 467 |
return $endpoint_args;
|
| 468 |
}
|
| 469 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 470 |
}
|
lib/endpoints/class-wp-rest-meta-controller.php
DELETED
|
@@ -1,468 +0,0 @@
|
|
| 1 |
-
<?php
|
| 2 |
-
/**
|
| 3 |
-
* Metadata base class.
|
| 4 |
-
*/
|
| 5 |
-
abstract class WP_REST_Meta_Controller extends WP_REST_Controller {
|
| 6 |
-
/**
|
| 7 |
-
* Associated object type.
|
| 8 |
-
*
|
| 9 |
-
* @var string Type slug ("post", "user", or "comment")
|
| 10 |
-
*/
|
| 11 |
-
protected $parent_type = null;
|
| 12 |
-
|
| 13 |
-
/**
|
| 14 |
-
* Base path for parent meta type endpoints.
|
| 15 |
-
*
|
| 16 |
-
* @var string
|
| 17 |
-
*/
|
| 18 |
-
protected $parent_base = null;
|
| 19 |
-
|
| 20 |
-
/**
|
| 21 |
-
* Construct the API handler object.
|
| 22 |
-
*/
|
| 23 |
-
public function __construct() {
|
| 24 |
-
if ( empty( $this->parent_type ) ) {
|
| 25 |
-
_doing_it_wrong( 'WP_REST_Meta_Controller::__construct', __( 'The object type must be overridden' ), 'WPAPI-2.0' );
|
| 26 |
-
return;
|
| 27 |
-
}
|
| 28 |
-
if ( empty( $this->parent_base ) ) {
|
| 29 |
-
_doing_it_wrong( 'WP_REST_Meta_Controller::__construct', __( 'The parent base must be overridden' ), 'WPAPI-2.0' );
|
| 30 |
-
return;
|
| 31 |
-
}
|
| 32 |
-
}
|
| 33 |
-
|
| 34 |
-
/**
|
| 35 |
-
* Register the meta-related routes.
|
| 36 |
-
*/
|
| 37 |
-
public function register_routes() {
|
| 38 |
-
register_rest_route( 'wp/v2', '/' . $this->parent_base . '/(?P<parent_id>[\d]+)/meta', array(
|
| 39 |
-
array(
|
| 40 |
-
'methods' => WP_REST_Server::READABLE,
|
| 41 |
-
'callback' => array( $this, 'get_items' ),
|
| 42 |
-
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
| 43 |
-
'args' => $this->get_collection_params(),
|
| 44 |
-
),
|
| 45 |
-
array(
|
| 46 |
-
'methods' => WP_REST_Server::CREATABLE,
|
| 47 |
-
'callback' => array( $this, 'create_item' ),
|
| 48 |
-
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
| 49 |
-
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
| 50 |
-
),
|
| 51 |
-
|
| 52 |
-
'schema' => array( $this, 'get_public_item_schema' ),
|
| 53 |
-
) );
|
| 54 |
-
register_rest_route( 'wp/v2', '/' . $this->parent_base . '/(?P<parent_id>[\d]+)/meta/(?P<id>[\d]+)', array(
|
| 55 |
-
array(
|
| 56 |
-
'methods' => WP_REST_Server::READABLE,
|
| 57 |
-
'callback' => array( $this, 'get_item' ),
|
| 58 |
-
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
| 59 |
-
'args' => array(
|
| 60 |
-
'context' => $this->get_context_param( array( 'default' => 'edit' ) ),
|
| 61 |
-
),
|
| 62 |
-
),
|
| 63 |
-
array(
|
| 64 |
-
'methods' => WP_REST_Server::EDITABLE,
|
| 65 |
-
'callback' => array( $this, 'update_item' ),
|
| 66 |
-
'permission_callback' => array( $this, 'update_item_permissions_check' ),
|
| 67 |
-
'args' => $this->get_endpoint_args_for_item_schema( false ),
|
| 68 |
-
),
|
| 69 |
-
array(
|
| 70 |
-
'methods' => WP_REST_Server::DELETABLE,
|
| 71 |
-
'callback' => array( $this, 'delete_item' ),
|
| 72 |
-
'permission_callback' => array( $this, 'delete_item_permissions_check' ),
|
| 73 |
-
'args' => array(
|
| 74 |
-
'force' => array(
|
| 75 |
-
'default' => false,
|
| 76 |
-
'description' => __( 'Required to be true, as resource does not support trashing.' ),
|
| 77 |
-
),
|
| 78 |
-
),
|
| 79 |
-
),
|
| 80 |
-
|
| 81 |
-
'schema' => array( $this, 'get_public_item_schema' ),
|
| 82 |
-
) );
|
| 83 |
-
}
|
| 84 |
-
|
| 85 |
-
/**
|
| 86 |
-
* Get the meta schema, conforming to JSON Schema
|
| 87 |
-
*
|
| 88 |
-
* @return array
|
| 89 |
-
*/
|
| 90 |
-
public function get_item_schema() {
|
| 91 |
-
$schema = array(
|
| 92 |
-
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
| 93 |
-
'title' => 'meta',
|
| 94 |
-
'type' => 'object',
|
| 95 |
-
/*
|
| 96 |
-
* Base properties for every Post
|
| 97 |
-
*/
|
| 98 |
-
'properties' => array(
|
| 99 |
-
'id' => array(
|
| 100 |
-
'description' => __( 'Unique identifier for the object.' ),
|
| 101 |
-
'type' => 'integer',
|
| 102 |
-
'context' => array( 'edit' ),
|
| 103 |
-
'readonly' => true,
|
| 104 |
-
),
|
| 105 |
-
'key' => array(
|
| 106 |
-
'description' => __( 'The key for the custom field.' ),
|
| 107 |
-
'type' => 'string',
|
| 108 |
-
'context' => array( 'edit' ),
|
| 109 |
-
'required' => true,
|
| 110 |
-
'arg_options' => array(
|
| 111 |
-
'sanitize_callback' => 'sanitize_text_field',
|
| 112 |
-
),
|
| 113 |
-
),
|
| 114 |
-
'value' => array(
|
| 115 |
-
'description' => __( 'The value of the custom field.' ),
|
| 116 |
-
'type' => 'string',
|
| 117 |
-
'context' => array( 'edit' ),
|
| 118 |
-
),
|
| 119 |
-
),
|
| 120 |
-
);
|
| 121 |
-
return $schema;
|
| 122 |
-
}
|
| 123 |
-
|
| 124 |
-
/**
|
| 125 |
-
* Get the query params for collections
|
| 126 |
-
*
|
| 127 |
-
* @return array
|
| 128 |
-
*/
|
| 129 |
-
public function get_collection_params() {
|
| 130 |
-
$params = parent::get_collection_params();
|
| 131 |
-
$new_params = array();
|
| 132 |
-
$new_params['context'] = $params['context'];
|
| 133 |
-
$new_params['context']['default'] = 'edit';
|
| 134 |
-
return $new_params;
|
| 135 |
-
}
|
| 136 |
-
|
| 137 |
-
/**
|
| 138 |
-
* Get the meta ID column for the relevant table.
|
| 139 |
-
*
|
| 140 |
-
* @return string
|
| 141 |
-
*/
|
| 142 |
-
protected function get_id_column() {
|
| 143 |
-
return ( 'user' === $this->parent_type ) ? 'umeta_id' : 'meta_id';
|
| 144 |
-
}
|
| 145 |
-
|
| 146 |
-
/**
|
| 147 |
-
* Get the object (parent) ID column for the relevant table.
|
| 148 |
-
*
|
| 149 |
-
* @return string
|
| 150 |
-
*/
|
| 151 |
-
protected function get_parent_column() {
|
| 152 |
-
return ( 'user' === $this->parent_type ) ? 'user_id' : 'post_id';
|
| 153 |
-
}
|
| 154 |
-
|
| 155 |
-
/**
|
| 156 |
-
* Retrieve custom fields for object.
|
| 157 |
-
*
|
| 158 |
-
* @param WP_REST_Request $request
|
| 159 |
-
* @return WP_REST_Request|WP_Error List of meta object data on success, WP_Error otherwise
|
| 160 |
-
*/
|
| 161 |
-
public function get_items( $request ) {
|
| 162 |
-
$parent_id = (int) $request['parent_id'];
|
| 163 |
-
|
| 164 |
-
global $wpdb;
|
| 165 |
-
$table = _get_meta_table( $this->parent_type );
|
| 166 |
-
$parent_column = $this->get_parent_column();
|
| 167 |
-
$id_column = $this->get_id_column();
|
| 168 |
-
|
| 169 |
-
// @codingStandardsIgnoreStart
|
| 170 |
-
$results = $wpdb->get_results( $wpdb->prepare( "SELECT $id_column, $parent_column, meta_key, meta_value FROM $table WHERE $parent_column = %d", $parent_id ) );
|
| 171 |
-
// @codingStandardsIgnoreEnd
|
| 172 |
-
|
| 173 |
-
$meta = array();
|
| 174 |
-
|
| 175 |
-
foreach ( $results as $row ) {
|
| 176 |
-
$value = $this->prepare_item_for_response( $row, $request, true );
|
| 177 |
-
|
| 178 |
-
if ( is_wp_error( $value ) ) {
|
| 179 |
-
continue;
|
| 180 |
-
}
|
| 181 |
-
|
| 182 |
-
$meta[] = $this->prepare_response_for_collection( $value );
|
| 183 |
-
}
|
| 184 |
-
|
| 185 |
-
return rest_ensure_response( $meta );
|
| 186 |
-
}
|
| 187 |
-
|
| 188 |
-
/**
|
| 189 |
-
* Retrieve custom field object.
|
| 190 |
-
*
|
| 191 |
-
* @param WP_REST_Request $request
|
| 192 |
-
* @return WP_REST_Request|WP_Error Meta object data on success, WP_Error otherwise
|
| 193 |
-
*/
|
| 194 |
-
public function get_item( $request ) {
|
| 195 |
-
$parent_id = (int) $request['parent_id'];
|
| 196 |
-
$mid = (int) $request['id'];
|
| 197 |
-
|
| 198 |
-
$parent_column = $this->get_parent_column();
|
| 199 |
-
$meta = get_metadata_by_mid( $this->parent_type, $mid );
|
| 200 |
-
|
| 201 |
-
if ( empty( $meta ) ) {
|
| 202 |
-
return new WP_Error( 'rest_meta_invalid_id', __( 'Invalid meta id.' ), array( 'status' => 404 ) );
|
| 203 |
-
}
|
| 204 |
-
|
| 205 |
-
if ( absint( $meta->$parent_column ) !== $parent_id ) {
|
| 206 |
-
return new WP_Error( 'rest_meta_' . $this->parent_type . '_mismatch', __( 'Meta does not belong to this object' ), array( 'status' => 400 ) );
|
| 207 |
-
}
|
| 208 |
-
|
| 209 |
-
return $this->prepare_item_for_response( $meta, $request );
|
| 210 |
-
}
|
| 211 |
-
|
| 212 |
-
/**
|
| 213 |
-
* Prepares meta data for return as an object.
|
| 214 |
-
*
|
| 215 |
-
* @param stdClass $data Metadata row from database
|
| 216 |
-
* @param WP_REST_Request $request
|
| 217 |
-
* @param boolean $is_raw Is the value field still serialized? (False indicates the value has been unserialized)
|
| 218 |
-
* @return WP_REST_Response|WP_Error Meta object data on success, WP_Error otherwise
|
| 219 |
-
*/
|
| 220 |
-
public function prepare_item_for_response( $data, $request, $is_raw = false ) {
|
| 221 |
-
$id_column = $this->get_id_column();
|
| 222 |
-
$id = $data->$id_column;
|
| 223 |
-
$key = $data->meta_key;
|
| 224 |
-
$value = $data->meta_value;
|
| 225 |
-
|
| 226 |
-
// Don't expose protected fields.
|
| 227 |
-
if ( is_protected_meta( $key ) ) {
|
| 228 |
-
return new WP_Error( 'rest_meta_protected', sprintf( __( '%s is marked as a protected field.' ), $key ), array( 'status' => 403 ) );
|
| 229 |
-
}
|
| 230 |
-
|
| 231 |
-
// Normalize serialized strings
|
| 232 |
-
if ( $is_raw && is_serialized_string( $value ) ) {
|
| 233 |
-
$value = unserialize( $value );
|
| 234 |
-
}
|
| 235 |
-
|
| 236 |
-
// Don't expose serialized data
|
| 237 |
-
if ( is_serialized( $value ) || ! is_string( $value ) ) {
|
| 238 |
-
return new WP_Error( 'rest_meta_protected', sprintf( __( '%s contains serialized data.' ), $key ), array( 'status' => 403 ) );
|
| 239 |
-
}
|
| 240 |
-
|
| 241 |
-
$meta = array(
|
| 242 |
-
'id' => (int) $id,
|
| 243 |
-
'key' => $key,
|
| 244 |
-
'value' => $value,
|
| 245 |
-
);
|
| 246 |
-
|
| 247 |
-
$response = rest_ensure_response( $meta );
|
| 248 |
-
$parent_column = $this->get_parent_column();
|
| 249 |
-
$response->add_link( 'about', rest_url( 'wp/' . $this->parent_base . '/' . $data->$parent_column ), array( 'embeddable' => true ) );
|
| 250 |
-
|
| 251 |
-
/**
|
| 252 |
-
* Filter a meta value returned from the API.
|
| 253 |
-
*
|
| 254 |
-
* Allows modification of the meta value right before it is returned.
|
| 255 |
-
*
|
| 256 |
-
* @param array $response Key value array of meta data: id, key, value.
|
| 257 |
-
* @param WP_REST_Request $request Request used to generate the response.
|
| 258 |
-
*/
|
| 259 |
-
return apply_filters( 'rest_prepare_meta_value', $response, $request );
|
| 260 |
-
}
|
| 261 |
-
|
| 262 |
-
/**
|
| 263 |
-
* Add meta to an object.
|
| 264 |
-
*
|
| 265 |
-
* @param WP_REST_Request $request
|
| 266 |
-
* @return WP_REST_Response|WP_Error
|
| 267 |
-
*/
|
| 268 |
-
public function update_item( $request ) {
|
| 269 |
-
$parent_id = (int) $request['parent_id'];
|
| 270 |
-
$mid = (int) $request['id'];
|
| 271 |
-
|
| 272 |
-
$parent_column = $this->get_parent_column();
|
| 273 |
-
$current = get_metadata_by_mid( $this->parent_type, $mid );
|
| 274 |
-
|
| 275 |
-
if ( empty( $current ) ) {
|
| 276 |
-
return new WP_Error( 'rest_meta_invalid_id', __( 'Invalid meta id.' ), array( 'status' => 404 ) );
|
| 277 |
-
}
|
| 278 |
-
|
| 279 |
-
if ( absint( $current->$parent_column ) !== $parent_id ) {
|
| 280 |
-
return new WP_Error( 'rest_meta_' . $this->parent_type . '_mismatch', __( 'Meta does not belong to this object' ), array( 'status' => 400 ) );
|
| 281 |
-
}
|
| 282 |
-
|
| 283 |
-
if ( ! isset( $request['key'] ) && ! isset( $request['value'] ) ) {
|
| 284 |
-
return new WP_Error( 'rest_meta_data_invalid', __( 'Invalid meta parameters.' ), array( 'status' => 400 ) );
|
| 285 |
-
}
|
| 286 |
-
if ( isset( $request['key'] ) ) {
|
| 287 |
-
$key = $request['key'];
|
| 288 |
-
} else {
|
| 289 |
-
$key = $current->meta_key;
|
| 290 |
-
}
|
| 291 |
-
|
| 292 |
-
if ( isset( $request['value'] ) ) {
|
| 293 |
-
$value = $request['value'];
|
| 294 |
-
} else {
|
| 295 |
-
$value = $current->meta_value;
|
| 296 |
-
}
|
| 297 |
-
|
| 298 |
-
if ( ! $key ) {
|
| 299 |
-
return new WP_Error( 'rest_meta_invalid_key', __( 'Invalid meta key.' ), array( 'status' => 400 ) );
|
| 300 |
-
}
|
| 301 |
-
|
| 302 |
-
// for now let's not allow updating of arrays, objects or serialized values.
|
| 303 |
-
if ( ! $this->is_valid_meta_data( $current->meta_value ) ) {
|
| 304 |
-
$code = ( $this->parent_type === 'post' ) ? 'rest_post_invalid_action' : 'rest_meta_invalid_action';
|
| 305 |
-
return new WP_Error( $code, __( 'Invalid existing meta data for action.' ), array( 'status' => 400 ) );
|
| 306 |
-
}
|
| 307 |
-
|
| 308 |
-
if ( ! $this->is_valid_meta_data( $value ) ) {
|
| 309 |
-
$code = ( $this->parent_type === 'post' ) ? 'rest_post_invalid_action' : 'rest_meta_invalid_action';
|
| 310 |
-
return new WP_Error( $code, __( 'Invalid provided meta data for action.' ), array( 'status' => 400 ) );
|
| 311 |
-
}
|
| 312 |
-
|
| 313 |
-
if ( is_protected_meta( $current->meta_key ) ) {
|
| 314 |
-
return new WP_Error( 'rest_meta_protected', sprintf( __( '%s is marked as a protected field.' ), $current->meta_key ), array( 'status' => 403 ) );
|
| 315 |
-
}
|
| 316 |
-
|
| 317 |
-
if ( is_protected_meta( $key ) ) {
|
| 318 |
-
return new WP_Error( 'rest_meta_protected', sprintf( __( '%s is marked as a protected field.' ), $key ), array( 'status' => 403 ) );
|
| 319 |
-
}
|
| 320 |
-
|
| 321 |
-
// update_metadata_by_mid will return false if these are equal, so check
|
| 322 |
-
// first and pass through
|
| 323 |
-
if ( (string) $value === $current->meta_value && (string) $key === $current->meta_key ) {
|
| 324 |
-
return $this->get_item( $request );
|
| 325 |
-
}
|
| 326 |
-
|
| 327 |
-
if ( ! update_metadata_by_mid( $this->parent_type, $mid, $value, $key ) ) {
|
| 328 |
-
return new WP_Error( 'rest_meta_could_not_update', __( 'Could not update meta.' ), array( 'status' => 500 ) );
|
| 329 |
-
}
|
| 330 |
-
|
| 331 |
-
$request = new WP_REST_Request( 'GET' );
|
| 332 |
-
$request->set_query_params( array(
|
| 333 |
-
'context' => 'edit',
|
| 334 |
-
'parent_id' => $parent_id,
|
| 335 |
-
'id' => $mid,
|
| 336 |
-
) );
|
| 337 |
-
$response = $this->get_item( $request );
|
| 338 |
-
|
| 339 |
-
/**
|
| 340 |
-
* Fires after meta is added to an object or updated via the REST API.
|
| 341 |
-
*
|
| 342 |
-
* @param array $value The inserted meta data.
|
| 343 |
-
* @param WP_REST_Request $request The request sent to the API.
|
| 344 |
-
* @param boolean $creating True when adding meta, false when updating.
|
| 345 |
-
*/
|
| 346 |
-
do_action( 'rest_insert_meta', $value, $request, false );
|
| 347 |
-
|
| 348 |
-
return rest_ensure_response( $response );
|
| 349 |
-
}
|
| 350 |
-
|
| 351 |
-
/**
|
| 352 |
-
* Check if the data provided is valid data.
|
| 353 |
-
*
|
| 354 |
-
* Excludes serialized data from being sent via the API.
|
| 355 |
-
*
|
| 356 |
-
* @see https://github.com/WP-API/WP-API/pull/68
|
| 357 |
-
* @param mixed $data Data to be checked
|
| 358 |
-
* @return boolean Whether the data is valid or not
|
| 359 |
-
*/
|
| 360 |
-
protected function is_valid_meta_data( $data ) {
|
| 361 |
-
if ( is_array( $data ) || is_object( $data ) || is_serialized( $data ) ) {
|
| 362 |
-
return false;
|
| 363 |
-
}
|
| 364 |
-
|
| 365 |
-
return true;
|
| 366 |
-
}
|
| 367 |
-
|
| 368 |
-
/**
|
| 369 |
-
* Add meta to an object.
|
| 370 |
-
*
|
| 371 |
-
* @param WP_REST_Request $request
|
| 372 |
-
* @return WP_REST_Response|WP_Error
|
| 373 |
-
*/
|
| 374 |
-
public function create_item( $request ) {
|
| 375 |
-
$parent_id = (int) $request['parent_id'];
|
| 376 |
-
|
| 377 |
-
if ( ! $this->is_valid_meta_data( $request['value'] ) ) {
|
| 378 |
-
$code = ( $this->parent_type === 'post' ) ? 'rest_post_invalid_action' : 'rest_meta_invalid_action';
|
| 379 |
-
|
| 380 |
-
// for now let's not allow updating of arrays, objects or serialized values.
|
| 381 |
-
return new WP_Error( $code, __( 'Invalid provided meta data for action.' ), array( 'status' => 400 ) );
|
| 382 |
-
}
|
| 383 |
-
|
| 384 |
-
if ( empty( $request['key'] ) ) {
|
| 385 |
-
return new WP_Error( 'rest_meta_invalid_key', __( 'Invalid meta key.' ), array( 'status' => 400 ) );
|
| 386 |
-
}
|
| 387 |
-
|
| 388 |
-
if ( is_protected_meta( $request['key'] ) ) {
|
| 389 |
-
return new WP_Error( 'rest_meta_protected', sprintf( __( '%s is marked as a protected field.' ), $request['key'] ), array( 'status' => 403 ) );
|
| 390 |
-
}
|
| 391 |
-
|
| 392 |
-
$meta_key = wp_slash( $request['key'] );
|
| 393 |
-
$value = wp_slash( $request['value'] );
|
| 394 |
-
|
| 395 |
-
$mid = add_metadata( $this->parent_type, $parent_id, $meta_key, $value );
|
| 396 |
-
if ( ! $mid ) {
|
| 397 |
-
return new WP_Error( 'rest_meta_could_not_add', __( 'Could not add meta.' ), array( 'status' => 400 ) );
|
| 398 |
-
}
|
| 399 |
-
|
| 400 |
-
$request = new WP_REST_Request( 'GET' );
|
| 401 |
-
$request->set_query_params( array(
|
| 402 |
-
'context' => 'edit',
|
| 403 |
-
'parent_id' => $parent_id,
|
| 404 |
-
'id' => $mid,
|
| 405 |
-
) );
|
| 406 |
-
$response = rest_ensure_response( $this->get_item( $request ) );
|
| 407 |
-
|
| 408 |
-
$response->set_status( 201 );
|
| 409 |
-
$data = $response->get_data();
|
| 410 |
-
$response->header( 'Location', rest_url( 'wp/v2' . '/' . $this->parent_base . '/' . $parent_id . '/meta/' . $data['id'] ) );
|
| 411 |
-
|
| 412 |
-
/* This action is documented in lib/endpoints/class-wp-rest-meta-controller.php */
|
| 413 |
-
do_action( 'rest_insert_meta', $data, $request, true );
|
| 414 |
-
|
| 415 |
-
return $response;
|
| 416 |
-
}
|
| 417 |
-
|
| 418 |
-
/**
|
| 419 |
-
* Delete meta from an object.
|
| 420 |
-
*
|
| 421 |
-
* @param WP_REST_Request $request
|
| 422 |
-
* @return WP_REST_Response|WP_Error Message on success, WP_Error otherwise
|
| 423 |
-
*/
|
| 424 |
-
public function delete_item( $request ) {
|
| 425 |
-
$parent_id = (int) $request['parent_id'];
|
| 426 |
-
$mid = (int) $request['id'];
|
| 427 |
-
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
|
| 428 |
-
|
| 429 |
-
// We don't support trashing for this type, error out
|
| 430 |
-
if ( ! $force ) {
|
| 431 |
-
return new WP_Error( 'rest_trash_not_supported', __( 'Meta does not support trashing.' ), array( 'status' => 501 ) );
|
| 432 |
-
}
|
| 433 |
-
|
| 434 |
-
$parent_column = $this->get_parent_column();
|
| 435 |
-
$current = get_metadata_by_mid( $this->parent_type, $mid );
|
| 436 |
-
|
| 437 |
-
if ( empty( $current ) ) {
|
| 438 |
-
return new WP_Error( 'rest_meta_invalid_id', __( 'Invalid meta id.' ), array( 'status' => 404 ) );
|
| 439 |
-
}
|
| 440 |
-
|
| 441 |
-
if ( absint( $current->$parent_column ) !== (int) $parent_id ) {
|
| 442 |
-
return new WP_Error( 'rest_meta_' . $this->parent_type . '_mismatch', __( 'Meta does not belong to this object' ), array( 'status' => 400 ) );
|
| 443 |
-
}
|
| 444 |
-
|
| 445 |
-
// for now let's not allow updating of arrays, objects or serialized values.
|
| 446 |
-
if ( ! $this->is_valid_meta_data( $current->meta_value ) ) {
|
| 447 |
-
$code = ( $this->parent_type === 'post' ) ? 'rest_post_invalid_action' : 'rest_meta_invalid_action';
|
| 448 |
-
return new WP_Error( $code, __( 'Invalid existing meta data for action.' ), array( 'status' => 400 ) );
|
| 449 |
-
}
|
| 450 |
-
|
| 451 |
-
if ( is_protected_meta( $current->meta_key ) ) {
|
| 452 |
-
return new WP_Error( 'rest_meta_protected', sprintf( __( '%s is marked as a protected field.' ), $current->meta_key ), array( 'status' => 403 ) );
|
| 453 |
-
}
|
| 454 |
-
|
| 455 |
-
if ( ! delete_metadata_by_mid( $this->parent_type, $mid ) ) {
|
| 456 |
-
return new WP_Error( 'rest_meta_could_not_delete', __( 'Could not delete meta.' ), array( 'status' => 500 ) );
|
| 457 |
-
}
|
| 458 |
-
|
| 459 |
-
/**
|
| 460 |
-
* Fires after a meta value is deleted via the REST API.
|
| 461 |
-
*
|
| 462 |
-
* @param WP_REST_Request $request The request sent to the API.
|
| 463 |
-
*/
|
| 464 |
-
do_action( 'rest_delete_meta', $request );
|
| 465 |
-
|
| 466 |
-
return rest_ensure_response( array( 'message' => __( 'Deleted meta' ) ) );
|
| 467 |
-
}
|
| 468 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/endpoints/class-wp-rest-meta-posts-controller.php
DELETED
|
@@ -1,115 +0,0 @@
|
|
| 1 |
-
<?php
|
| 2 |
-
|
| 3 |
-
class WP_REST_Meta_Posts_Controller extends WP_REST_Meta_Controller {
|
| 4 |
-
/**
|
| 5 |
-
* Associated object type.
|
| 6 |
-
*
|
| 7 |
-
* @var string Type slug ("post" or "user")
|
| 8 |
-
*/
|
| 9 |
-
protected $parent_type = 'post';
|
| 10 |
-
|
| 11 |
-
/**
|
| 12 |
-
* Associated post type name.
|
| 13 |
-
*
|
| 14 |
-
* @var string
|
| 15 |
-
*/
|
| 16 |
-
protected $parent_post_type;
|
| 17 |
-
|
| 18 |
-
/**
|
| 19 |
-
* Associated post type controller class object.
|
| 20 |
-
*
|
| 21 |
-
* @var WP_REST_Posts_Controller
|
| 22 |
-
*/
|
| 23 |
-
protected $parent_controller;
|
| 24 |
-
|
| 25 |
-
/**
|
| 26 |
-
* Base path for post type endpoints.
|
| 27 |
-
*
|
| 28 |
-
* @var string
|
| 29 |
-
*/
|
| 30 |
-
protected $parent_base;
|
| 31 |
-
|
| 32 |
-
public function __construct( $parent_post_type ) {
|
| 33 |
-
$this->parent_post_type = $parent_post_type;
|
| 34 |
-
$this->parent_controller = new WP_REST_Posts_Controller( $this->parent_post_type );
|
| 35 |
-
$this->parent_base = $this->parent_controller->get_post_type_base( $this->parent_post_type );
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
/**
|
| 39 |
-
* Check if a given request has access to get meta for a post.
|
| 40 |
-
*
|
| 41 |
-
* @param WP_REST_Request $request Full data about the request.
|
| 42 |
-
* @return WP_Error|boolean
|
| 43 |
-
*/
|
| 44 |
-
public function get_items_permissions_check( $request ) {
|
| 45 |
-
$parent = get_post( (int) $request['parent_id'] );
|
| 46 |
-
|
| 47 |
-
if ( empty( $parent ) || empty( $parent->ID ) ) {
|
| 48 |
-
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post id.' ), array( 'status' => 404 ) );
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
if ( ! $this->parent_controller->check_read_permission( $parent ) ) {
|
| 52 |
-
return new WP_Error( 'rest_forbidden', __( 'Sorry, you cannot view this post.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 53 |
-
}
|
| 54 |
-
|
| 55 |
-
$post_type = get_post_type_object( $parent->post_type );
|
| 56 |
-
if ( ! current_user_can( $post_type->cap->edit_post, $parent->ID ) ) {
|
| 57 |
-
return new WP_Error( 'rest_forbidden', __( 'Sorry, you cannot view the meta for this post.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 58 |
-
}
|
| 59 |
-
return true;
|
| 60 |
-
}
|
| 61 |
-
|
| 62 |
-
/**
|
| 63 |
-
* Check if a given request has access to get a specific meta entry for a post.
|
| 64 |
-
*
|
| 65 |
-
* @param WP_REST_Request $request Full data about the request.
|
| 66 |
-
* @return WP_Error|boolean
|
| 67 |
-
*/
|
| 68 |
-
public function get_item_permissions_check( $request ) {
|
| 69 |
-
return $this->get_items_permissions_check( $request );
|
| 70 |
-
}
|
| 71 |
-
|
| 72 |
-
/**
|
| 73 |
-
* Check if a given request has access to create a meta entry for a post.
|
| 74 |
-
*
|
| 75 |
-
* @param WP_REST_Request $request Full data about the request.
|
| 76 |
-
* @return WP_Error|boolean
|
| 77 |
-
*/
|
| 78 |
-
public function create_item_permissions_check( $request ) {
|
| 79 |
-
return $this->get_items_permissions_check( $request );
|
| 80 |
-
}
|
| 81 |
-
|
| 82 |
-
/**
|
| 83 |
-
* Check if a given request has access to update a meta entry for a post.
|
| 84 |
-
*
|
| 85 |
-
* @param WP_REST_Request $request Full data about the request.
|
| 86 |
-
* @return WP_Error|boolean
|
| 87 |
-
*/
|
| 88 |
-
public function update_item_permissions_check( $request ) {
|
| 89 |
-
return $this->get_items_permissions_check( $request );
|
| 90 |
-
}
|
| 91 |
-
|
| 92 |
-
/**
|
| 93 |
-
* Check if a given request has access to delete meta for a post.
|
| 94 |
-
*
|
| 95 |
-
* @param WP_REST_Request $request Full details about the request.
|
| 96 |
-
* @return WP_Error|boolean
|
| 97 |
-
*/
|
| 98 |
-
public function delete_item_permissions_check( $request ) {
|
| 99 |
-
$parent = get_post( (int) $request['parent_id'] );
|
| 100 |
-
|
| 101 |
-
if ( empty( $parent ) || empty( $parent->ID ) ) {
|
| 102 |
-
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post id.' ), array( 'status' => 404 ) );
|
| 103 |
-
}
|
| 104 |
-
|
| 105 |
-
if ( ! $this->parent_controller->check_read_permission( $parent ) ) {
|
| 106 |
-
return new WP_Error( 'rest_forbidden', __( 'Sorry, you cannot view this post.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 107 |
-
}
|
| 108 |
-
|
| 109 |
-
$post_type = get_post_type_object( $parent->post_type );
|
| 110 |
-
if ( ! current_user_can( $post_type->cap->delete_post, $parent->ID ) ) {
|
| 111 |
-
return new WP_Error( 'rest_forbidden', __( 'Sorry, you cannot delete the meta for this post.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 112 |
-
}
|
| 113 |
-
return true;
|
| 114 |
-
}
|
| 115 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lib/endpoints/class-wp-rest-post-statuses-controller.php
CHANGED
|
@@ -2,24 +2,31 @@
|
|
| 2 |
|
| 3 |
class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
/**
|
| 6 |
* Register the routes for the objects of the controller.
|
| 7 |
*/
|
| 8 |
public function register_routes() {
|
| 9 |
|
| 10 |
-
register_rest_route(
|
| 11 |
array(
|
| 12 |
'methods' => WP_REST_Server::READABLE,
|
| 13 |
'callback' => array( $this, 'get_items' ),
|
|
|
|
| 14 |
'args' => $this->get_collection_params(),
|
| 15 |
),
|
| 16 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 17 |
) );
|
| 18 |
|
| 19 |
-
register_rest_route( '
|
| 20 |
array(
|
| 21 |
'methods' => WP_REST_Server::READABLE,
|
| 22 |
'callback' => array( $this, 'get_item' ),
|
|
|
|
| 23 |
'args' => array(
|
| 24 |
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
|
| 25 |
),
|
|
@@ -28,6 +35,25 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
|
|
| 28 |
) );
|
| 29 |
}
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
/**
|
| 32 |
* Get all post statuses, depending on user context
|
| 33 |
*
|
|
@@ -36,21 +62,58 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
|
|
| 36 |
*/
|
| 37 |
public function get_items( $request ) {
|
| 38 |
$data = array();
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
$
|
| 43 |
-
|
| 44 |
-
foreach ( $statuses as $obj ) {
|
| 45 |
-
$status = $this->prepare_item_for_response( $obj, $request );
|
| 46 |
-
if ( is_wp_error( $status ) ) {
|
| 47 |
continue;
|
| 48 |
}
|
|
|
|
| 49 |
$data[ $obj->name ] = $this->prepare_response_for_collection( $status );
|
| 50 |
}
|
| 51 |
return rest_ensure_response( $data );
|
| 52 |
}
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
/**
|
| 55 |
* Get a specific post status
|
| 56 |
*
|
|
@@ -60,7 +123,7 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
|
|
| 60 |
public function get_item( $request ) {
|
| 61 |
$obj = get_post_status_object( $request['status'] );
|
| 62 |
if ( empty( $obj ) ) {
|
| 63 |
-
return new WP_Error( 'rest_status_invalid', __( 'Invalid
|
| 64 |
}
|
| 65 |
$data = $this->prepare_item_for_response( $obj, $request );
|
| 66 |
return rest_ensure_response( $data );
|
|
@@ -74,9 +137,6 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
|
|
| 74 |
* @return WP_REST_Response Post status data
|
| 75 |
*/
|
| 76 |
public function prepare_item_for_response( $status, $request ) {
|
| 77 |
-
if ( ( false === $status->public && ! is_user_logged_in() ) || ( true === $status->internal && is_user_logged_in() ) ) {
|
| 78 |
-
return new WP_Error( 'rest_cannot_read_status', __( 'Cannot view status.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 79 |
-
}
|
| 80 |
|
| 81 |
$data = array(
|
| 82 |
'name' => $status->label,
|
|
@@ -94,12 +154,10 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
|
|
| 94 |
|
| 95 |
$response = rest_ensure_response( $data );
|
| 96 |
|
| 97 |
-
$posts_controller = new WP_REST_Posts_Controller( 'post' );
|
| 98 |
-
|
| 99 |
if ( 'publish' === $status->name ) {
|
| 100 |
-
$response->add_link( 'archives', rest_url( '/wp/v2/'
|
| 101 |
} else {
|
| 102 |
-
$response->add_link( 'archives', add_query_arg( 'status', $status->name, rest_url( '/wp/v2/'
|
| 103 |
}
|
| 104 |
|
| 105 |
/**
|
|
@@ -126,42 +184,49 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
|
|
| 126 |
'type' => 'object',
|
| 127 |
'properties' => array(
|
| 128 |
'name' => array(
|
| 129 |
-
'description' => __( 'The title for the
|
| 130 |
'type' => 'string',
|
| 131 |
-
'context' => array( 'view' ),
|
| 132 |
-
|
|
|
|
| 133 |
'private' => array(
|
| 134 |
-
'description' => __( 'Whether posts with this
|
| 135 |
'type' => 'boolean',
|
| 136 |
-
'context' => array( '
|
| 137 |
-
|
|
|
|
| 138 |
'protected' => array(
|
| 139 |
-
'description' => __( 'Whether posts with this
|
| 140 |
'type' => 'boolean',
|
| 141 |
-
'context' => array( '
|
| 142 |
-
|
|
|
|
| 143 |
'public' => array(
|
| 144 |
-
'description' => __( 'Whether posts of this
|
| 145 |
'type' => 'boolean',
|
| 146 |
-
'context' => array( 'view' ),
|
| 147 |
-
|
|
|
|
| 148 |
'queryable' => array(
|
| 149 |
-
'description' => __( 'Whether posts with this
|
| 150 |
'type' => 'boolean',
|
| 151 |
-
'context' => array( 'view' ),
|
| 152 |
-
|
|
|
|
| 153 |
'show_in_list' => array(
|
| 154 |
'description' => __( 'Whether to include posts in the edit listing for their post type.' ),
|
| 155 |
'type' => 'boolean',
|
| 156 |
-
'context' => array( '
|
| 157 |
-
|
|
|
|
| 158 |
'slug' => array(
|
| 159 |
-
'description' => __( 'An alphanumeric identifier for the
|
| 160 |
'type' => 'string',
|
| 161 |
-
'context' => array( 'view' ),
|
| 162 |
-
|
| 163 |
),
|
| 164 |
-
)
|
|
|
|
| 165 |
return $this->add_additional_fields_schema( $schema );
|
| 166 |
}
|
| 167 |
|
| 2 |
|
| 3 |
class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
|
| 4 |
|
| 5 |
+
public function __construct() {
|
| 6 |
+
$this->namespace = 'wp/v2';
|
| 7 |
+
$this->rest_base = 'statuses';
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
/**
|
| 11 |
* Register the routes for the objects of the controller.
|
| 12 |
*/
|
| 13 |
public function register_routes() {
|
| 14 |
|
| 15 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
|
| 16 |
array(
|
| 17 |
'methods' => WP_REST_Server::READABLE,
|
| 18 |
'callback' => array( $this, 'get_items' ),
|
| 19 |
+
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
| 20 |
'args' => $this->get_collection_params(),
|
| 21 |
),
|
| 22 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 23 |
) );
|
| 24 |
|
| 25 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<status>[\w-]+)', array(
|
| 26 |
array(
|
| 27 |
'methods' => WP_REST_Server::READABLE,
|
| 28 |
'callback' => array( $this, 'get_item' ),
|
| 29 |
+
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
| 30 |
'args' => array(
|
| 31 |
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
|
| 32 |
),
|
| 35 |
) );
|
| 36 |
}
|
| 37 |
|
| 38 |
+
/**
|
| 39 |
+
* Check whether a given request has permission to read post statuses.
|
| 40 |
+
*
|
| 41 |
+
* @param WP_REST_Request $request Full details about the request.
|
| 42 |
+
* @return WP_Error|boolean
|
| 43 |
+
*/
|
| 44 |
+
public function get_items_permissions_check( $request ) {
|
| 45 |
+
if ( 'edit' === $request['context'] ) {
|
| 46 |
+
$types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
|
| 47 |
+
foreach ( $types as $type ) {
|
| 48 |
+
if ( current_user_can( $type->cap->edit_posts ) ) {
|
| 49 |
+
return true;
|
| 50 |
+
}
|
| 51 |
+
}
|
| 52 |
+
return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot view this resource with edit context.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 53 |
+
}
|
| 54 |
+
return true;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
/**
|
| 58 |
* Get all post statuses, depending on user context
|
| 59 |
*
|
| 62 |
*/
|
| 63 |
public function get_items( $request ) {
|
| 64 |
$data = array();
|
| 65 |
+
$statuses = get_post_stati( array( 'internal' => false ), 'object' );
|
| 66 |
+
$statuses['trash'] = get_post_status_object( 'trash' );
|
| 67 |
+
foreach ( $statuses as $slug => $obj ) {
|
| 68 |
+
$ret = $this->check_read_permission( $obj );
|
| 69 |
+
if ( ! $ret ) {
|
|
|
|
|
|
|
|
|
|
| 70 |
continue;
|
| 71 |
}
|
| 72 |
+
$status = $this->prepare_item_for_response( $obj, $request );
|
| 73 |
$data[ $obj->name ] = $this->prepare_response_for_collection( $status );
|
| 74 |
}
|
| 75 |
return rest_ensure_response( $data );
|
| 76 |
}
|
| 77 |
|
| 78 |
+
/**
|
| 79 |
+
* Check if a given request has access to read a post status.
|
| 80 |
+
*
|
| 81 |
+
* @param WP_REST_Request $request Full details about the request.
|
| 82 |
+
* @return WP_Error|boolean
|
| 83 |
+
*/
|
| 84 |
+
public function get_item_permissions_check( $request ) {
|
| 85 |
+
$status = get_post_status_object( $request['status'] );
|
| 86 |
+
if ( empty( $status ) ) {
|
| 87 |
+
return new WP_Error( 'rest_status_invalid', __( 'Invalid resource.' ), array( 'status' => 404 ) );
|
| 88 |
+
}
|
| 89 |
+
$check = $this->check_read_permission( $status );
|
| 90 |
+
if ( ! $check ) {
|
| 91 |
+
return new WP_Error( 'rest_cannot_read_status', __( 'Cannot view resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 92 |
+
}
|
| 93 |
+
return true;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
/**
|
| 97 |
+
* Check whether a given post status should be visible
|
| 98 |
+
*
|
| 99 |
+
* @param object $status
|
| 100 |
+
* @return boolean
|
| 101 |
+
*/
|
| 102 |
+
protected function check_read_permission( $status ) {
|
| 103 |
+
if ( true === $status->public ) {
|
| 104 |
+
return true;
|
| 105 |
+
}
|
| 106 |
+
if ( false === $status->internal || 'trash' === $status->name ) {
|
| 107 |
+
$types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
|
| 108 |
+
foreach ( $types as $type ) {
|
| 109 |
+
if ( current_user_can( $type->cap->edit_posts ) ) {
|
| 110 |
+
return true;
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
}
|
| 114 |
+
return false;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
/**
|
| 118 |
* Get a specific post status
|
| 119 |
*
|
| 123 |
public function get_item( $request ) {
|
| 124 |
$obj = get_post_status_object( $request['status'] );
|
| 125 |
if ( empty( $obj ) ) {
|
| 126 |
+
return new WP_Error( 'rest_status_invalid', __( 'Invalid resource.' ), array( 'status' => 404 ) );
|
| 127 |
}
|
| 128 |
$data = $this->prepare_item_for_response( $obj, $request );
|
| 129 |
return rest_ensure_response( $data );
|
| 137 |
* @return WP_REST_Response Post status data
|
| 138 |
*/
|
| 139 |
public function prepare_item_for_response( $status, $request ) {
|
|
|
|
|
|
|
|
|
|
| 140 |
|
| 141 |
$data = array(
|
| 142 |
'name' => $status->label,
|
| 154 |
|
| 155 |
$response = rest_ensure_response( $data );
|
| 156 |
|
|
|
|
|
|
|
| 157 |
if ( 'publish' === $status->name ) {
|
| 158 |
+
$response->add_link( 'archives', rest_url( '/wp/v2/posts' ) );
|
| 159 |
} else {
|
| 160 |
+
$response->add_link( 'archives', add_query_arg( 'status', $status->name, rest_url( '/wp/v2/posts' ) ) );
|
| 161 |
}
|
| 162 |
|
| 163 |
/**
|
| 184 |
'type' => 'object',
|
| 185 |
'properties' => array(
|
| 186 |
'name' => array(
|
| 187 |
+
'description' => __( 'The title for the resource.' ),
|
| 188 |
'type' => 'string',
|
| 189 |
+
'context' => array( 'embed', 'view', 'edit' ),
|
| 190 |
+
'readonly' => true,
|
| 191 |
+
),
|
| 192 |
'private' => array(
|
| 193 |
+
'description' => __( 'Whether posts with this resource should be private.' ),
|
| 194 |
'type' => 'boolean',
|
| 195 |
+
'context' => array( 'edit' ),
|
| 196 |
+
'readonly' => true,
|
| 197 |
+
),
|
| 198 |
'protected' => array(
|
| 199 |
+
'description' => __( 'Whether posts with this resource should be protected.' ),
|
| 200 |
'type' => 'boolean',
|
| 201 |
+
'context' => array( 'edit' ),
|
| 202 |
+
'readonly' => true,
|
| 203 |
+
),
|
| 204 |
'public' => array(
|
| 205 |
+
'description' => __( 'Whether posts of this resource should be shown in the front end of the site.' ),
|
| 206 |
'type' => 'boolean',
|
| 207 |
+
'context' => array( 'view', 'edit' ),
|
| 208 |
+
'readonly' => true,
|
| 209 |
+
),
|
| 210 |
'queryable' => array(
|
| 211 |
+
'description' => __( 'Whether posts with this resource should be publicly-queryable.' ),
|
| 212 |
'type' => 'boolean',
|
| 213 |
+
'context' => array( 'view', 'edit' ),
|
| 214 |
+
'readonly' => true,
|
| 215 |
+
),
|
| 216 |
'show_in_list' => array(
|
| 217 |
'description' => __( 'Whether to include posts in the edit listing for their post type.' ),
|
| 218 |
'type' => 'boolean',
|
| 219 |
+
'context' => array( 'edit' ),
|
| 220 |
+
'readonly' => true,
|
| 221 |
+
),
|
| 222 |
'slug' => array(
|
| 223 |
+
'description' => __( 'An alphanumeric identifier for the resource.' ),
|
| 224 |
'type' => 'string',
|
| 225 |
+
'context' => array( 'embed', 'view', 'edit' ),
|
| 226 |
+
'readonly' => true,
|
| 227 |
),
|
| 228 |
+
),
|
| 229 |
+
);
|
| 230 |
return $this->add_additional_fields_schema( $schema );
|
| 231 |
}
|
| 232 |
|
lib/endpoints/class-wp-rest-post-types-controller.php
CHANGED
|
@@ -2,21 +2,27 @@
|
|
| 2 |
|
| 3 |
class WP_REST_Post_Types_Controller extends WP_REST_Controller {
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
/**
|
| 6 |
* Register the routes for the objects of the controller.
|
| 7 |
*/
|
| 8 |
public function register_routes() {
|
| 9 |
|
| 10 |
-
register_rest_route(
|
| 11 |
array(
|
| 12 |
'methods' => WP_REST_Server::READABLE,
|
| 13 |
'callback' => array( $this, 'get_items' ),
|
|
|
|
| 14 |
'args' => $this->get_collection_params(),
|
| 15 |
),
|
| 16 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 17 |
) );
|
| 18 |
|
| 19 |
-
register_rest_route( '
|
| 20 |
array(
|
| 21 |
'methods' => WP_REST_Server::READABLE,
|
| 22 |
'callback' => array( $this, 'get_item' ),
|
|
@@ -28,6 +34,24 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
|
|
| 28 |
) );
|
| 29 |
}
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
/**
|
| 32 |
* Get all public post types
|
| 33 |
*
|
|
@@ -55,13 +79,13 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
|
|
| 55 |
public function get_item( $request ) {
|
| 56 |
$obj = get_post_type_object( $request['type'] );
|
| 57 |
if ( empty( $obj ) ) {
|
| 58 |
-
return new WP_Error( 'rest_type_invalid', __( 'Invalid
|
| 59 |
}
|
| 60 |
if ( empty( $obj->show_in_rest ) ) {
|
| 61 |
-
return new WP_Error( 'rest_cannot_read_type', __( 'Cannot view
|
| 62 |
}
|
| 63 |
if ( 'edit' === $request['context'] && ! current_user_can( $obj->cap->edit_posts ) ) {
|
| 64 |
-
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to manage this
|
| 65 |
}
|
| 66 |
$data = $this->prepare_item_for_response( $obj, $request );
|
| 67 |
return rest_ensure_response( $data );
|
|
@@ -76,6 +100,7 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
|
|
| 76 |
*/
|
| 77 |
public function prepare_item_for_response( $post_type, $request ) {
|
| 78 |
$data = array(
|
|
|
|
| 79 |
'description' => $post_type->description,
|
| 80 |
'hierarchical' => $post_type->hierarchical,
|
| 81 |
'labels' => $post_type->labels,
|
|
@@ -92,7 +117,7 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
|
|
| 92 |
$base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name;
|
| 93 |
$response->add_links( array(
|
| 94 |
'collection' => array(
|
| 95 |
-
'href' => rest_url( '
|
| 96 |
),
|
| 97 |
'https://api.w.org/items' => array(
|
| 98 |
'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ),
|
|
@@ -122,33 +147,44 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
|
|
| 122 |
'title' => 'type',
|
| 123 |
'type' => 'object',
|
| 124 |
'properties' => array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
'description' => array(
|
| 126 |
-
'description' => __( 'A human-readable description of the
|
| 127 |
'type' => 'string',
|
| 128 |
'context' => array( 'view', 'edit' ),
|
| 129 |
-
|
|
|
|
| 130 |
'hierarchical' => array(
|
| 131 |
-
'description' => __( 'Whether or not the
|
| 132 |
'type' => 'boolean',
|
| 133 |
'context' => array( 'view', 'edit' ),
|
| 134 |
-
|
|
|
|
| 135 |
'labels' => array(
|
| 136 |
-
'description' => __( 'Human-readable labels for the
|
| 137 |
'type' => 'object',
|
| 138 |
'context' => array( 'edit' ),
|
| 139 |
-
|
|
|
|
| 140 |
'name' => array(
|
| 141 |
-
'description' => __( 'The title for the
|
| 142 |
'type' => 'string',
|
| 143 |
-
'context' => array( 'view', 'edit' ),
|
| 144 |
-
|
|
|
|
| 145 |
'slug' => array(
|
| 146 |
-
'description' => __( 'An alphanumeric identifier for the
|
| 147 |
'type' => 'string',
|
| 148 |
-
'context' => array( 'view', 'edit' ),
|
| 149 |
-
|
| 150 |
),
|
| 151 |
-
)
|
|
|
|
| 152 |
return $this->add_additional_fields_schema( $schema );
|
| 153 |
}
|
| 154 |
|
| 2 |
|
| 3 |
class WP_REST_Post_Types_Controller extends WP_REST_Controller {
|
| 4 |
|
| 5 |
+
public function __construct() {
|
| 6 |
+
$this->namespace = 'wp/v2';
|
| 7 |
+
$this->rest_base = 'types';
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
/**
|
| 11 |
* Register the routes for the objects of the controller.
|
| 12 |
*/
|
| 13 |
public function register_routes() {
|
| 14 |
|
| 15 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
|
| 16 |
array(
|
| 17 |
'methods' => WP_REST_Server::READABLE,
|
| 18 |
'callback' => array( $this, 'get_items' ),
|
| 19 |
+
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
| 20 |
'args' => $this->get_collection_params(),
|
| 21 |
),
|
| 22 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 23 |
) );
|
| 24 |
|
| 25 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<type>[\w-]+)', array(
|
| 26 |
array(
|
| 27 |
'methods' => WP_REST_Server::READABLE,
|
| 28 |
'callback' => array( $this, 'get_item' ),
|
| 34 |
) );
|
| 35 |
}
|
| 36 |
|
| 37 |
+
/**
|
| 38 |
+
* Check whether a given request has permission to read types.
|
| 39 |
+
*
|
| 40 |
+
* @param WP_REST_Request $request Full details about the request.
|
| 41 |
+
* @return WP_Error|boolean
|
| 42 |
+
*/
|
| 43 |
+
public function get_items_permissions_check( $request ) {
|
| 44 |
+
if ( 'edit' === $request['context'] ) {
|
| 45 |
+
foreach ( get_post_types( array(), 'object' ) as $post_type ) {
|
| 46 |
+
if ( ! empty( $post_type->show_in_rest ) && current_user_can( $post_type->cap->edit_posts ) ) {
|
| 47 |
+
return true;
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot view this resource with edit context.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 51 |
+
}
|
| 52 |
+
return true;
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
/**
|
| 56 |
* Get all public post types
|
| 57 |
*
|
| 79 |
public function get_item( $request ) {
|
| 80 |
$obj = get_post_type_object( $request['type'] );
|
| 81 |
if ( empty( $obj ) ) {
|
| 82 |
+
return new WP_Error( 'rest_type_invalid', __( 'Invalid resource.' ), array( 'status' => 404 ) );
|
| 83 |
}
|
| 84 |
if ( empty( $obj->show_in_rest ) ) {
|
| 85 |
+
return new WP_Error( 'rest_cannot_read_type', __( 'Cannot view resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 86 |
}
|
| 87 |
if ( 'edit' === $request['context'] && ! current_user_can( $obj->cap->edit_posts ) ) {
|
| 88 |
+
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to manage this resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 89 |
}
|
| 90 |
$data = $this->prepare_item_for_response( $obj, $request );
|
| 91 |
return rest_ensure_response( $data );
|
| 100 |
*/
|
| 101 |
public function prepare_item_for_response( $post_type, $request ) {
|
| 102 |
$data = array(
|
| 103 |
+
'capabilities' => $post_type->cap,
|
| 104 |
'description' => $post_type->description,
|
| 105 |
'hierarchical' => $post_type->hierarchical,
|
| 106 |
'labels' => $post_type->labels,
|
| 117 |
$base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name;
|
| 118 |
$response->add_links( array(
|
| 119 |
'collection' => array(
|
| 120 |
+
'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
|
| 121 |
),
|
| 122 |
'https://api.w.org/items' => array(
|
| 123 |
'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ),
|
| 147 |
'title' => 'type',
|
| 148 |
'type' => 'object',
|
| 149 |
'properties' => array(
|
| 150 |
+
'capabilities' => array(
|
| 151 |
+
'description' => __( 'All capabilities used by the resource.' ),
|
| 152 |
+
'type' => 'array',
|
| 153 |
+
'context' => array( 'edit' ),
|
| 154 |
+
'readonly' => true,
|
| 155 |
+
),
|
| 156 |
'description' => array(
|
| 157 |
+
'description' => __( 'A human-readable description of the resource.' ),
|
| 158 |
'type' => 'string',
|
| 159 |
'context' => array( 'view', 'edit' ),
|
| 160 |
+
'readonly' => true,
|
| 161 |
+
),
|
| 162 |
'hierarchical' => array(
|
| 163 |
+
'description' => __( 'Whether or not the resource should have children.' ),
|
| 164 |
'type' => 'boolean',
|
| 165 |
'context' => array( 'view', 'edit' ),
|
| 166 |
+
'readonly' => true,
|
| 167 |
+
),
|
| 168 |
'labels' => array(
|
| 169 |
+
'description' => __( 'Human-readable labels for the resource for various contexts.' ),
|
| 170 |
'type' => 'object',
|
| 171 |
'context' => array( 'edit' ),
|
| 172 |
+
'readonly' => true,
|
| 173 |
+
),
|
| 174 |
'name' => array(
|
| 175 |
+
'description' => __( 'The title for the resource.' ),
|
| 176 |
'type' => 'string',
|
| 177 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 178 |
+
'readonly' => true,
|
| 179 |
+
),
|
| 180 |
'slug' => array(
|
| 181 |
+
'description' => __( 'An alphanumeric identifier for the resource.' ),
|
| 182 |
'type' => 'string',
|
| 183 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 184 |
+
'readonly' => true,
|
| 185 |
),
|
| 186 |
+
),
|
| 187 |
+
);
|
| 188 |
return $this->add_additional_fields_schema( $schema );
|
| 189 |
}
|
| 190 |
|
lib/endpoints/class-wp-rest-posts-controller.php
CHANGED
|
@@ -6,6 +6,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 6 |
|
| 7 |
public function __construct( $post_type ) {
|
| 8 |
$this->post_type = $post_type;
|
|
|
|
|
|
|
|
|
|
| 9 |
}
|
| 10 |
|
| 11 |
/**
|
|
@@ -13,9 +16,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 13 |
*/
|
| 14 |
public function register_routes() {
|
| 15 |
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
register_rest_route( 'wp/v2', '/' . $base, array(
|
| 19 |
array(
|
| 20 |
'methods' => WP_REST_Server::READABLE,
|
| 21 |
'callback' => array( $this, 'get_items' ),
|
|
@@ -28,10 +29,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 28 |
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
| 29 |
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
| 30 |
),
|
| 31 |
-
|
| 32 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 33 |
) );
|
| 34 |
-
register_rest_route(
|
| 35 |
array(
|
| 36 |
'methods' => WP_REST_Server::READABLE,
|
| 37 |
'callback' => array( $this, 'get_item' ),
|
|
@@ -57,7 +57,6 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 57 |
),
|
| 58 |
),
|
| 59 |
),
|
| 60 |
-
|
| 61 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 62 |
) );
|
| 63 |
}
|
|
@@ -87,7 +86,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 87 |
*/
|
| 88 |
public function get_items( $request ) {
|
| 89 |
$args = array();
|
| 90 |
-
$args['
|
|
|
|
|
|
|
| 91 |
$args['offset'] = $request['offset'];
|
| 92 |
$args['order'] = $request['order'];
|
| 93 |
$args['orderby'] = $request['orderby'];
|
|
@@ -121,7 +122,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 121 |
* @param WP_REST_Request $request The request used.
|
| 122 |
*/
|
| 123 |
$args = apply_filters( "rest_{$this->post_type}_query", $args, $request );
|
| 124 |
-
$query_args = $this->prepare_items_query( $args );
|
| 125 |
|
| 126 |
$posts_query = new WP_Query();
|
| 127 |
$query_result = $posts_query->query( $query_args );
|
|
@@ -159,7 +160,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 159 |
unset( $request_params['filter']['posts_per_page'] );
|
| 160 |
unset( $request_params['filter']['paged'] );
|
| 161 |
}
|
| 162 |
-
$base = add_query_arg( $request_params, rest_url( '
|
| 163 |
|
| 164 |
if ( $page > 1 ) {
|
| 165 |
$prev_page = $page - 1;
|
|
@@ -321,7 +322,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 321 |
$response = $this->prepare_item_for_response( $post, $request );
|
| 322 |
$response = rest_ensure_response( $response );
|
| 323 |
$response->set_status( 201 );
|
| 324 |
-
$response->header( 'Location', rest_url( '
|
| 325 |
|
| 326 |
return $response;
|
| 327 |
}
|
|
@@ -481,7 +482,6 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 481 |
// If we're forcing, then delete permanently.
|
| 482 |
if ( $force ) {
|
| 483 |
$result = wp_delete_post( $id, true );
|
| 484 |
-
$status = 'deleted';
|
| 485 |
} else {
|
| 486 |
// If we don't support trashing for this type, error out.
|
| 487 |
if ( ! $supports_trash ) {
|
|
@@ -496,28 +496,20 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 496 |
// (Note that internally this falls through to `wp_delete_post` if
|
| 497 |
// the trash is disabled.)
|
| 498 |
$result = wp_trash_post( $id );
|
| 499 |
-
$status = 'trashed';
|
| 500 |
}
|
| 501 |
|
| 502 |
if ( ! $result ) {
|
| 503 |
return new WP_Error( 'rest_cannot_delete', __( 'The post cannot be deleted.' ), array( 'status' => 500 ) );
|
| 504 |
}
|
| 505 |
|
| 506 |
-
$data = $response->get_data();
|
| 507 |
-
$data = array(
|
| 508 |
-
'data' => $data,
|
| 509 |
-
$status => true,
|
| 510 |
-
);
|
| 511 |
-
$response->set_data( $data );
|
| 512 |
-
|
| 513 |
/**
|
| 514 |
* Fires after a single post is deleted or trashed via the REST API.
|
| 515 |
*
|
| 516 |
-
* @param object
|
| 517 |
-
* @param
|
| 518 |
-
* @param WP_REST_Request
|
| 519 |
*/
|
| 520 |
-
do_action( "rest_delete_{$this->post_type}", $post, $
|
| 521 |
|
| 522 |
return $response;
|
| 523 |
}
|
|
@@ -526,10 +518,11 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 526 |
* Determine the allowed query_vars for a get_items() response and
|
| 527 |
* prepare for WP_Query.
|
| 528 |
*
|
| 529 |
-
* @param array
|
| 530 |
-
* @
|
|
|
|
| 531 |
*/
|
| 532 |
-
protected function prepare_items_query( $prepared_args = array() ) {
|
| 533 |
|
| 534 |
$valid_vars = array_flip( $this->get_allowed_query_vars() );
|
| 535 |
$query_args = array();
|
|
@@ -594,7 +587,19 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 594 |
$valid_vars = array_merge( $valid_vars, $private );
|
| 595 |
}
|
| 596 |
// Define our own in addition to WP's normal vars.
|
| 597 |
-
$rest_valid = array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 598 |
$valid_vars = array_merge( $valid_vars, $rest_valid );
|
| 599 |
|
| 600 |
/**
|
|
@@ -1027,22 +1032,6 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1027 |
return current_user_can( $post_type->cap->delete_post, $post->ID );
|
| 1028 |
}
|
| 1029 |
|
| 1030 |
-
/**
|
| 1031 |
-
* Get the base path for a post type's endpoints.
|
| 1032 |
-
*
|
| 1033 |
-
* @param object|string $post_type
|
| 1034 |
-
* @return string $base
|
| 1035 |
-
*/
|
| 1036 |
-
public function get_post_type_base( $post_type ) {
|
| 1037 |
-
if ( ! is_object( $post_type ) ) {
|
| 1038 |
-
$post_type = get_post_type_object( $post_type );
|
| 1039 |
-
}
|
| 1040 |
-
|
| 1041 |
-
$base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name;
|
| 1042 |
-
|
| 1043 |
-
return $base;
|
| 1044 |
-
}
|
| 1045 |
-
|
| 1046 |
/**
|
| 1047 |
* Prepare a single post output for response.
|
| 1048 |
*
|
|
@@ -1154,7 +1143,8 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1154 |
$taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
|
| 1155 |
foreach ( $taxonomies as $taxonomy ) {
|
| 1156 |
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
|
| 1157 |
-
$
|
|
|
|
| 1158 |
}
|
| 1159 |
|
| 1160 |
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
|
@@ -1186,7 +1176,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1186 |
* @return array Links for the given post.
|
| 1187 |
*/
|
| 1188 |
protected function prepare_links( $post ) {
|
| 1189 |
-
$base = '
|
| 1190 |
|
| 1191 |
// Entity meta
|
| 1192 |
$links = array(
|
|
@@ -1452,7 +1442,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1452 |
'context' => array( 'edit' ),
|
| 1453 |
),
|
| 1454 |
'rendered' => array(
|
| 1455 |
-
'description' => __( '
|
| 1456 |
'type' => 'string',
|
| 1457 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 1458 |
),
|
|
@@ -1472,7 +1462,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1472 |
'context' => array( 'edit' ),
|
| 1473 |
),
|
| 1474 |
'rendered' => array(
|
| 1475 |
-
'description' => __( '
|
| 1476 |
'type' => 'string',
|
| 1477 |
'context' => array( 'view', 'edit' ),
|
| 1478 |
),
|
|
@@ -1500,7 +1490,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1500 |
'context' => array( 'edit' ),
|
| 1501 |
),
|
| 1502 |
'rendered' => array(
|
| 1503 |
-
'description' => __( '
|
| 1504 |
'type' => 'string',
|
| 1505 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 1506 |
),
|
|
@@ -1593,10 +1583,18 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1593 |
|
| 1594 |
if ( post_type_supports( $this->post_type, 'author' ) ) {
|
| 1595 |
$params['author'] = array(
|
| 1596 |
-
'description' => __( 'Limit result set to posts assigned to
|
| 1597 |
-
'type' => '
|
| 1598 |
-
'default' =>
|
| 1599 |
-
'sanitize_callback' => '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1600 |
);
|
| 1601 |
}
|
| 1602 |
$params['exclude'] = array(
|
|
@@ -1611,16 +1609,26 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1611 |
'default' => array(),
|
| 1612 |
'sanitize_callback' => 'wp_parse_id_list',
|
| 1613 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1614 |
$params['offset'] = array(
|
| 1615 |
'description' => __( 'Offset the result set by a specific number of items.' ),
|
| 1616 |
'type' => 'integer',
|
| 1617 |
'sanitize_callback' => 'absint',
|
|
|
|
| 1618 |
);
|
| 1619 |
$params['order'] = array(
|
| 1620 |
'description' => __( 'Order sort attribute ascending or descending.' ),
|
| 1621 |
'type' => 'string',
|
| 1622 |
'default' => 'desc',
|
| 1623 |
'enum' => array( 'asc', 'desc' ),
|
|
|
|
| 1624 |
);
|
| 1625 |
$params['orderby'] = array(
|
| 1626 |
'description' => __( 'Sort collection by object attribute.' ),
|
|
@@ -1633,7 +1641,11 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1633 |
'title',
|
| 1634 |
'slug',
|
| 1635 |
),
|
|
|
|
| 1636 |
);
|
|
|
|
|
|
|
|
|
|
| 1637 |
|
| 1638 |
$post_type_obj = get_post_type_object( $this->post_type );
|
| 1639 |
if ( $post_type_obj->hierarchical || 'attachment' === $this->post_type ) {
|
|
@@ -1654,6 +1666,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
|
|
| 1654 |
$params['slug'] = array(
|
| 1655 |
'description' => __( 'Limit result set to posts with a specific slug.' ),
|
| 1656 |
'type' => 'string',
|
|
|
|
| 1657 |
);
|
| 1658 |
$params['status'] = array(
|
| 1659 |
'default' => 'publish',
|
| 6 |
|
| 7 |
public function __construct( $post_type ) {
|
| 8 |
$this->post_type = $post_type;
|
| 9 |
+
$this->namespace = 'wp/v2';
|
| 10 |
+
$obj = get_post_type_object( $post_type );
|
| 11 |
+
$this->rest_base = ! empty( $obj->rest_base ) ? $obj->rest_base : $obj->name;
|
| 12 |
}
|
| 13 |
|
| 14 |
/**
|
| 16 |
*/
|
| 17 |
public function register_routes() {
|
| 18 |
|
| 19 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
|
|
|
|
|
|
|
| 20 |
array(
|
| 21 |
'methods' => WP_REST_Server::READABLE,
|
| 22 |
'callback' => array( $this, 'get_items' ),
|
| 29 |
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
| 30 |
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
| 31 |
),
|
|
|
|
| 32 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 33 |
) );
|
| 34 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
|
| 35 |
array(
|
| 36 |
'methods' => WP_REST_Server::READABLE,
|
| 37 |
'callback' => array( $this, 'get_item' ),
|
| 57 |
),
|
| 58 |
),
|
| 59 |
),
|
|
|
|
| 60 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 61 |
) );
|
| 62 |
}
|
| 86 |
*/
|
| 87 |
public function get_items( $request ) {
|
| 88 |
$args = array();
|
| 89 |
+
$args['author__in'] = $request['author'];
|
| 90 |
+
$args['author__not_in'] = $request['author_exclude'];
|
| 91 |
+
$args['menu_order'] = $request['menu_order'];
|
| 92 |
$args['offset'] = $request['offset'];
|
| 93 |
$args['order'] = $request['order'];
|
| 94 |
$args['orderby'] = $request['orderby'];
|
| 122 |
* @param WP_REST_Request $request The request used.
|
| 123 |
*/
|
| 124 |
$args = apply_filters( "rest_{$this->post_type}_query", $args, $request );
|
| 125 |
+
$query_args = $this->prepare_items_query( $args, $request );
|
| 126 |
|
| 127 |
$posts_query = new WP_Query();
|
| 128 |
$query_result = $posts_query->query( $query_args );
|
| 160 |
unset( $request_params['filter']['posts_per_page'] );
|
| 161 |
unset( $request_params['filter']['paged'] );
|
| 162 |
}
|
| 163 |
+
$base = add_query_arg( $request_params, rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
|
| 164 |
|
| 165 |
if ( $page > 1 ) {
|
| 166 |
$prev_page = $page - 1;
|
| 322 |
$response = $this->prepare_item_for_response( $post, $request );
|
| 323 |
$response = rest_ensure_response( $response );
|
| 324 |
$response->set_status( 201 );
|
| 325 |
+
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $post_id ) ) );
|
| 326 |
|
| 327 |
return $response;
|
| 328 |
}
|
| 482 |
// If we're forcing, then delete permanently.
|
| 483 |
if ( $force ) {
|
| 484 |
$result = wp_delete_post( $id, true );
|
|
|
|
| 485 |
} else {
|
| 486 |
// If we don't support trashing for this type, error out.
|
| 487 |
if ( ! $supports_trash ) {
|
| 496 |
// (Note that internally this falls through to `wp_delete_post` if
|
| 497 |
// the trash is disabled.)
|
| 498 |
$result = wp_trash_post( $id );
|
|
|
|
| 499 |
}
|
| 500 |
|
| 501 |
if ( ! $result ) {
|
| 502 |
return new WP_Error( 'rest_cannot_delete', __( 'The post cannot be deleted.' ), array( 'status' => 500 ) );
|
| 503 |
}
|
| 504 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 505 |
/**
|
| 506 |
* Fires after a single post is deleted or trashed via the REST API.
|
| 507 |
*
|
| 508 |
+
* @param object $post The deleted or trashed post.
|
| 509 |
+
* @param WP_REST_Response $response The response data.
|
| 510 |
+
* @param WP_REST_Request $request The request sent to the API.
|
| 511 |
*/
|
| 512 |
+
do_action( "rest_delete_{$this->post_type}", $post, $response, $request );
|
| 513 |
|
| 514 |
return $response;
|
| 515 |
}
|
| 518 |
* Determine the allowed query_vars for a get_items() response and
|
| 519 |
* prepare for WP_Query.
|
| 520 |
*
|
| 521 |
+
* @param array $prepared_args
|
| 522 |
+
* @param WP_REST_Request $request
|
| 523 |
+
* @return array $query_args
|
| 524 |
*/
|
| 525 |
+
protected function prepare_items_query( $prepared_args = array(), $request = null ) {
|
| 526 |
|
| 527 |
$valid_vars = array_flip( $this->get_allowed_query_vars() );
|
| 528 |
$query_args = array();
|
| 587 |
$valid_vars = array_merge( $valid_vars, $private );
|
| 588 |
}
|
| 589 |
// Define our own in addition to WP's normal vars.
|
| 590 |
+
$rest_valid = array(
|
| 591 |
+
'author__in',
|
| 592 |
+
'author__not_in',
|
| 593 |
+
'ignore_sticky_posts',
|
| 594 |
+
'menu_order',
|
| 595 |
+
'offset',
|
| 596 |
+
'post__in',
|
| 597 |
+
'post__not_in',
|
| 598 |
+
'post_parent',
|
| 599 |
+
'post_parent__in',
|
| 600 |
+
'post_parent__not_in',
|
| 601 |
+
'posts_per_page',
|
| 602 |
+
);
|
| 603 |
$valid_vars = array_merge( $valid_vars, $rest_valid );
|
| 604 |
|
| 605 |
/**
|
| 1032 |
return current_user_can( $post_type->cap->delete_post, $post->ID );
|
| 1033 |
}
|
| 1034 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1035 |
/**
|
| 1036 |
* Prepare a single post output for response.
|
| 1037 |
*
|
| 1143 |
$taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );
|
| 1144 |
foreach ( $taxonomies as $taxonomy ) {
|
| 1145 |
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
|
| 1146 |
+
$terms = get_the_terms( $post, $taxonomy->name );
|
| 1147 |
+
$data[ $base ] = $terms ? wp_list_pluck( $terms, 'term_id' ) : array();
|
| 1148 |
}
|
| 1149 |
|
| 1150 |
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
| 1176 |
* @return array Links for the given post.
|
| 1177 |
*/
|
| 1178 |
protected function prepare_links( $post ) {
|
| 1179 |
+
$base = sprintf( '/%s/%s', $this->namespace, $this->rest_base );
|
| 1180 |
|
| 1181 |
// Entity meta
|
| 1182 |
$links = array(
|
| 1442 |
'context' => array( 'edit' ),
|
| 1443 |
),
|
| 1444 |
'rendered' => array(
|
| 1445 |
+
'description' => __( 'HTML title for the object, transformed for display.' ),
|
| 1446 |
'type' => 'string',
|
| 1447 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 1448 |
),
|
| 1462 |
'context' => array( 'edit' ),
|
| 1463 |
),
|
| 1464 |
'rendered' => array(
|
| 1465 |
+
'description' => __( 'HTML content for the object, transformed for display.' ),
|
| 1466 |
'type' => 'string',
|
| 1467 |
'context' => array( 'view', 'edit' ),
|
| 1468 |
),
|
| 1490 |
'context' => array( 'edit' ),
|
| 1491 |
),
|
| 1492 |
'rendered' => array(
|
| 1493 |
+
'description' => __( 'HTML excerpt for the object, transformed for display.' ),
|
| 1494 |
'type' => 'string',
|
| 1495 |
'context' => array( 'view', 'edit', 'embed' ),
|
| 1496 |
),
|
| 1583 |
|
| 1584 |
if ( post_type_supports( $this->post_type, 'author' ) ) {
|
| 1585 |
$params['author'] = array(
|
| 1586 |
+
'description' => __( 'Limit result set to posts assigned to specific authors.' ),
|
| 1587 |
+
'type' => 'array',
|
| 1588 |
+
'default' => array(),
|
| 1589 |
+
'sanitize_callback' => 'wp_parse_id_list',
|
| 1590 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1591 |
+
);
|
| 1592 |
+
$params['author_exclude'] = array(
|
| 1593 |
+
'description' => __( 'Ensure result set excludes posts assigned to specific authors.' ),
|
| 1594 |
+
'type' => 'array',
|
| 1595 |
+
'default' => array(),
|
| 1596 |
+
'sanitize_callback' => 'wp_parse_id_list',
|
| 1597 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1598 |
);
|
| 1599 |
}
|
| 1600 |
$params['exclude'] = array(
|
| 1609 |
'default' => array(),
|
| 1610 |
'sanitize_callback' => 'wp_parse_id_list',
|
| 1611 |
);
|
| 1612 |
+
if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) {
|
| 1613 |
+
$params['menu_order'] = array(
|
| 1614 |
+
'description' => __( 'Limit result set to resources with a specific menu_order value.' ),
|
| 1615 |
+
'type' => 'integer',
|
| 1616 |
+
'sanitize_callback' => 'absint',
|
| 1617 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1618 |
+
);
|
| 1619 |
+
}
|
| 1620 |
$params['offset'] = array(
|
| 1621 |
'description' => __( 'Offset the result set by a specific number of items.' ),
|
| 1622 |
'type' => 'integer',
|
| 1623 |
'sanitize_callback' => 'absint',
|
| 1624 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1625 |
);
|
| 1626 |
$params['order'] = array(
|
| 1627 |
'description' => __( 'Order sort attribute ascending or descending.' ),
|
| 1628 |
'type' => 'string',
|
| 1629 |
'default' => 'desc',
|
| 1630 |
'enum' => array( 'asc', 'desc' ),
|
| 1631 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1632 |
);
|
| 1633 |
$params['orderby'] = array(
|
| 1634 |
'description' => __( 'Sort collection by object attribute.' ),
|
| 1641 |
'title',
|
| 1642 |
'slug',
|
| 1643 |
),
|
| 1644 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1645 |
);
|
| 1646 |
+
if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) {
|
| 1647 |
+
$params['orderby']['enum'][] = 'menu_order';
|
| 1648 |
+
}
|
| 1649 |
|
| 1650 |
$post_type_obj = get_post_type_object( $this->post_type );
|
| 1651 |
if ( $post_type_obj->hierarchical || 'attachment' === $this->post_type ) {
|
| 1666 |
$params['slug'] = array(
|
| 1667 |
'description' => __( 'Limit result set to posts with a specific slug.' ),
|
| 1668 |
'type' => 'string',
|
| 1669 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 1670 |
);
|
| 1671 |
$params['status'] = array(
|
| 1672 |
'default' => 'publish',
|
lib/endpoints/class-wp-rest-revisions-controller.php
CHANGED
|
@@ -9,7 +9,10 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 9 |
public function __construct( $parent_post_type ) {
|
| 10 |
$this->parent_post_type = $parent_post_type;
|
| 11 |
$this->parent_controller = new WP_REST_Posts_Controller( $parent_post_type );
|
| 12 |
-
$this->
|
|
|
|
|
|
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
/**
|
|
@@ -17,18 +20,17 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 17 |
*/
|
| 18 |
public function register_routes() {
|
| 19 |
|
| 20 |
-
register_rest_route(
|
| 21 |
array(
|
| 22 |
'methods' => WP_REST_Server::READABLE,
|
| 23 |
'callback' => array( $this, 'get_items' ),
|
| 24 |
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
| 25 |
'args' => $this->get_collection_params(),
|
| 26 |
),
|
| 27 |
-
|
| 28 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 29 |
) );
|
| 30 |
|
| 31 |
-
register_rest_route(
|
| 32 |
array(
|
| 33 |
'methods' => WP_REST_Server::READABLE,
|
| 34 |
'callback' => array( $this, 'get_item' ),
|
|
@@ -42,7 +44,6 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 42 |
'callback' => array( $this, 'delete_item' ),
|
| 43 |
'permission_callback' => array( $this, 'delete_item_permissions_check' ),
|
| 44 |
),
|
| 45 |
-
|
| 46 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 47 |
));
|
| 48 |
|
|
@@ -56,7 +57,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 56 |
*/
|
| 57 |
public function get_items_permissions_check( $request ) {
|
| 58 |
|
| 59 |
-
$parent = get_post( $request['
|
| 60 |
if ( ! $parent ) {
|
| 61 |
return true;
|
| 62 |
}
|
|
@@ -76,12 +77,12 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 76 |
*/
|
| 77 |
public function get_items( $request ) {
|
| 78 |
|
| 79 |
-
$parent = get_post( $request['
|
| 80 |
-
if ( ! $request['
|
| 81 |
-
return new WP_Error( '
|
| 82 |
}
|
| 83 |
|
| 84 |
-
$revisions = wp_get_post_revisions( $request['
|
| 85 |
|
| 86 |
$response = array();
|
| 87 |
foreach ( $revisions as $revision ) {
|
|
@@ -109,9 +110,9 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 109 |
*/
|
| 110 |
public function get_item( $request ) {
|
| 111 |
|
| 112 |
-
$parent = get_post( $request['
|
| 113 |
-
if ( ! $request['
|
| 114 |
-
return new WP_Error( '
|
| 115 |
}
|
| 116 |
|
| 117 |
$revision = get_post( $request['id'] );
|
|
@@ -209,7 +210,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 209 |
$response = rest_ensure_response( $data );
|
| 210 |
|
| 211 |
if ( ! empty( $data['parent'] ) ) {
|
| 212 |
-
$response->add_link( 'parent', rest_url( sprintf( '
|
| 213 |
}
|
| 214 |
|
| 215 |
/**
|
|
@@ -259,53 +260,53 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 259 |
*/
|
| 260 |
'properties' => array(
|
| 261 |
'author' => array(
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
'date' => array(
|
| 267 |
'description' => __( 'The date the object was published.' ),
|
| 268 |
'type' => 'string',
|
| 269 |
'format' => 'date-time',
|
| 270 |
-
'context' => array( 'view' ),
|
| 271 |
),
|
| 272 |
'date_gmt' => array(
|
| 273 |
'description' => __( 'The date the object was published, as GMT.' ),
|
| 274 |
'type' => 'string',
|
| 275 |
'format' => 'date-time',
|
| 276 |
-
'context' => array( 'view' ),
|
| 277 |
),
|
| 278 |
'guid' => array(
|
| 279 |
'description' => __( 'GUID for the object, as it exists in the database.' ),
|
| 280 |
'type' => 'string',
|
| 281 |
-
'context' => array( 'view' ),
|
| 282 |
),
|
| 283 |
'id' => array(
|
| 284 |
'description' => __( 'Unique identifier for the object.' ),
|
| 285 |
'type' => 'integer',
|
| 286 |
-
'context' => array( 'view' ),
|
| 287 |
),
|
| 288 |
'modified' => array(
|
| 289 |
'description' => __( 'The date the object was last modified.' ),
|
| 290 |
'type' => 'string',
|
| 291 |
'format' => 'date-time',
|
| 292 |
-
'context' => array( 'view' ),
|
| 293 |
),
|
| 294 |
'modified_gmt' => array(
|
| 295 |
'description' => __( 'The date the object was last modified, as GMT.' ),
|
| 296 |
'type' => 'string',
|
| 297 |
'format' => 'date-time',
|
| 298 |
-
'context' => array( 'view' ),
|
| 299 |
),
|
| 300 |
'parent' => array(
|
| 301 |
'description' => __( 'The id for the parent of the object.' ),
|
| 302 |
'type' => 'integer',
|
| 303 |
-
'context' => array( 'view' ),
|
| 304 |
),
|
| 305 |
'slug' => array(
|
| 306 |
'description' => __( 'An alphanumeric identifier for the object unique to its type.' ),
|
| 307 |
'type' => 'string',
|
| 308 |
-
'context' => array( 'view' ),
|
| 309 |
),
|
| 310 |
),
|
| 311 |
);
|
|
@@ -323,7 +324,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 323 |
$schema['properties']['title'] = array(
|
| 324 |
'description' => __( 'Title for the object, as it exists in the database.' ),
|
| 325 |
'type' => 'string',
|
| 326 |
-
'context' => array( 'view' ),
|
| 327 |
);
|
| 328 |
break;
|
| 329 |
|
|
@@ -331,7 +332,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 331 |
$schema['properties']['content'] = array(
|
| 332 |
'description' => __( 'Content for the object, as it exists in the database.' ),
|
| 333 |
'type' => 'string',
|
| 334 |
-
'context' => array( 'view' ),
|
| 335 |
);
|
| 336 |
break;
|
| 337 |
|
|
@@ -339,7 +340,7 @@ class WP_REST_Revisions_Controller extends WP_REST_Controller {
|
|
| 339 |
$schema['properties']['excerpt'] = array(
|
| 340 |
'description' => __( 'Excerpt for the object, as it exists in the database.' ),
|
| 341 |
'type' => 'string',
|
| 342 |
-
'context' => array( 'view' ),
|
| 343 |
);
|
| 344 |
break;
|
| 345 |
|
| 9 |
public function __construct( $parent_post_type ) {
|
| 10 |
$this->parent_post_type = $parent_post_type;
|
| 11 |
$this->parent_controller = new WP_REST_Posts_Controller( $parent_post_type );
|
| 12 |
+
$this->namespace = 'wp/v2';
|
| 13 |
+
$this->rest_base = 'revisions';
|
| 14 |
+
$post_type_object = get_post_type_object( $parent_post_type );
|
| 15 |
+
$this->parent_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name;
|
| 16 |
}
|
| 17 |
|
| 18 |
/**
|
| 20 |
*/
|
| 21 |
public function register_routes() {
|
| 22 |
|
| 23 |
+
register_rest_route( $this->namespace, '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base, array(
|
| 24 |
array(
|
| 25 |
'methods' => WP_REST_Server::READABLE,
|
| 26 |
'callback' => array( $this, 'get_items' ),
|
| 27 |
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
| 28 |
'args' => $this->get_collection_params(),
|
| 29 |
),
|
|
|
|
| 30 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 31 |
) );
|
| 32 |
|
| 33 |
+
register_rest_route( $this->namespace, '/' . $this->parent_base . '/(?P<parent>[\d]+)/' . $this->rest_base . '/(?P<id>[\d]+)', array(
|
| 34 |
array(
|
| 35 |
'methods' => WP_REST_Server::READABLE,
|
| 36 |
'callback' => array( $this, 'get_item' ),
|
| 44 |
'callback' => array( $this, 'delete_item' ),
|
| 45 |
'permission_callback' => array( $this, 'delete_item_permissions_check' ),
|
| 46 |
),
|
|
|
|
| 47 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 48 |
));
|
| 49 |
|
| 57 |
*/
|
| 58 |
public function get_items_permissions_check( $request ) {
|
| 59 |
|
| 60 |
+
$parent = get_post( $request['parent'] );
|
| 61 |
if ( ! $parent ) {
|
| 62 |
return true;
|
| 63 |
}
|
| 77 |
*/
|
| 78 |
public function get_items( $request ) {
|
| 79 |
|
| 80 |
+
$parent = get_post( $request['parent'] );
|
| 81 |
+
if ( ! $request['parent'] || ! $parent || $this->parent_post_type !== $parent->post_type ) {
|
| 82 |
+
return new WP_Error( 'rest_post_invalid_parent', __( 'Invalid post parent id.' ), array( 'status' => 404 ) );
|
| 83 |
}
|
| 84 |
|
| 85 |
+
$revisions = wp_get_post_revisions( $request['parent'] );
|
| 86 |
|
| 87 |
$response = array();
|
| 88 |
foreach ( $revisions as $revision ) {
|
| 110 |
*/
|
| 111 |
public function get_item( $request ) {
|
| 112 |
|
| 113 |
+
$parent = get_post( $request['parent'] );
|
| 114 |
+
if ( ! $request['parent'] || ! $parent || $this->parent_post_type !== $parent->post_type ) {
|
| 115 |
+
return new WP_Error( 'rest_post_invalid_parent', __( 'Invalid post parent id.' ), array( 'status' => 404 ) );
|
| 116 |
}
|
| 117 |
|
| 118 |
$revision = get_post( $request['id'] );
|
| 210 |
$response = rest_ensure_response( $data );
|
| 211 |
|
| 212 |
if ( ! empty( $data['parent'] ) ) {
|
| 213 |
+
$response->add_link( 'parent', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->parent_base, $data['parent'] ) ) );
|
| 214 |
}
|
| 215 |
|
| 216 |
/**
|
| 260 |
*/
|
| 261 |
'properties' => array(
|
| 262 |
'author' => array(
|
| 263 |
+
'description' => __( 'The id for the author of the object.' ),
|
| 264 |
+
'type' => 'integer',
|
| 265 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 266 |
+
),
|
| 267 |
'date' => array(
|
| 268 |
'description' => __( 'The date the object was published.' ),
|
| 269 |
'type' => 'string',
|
| 270 |
'format' => 'date-time',
|
| 271 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 272 |
),
|
| 273 |
'date_gmt' => array(
|
| 274 |
'description' => __( 'The date the object was published, as GMT.' ),
|
| 275 |
'type' => 'string',
|
| 276 |
'format' => 'date-time',
|
| 277 |
+
'context' => array( 'view', 'edit' ),
|
| 278 |
),
|
| 279 |
'guid' => array(
|
| 280 |
'description' => __( 'GUID for the object, as it exists in the database.' ),
|
| 281 |
'type' => 'string',
|
| 282 |
+
'context' => array( 'view', 'edit' ),
|
| 283 |
),
|
| 284 |
'id' => array(
|
| 285 |
'description' => __( 'Unique identifier for the object.' ),
|
| 286 |
'type' => 'integer',
|
| 287 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 288 |
),
|
| 289 |
'modified' => array(
|
| 290 |
'description' => __( 'The date the object was last modified.' ),
|
| 291 |
'type' => 'string',
|
| 292 |
'format' => 'date-time',
|
| 293 |
+
'context' => array( 'view', 'edit' ),
|
| 294 |
),
|
| 295 |
'modified_gmt' => array(
|
| 296 |
'description' => __( 'The date the object was last modified, as GMT.' ),
|
| 297 |
'type' => 'string',
|
| 298 |
'format' => 'date-time',
|
| 299 |
+
'context' => array( 'view', 'edit' ),
|
| 300 |
),
|
| 301 |
'parent' => array(
|
| 302 |
'description' => __( 'The id for the parent of the object.' ),
|
| 303 |
'type' => 'integer',
|
| 304 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 305 |
),
|
| 306 |
'slug' => array(
|
| 307 |
'description' => __( 'An alphanumeric identifier for the object unique to its type.' ),
|
| 308 |
'type' => 'string',
|
| 309 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 310 |
),
|
| 311 |
),
|
| 312 |
);
|
| 324 |
$schema['properties']['title'] = array(
|
| 325 |
'description' => __( 'Title for the object, as it exists in the database.' ),
|
| 326 |
'type' => 'string',
|
| 327 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 328 |
);
|
| 329 |
break;
|
| 330 |
|
| 332 |
$schema['properties']['content'] = array(
|
| 333 |
'description' => __( 'Content for the object, as it exists in the database.' ),
|
| 334 |
'type' => 'string',
|
| 335 |
+
'context' => array( 'view', 'edit' ),
|
| 336 |
);
|
| 337 |
break;
|
| 338 |
|
| 340 |
$schema['properties']['excerpt'] = array(
|
| 341 |
'description' => __( 'Excerpt for the object, as it exists in the database.' ),
|
| 342 |
'type' => 'string',
|
| 343 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 344 |
);
|
| 345 |
break;
|
| 346 |
|
lib/endpoints/class-wp-rest-taxonomies-controller.php
CHANGED
|
@@ -2,21 +2,27 @@
|
|
| 2 |
|
| 3 |
class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
/**
|
| 6 |
* Register the routes for the objects of the controller.
|
| 7 |
*/
|
| 8 |
public function register_routes() {
|
| 9 |
|
| 10 |
-
register_rest_route(
|
| 11 |
array(
|
| 12 |
'methods' => WP_REST_Server::READABLE,
|
| 13 |
'callback' => array( $this, 'get_items' ),
|
|
|
|
| 14 |
'args' => $this->get_collection_params(),
|
| 15 |
),
|
| 16 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 17 |
) );
|
| 18 |
|
| 19 |
-
register_rest_route( '
|
| 20 |
array(
|
| 21 |
'methods' => WP_REST_Server::READABLE,
|
| 22 |
'callback' => array( $this, 'get_item' ),
|
|
@@ -29,6 +35,29 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
|
| 29 |
) );
|
| 30 |
}
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
/**
|
| 33 |
* Get all public taxonomies
|
| 34 |
*
|
|
@@ -68,7 +97,7 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
|
| 68 |
return false;
|
| 69 |
}
|
| 70 |
if ( 'edit' === $request['context'] && ! current_user_can( $tax_obj->cap->manage_terms ) ) {
|
| 71 |
-
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to manage this
|
| 72 |
}
|
| 73 |
}
|
| 74 |
|
|
@@ -84,7 +113,7 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
|
| 84 |
public function get_item( $request ) {
|
| 85 |
$tax_obj = get_taxonomy( $request['taxonomy'] );
|
| 86 |
if ( empty( $tax_obj ) ) {
|
| 87 |
-
return new WP_Error( 'rest_taxonomy_invalid', __( 'Invalid
|
| 88 |
}
|
| 89 |
$data = $this->prepare_item_for_response( $tax_obj, $request );
|
| 90 |
return rest_ensure_response( $data );
|
|
@@ -102,6 +131,7 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
|
| 102 |
$data = array(
|
| 103 |
'name' => $taxonomy->label,
|
| 104 |
'slug' => $taxonomy->name,
|
|
|
|
| 105 |
'description' => $taxonomy->description,
|
| 106 |
'labels' => $taxonomy->labels,
|
| 107 |
'types' => $taxonomy->object_type,
|
|
@@ -119,7 +149,7 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
|
| 119 |
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
|
| 120 |
$response->add_links( array(
|
| 121 |
'collection' => array(
|
| 122 |
-
'href' => rest_url( '
|
| 123 |
),
|
| 124 |
'https://api.w.org/items' => array(
|
| 125 |
'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ),
|
|
@@ -149,43 +179,56 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
|
| 149 |
'title' => 'taxonomy',
|
| 150 |
'type' => 'object',
|
| 151 |
'properties' => array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
'description' => array(
|
| 153 |
-
'description' => __( 'A human-readable description of the
|
| 154 |
'type' => 'string',
|
| 155 |
'context' => array( 'view', 'edit' ),
|
| 156 |
-
|
|
|
|
| 157 |
'hierarchical' => array(
|
| 158 |
-
'description' => __( 'Whether or not the
|
| 159 |
'type' => 'boolean',
|
| 160 |
'context' => array( 'view', 'edit' ),
|
| 161 |
-
|
|
|
|
| 162 |
'labels' => array(
|
| 163 |
-
'description' => __( 'Human-readable labels for the
|
| 164 |
'type' => 'object',
|
| 165 |
'context' => array( 'edit' ),
|
| 166 |
-
|
|
|
|
| 167 |
'name' => array(
|
| 168 |
-
'description' => __( 'The title for the
|
| 169 |
'type' => 'string',
|
| 170 |
-
'context' => array( 'view', 'edit' ),
|
| 171 |
-
|
|
|
|
| 172 |
'slug' => array(
|
| 173 |
-
'description' => __( 'An alphanumeric identifier for the
|
| 174 |
'type' => 'string',
|
| 175 |
-
'context' => array( 'view', 'edit' ),
|
| 176 |
-
|
|
|
|
| 177 |
'show_cloud' => array(
|
| 178 |
'description' => __( 'Whether or not the term cloud should be displayed.' ),
|
| 179 |
'type' => 'boolean',
|
| 180 |
'context' => array( 'edit' ),
|
| 181 |
-
|
|
|
|
| 182 |
'types' => array(
|
| 183 |
-
'description' => __( 'Types associated with
|
| 184 |
'type' => 'array',
|
| 185 |
'context' => array( 'view', 'edit' ),
|
| 186 |
-
|
| 187 |
),
|
| 188 |
-
)
|
|
|
|
| 189 |
return $this->add_additional_fields_schema( $schema );
|
| 190 |
}
|
| 191 |
|
|
@@ -198,8 +241,9 @@ class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
|
| 198 |
$new_params = array();
|
| 199 |
$new_params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
|
| 200 |
$new_params['type'] = array(
|
| 201 |
-
'description' => __( 'Limit results to
|
| 202 |
'type' => 'string',
|
|
|
|
| 203 |
);
|
| 204 |
return $new_params;
|
| 205 |
}
|
| 2 |
|
| 3 |
class WP_REST_Taxonomies_Controller extends WP_REST_Controller {
|
| 4 |
|
| 5 |
+
public function __construct() {
|
| 6 |
+
$this->namespace = 'wp/v2';
|
| 7 |
+
$this->rest_base = 'taxonomies';
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
/**
|
| 11 |
* Register the routes for the objects of the controller.
|
| 12 |
*/
|
| 13 |
public function register_routes() {
|
| 14 |
|
| 15 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
|
| 16 |
array(
|
| 17 |
'methods' => WP_REST_Server::READABLE,
|
| 18 |
'callback' => array( $this, 'get_items' ),
|
| 19 |
+
'permission_callback' => array( $this, 'get_items_permissions_check' ),
|
| 20 |
'args' => $this->get_collection_params(),
|
| 21 |
),
|
| 22 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 23 |
) );
|
| 24 |
|
| 25 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<taxonomy>[\w-]+)', array(
|
| 26 |
array(
|
| 27 |
'methods' => WP_REST_Server::READABLE,
|
| 28 |
'callback' => array( $this, 'get_item' ),
|
| 35 |
) );
|
| 36 |
}
|
| 37 |
|
| 38 |
+
/**
|
| 39 |
+
* Check whether a given request has permission to read taxonomies.
|
| 40 |
+
*
|
| 41 |
+
* @param WP_REST_Request $request Full details about the request.
|
| 42 |
+
* @return WP_Error|boolean
|
| 43 |
+
*/
|
| 44 |
+
public function get_items_permissions_check( $request ) {
|
| 45 |
+
if ( 'edit' === $request['context'] ) {
|
| 46 |
+
if ( ! empty( $request['type'] ) ) {
|
| 47 |
+
$taxonomies = get_object_taxonomies( $request['type'], 'objects' );
|
| 48 |
+
} else {
|
| 49 |
+
$taxonomies = get_taxonomies( '', 'objects' );
|
| 50 |
+
}
|
| 51 |
+
foreach ( $taxonomies as $taxonomy ) {
|
| 52 |
+
if ( ! empty( $taxonomy->show_in_rest ) && current_user_can( $taxonomy->cap->manage_terms ) ) {
|
| 53 |
+
return true;
|
| 54 |
+
}
|
| 55 |
+
}
|
| 56 |
+
return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot view this resource with edit context.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 57 |
+
}
|
| 58 |
+
return true;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
/**
|
| 62 |
* Get all public taxonomies
|
| 63 |
*
|
| 97 |
return false;
|
| 98 |
}
|
| 99 |
if ( 'edit' === $request['context'] && ! current_user_can( $tax_obj->cap->manage_terms ) ) {
|
| 100 |
+
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to manage this resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 101 |
}
|
| 102 |
}
|
| 103 |
|
| 113 |
public function get_item( $request ) {
|
| 114 |
$tax_obj = get_taxonomy( $request['taxonomy'] );
|
| 115 |
if ( empty( $tax_obj ) ) {
|
| 116 |
+
return new WP_Error( 'rest_taxonomy_invalid', __( 'Invalid resource.' ), array( 'status' => 404 ) );
|
| 117 |
}
|
| 118 |
$data = $this->prepare_item_for_response( $tax_obj, $request );
|
| 119 |
return rest_ensure_response( $data );
|
| 131 |
$data = array(
|
| 132 |
'name' => $taxonomy->label,
|
| 133 |
'slug' => $taxonomy->name,
|
| 134 |
+
'capabilities' => $taxonomy->cap,
|
| 135 |
'description' => $taxonomy->description,
|
| 136 |
'labels' => $taxonomy->labels,
|
| 137 |
'types' => $taxonomy->object_type,
|
| 149 |
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
|
| 150 |
$response->add_links( array(
|
| 151 |
'collection' => array(
|
| 152 |
+
'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
|
| 153 |
),
|
| 154 |
'https://api.w.org/items' => array(
|
| 155 |
'href' => rest_url( sprintf( 'wp/v2/%s', $base ) ),
|
| 179 |
'title' => 'taxonomy',
|
| 180 |
'type' => 'object',
|
| 181 |
'properties' => array(
|
| 182 |
+
'capabilities' => array(
|
| 183 |
+
'description' => __( 'All capabilities used by the resource.' ),
|
| 184 |
+
'type' => 'array',
|
| 185 |
+
'context' => array( 'edit' ),
|
| 186 |
+
'readonly' => true,
|
| 187 |
+
),
|
| 188 |
'description' => array(
|
| 189 |
+
'description' => __( 'A human-readable description of the resource.' ),
|
| 190 |
'type' => 'string',
|
| 191 |
'context' => array( 'view', 'edit' ),
|
| 192 |
+
'readonly' => true,
|
| 193 |
+
),
|
| 194 |
'hierarchical' => array(
|
| 195 |
+
'description' => __( 'Whether or not the resource should have children.' ),
|
| 196 |
'type' => 'boolean',
|
| 197 |
'context' => array( 'view', 'edit' ),
|
| 198 |
+
'readonly' => true,
|
| 199 |
+
),
|
| 200 |
'labels' => array(
|
| 201 |
+
'description' => __( 'Human-readable labels for the resource for various contexts.' ),
|
| 202 |
'type' => 'object',
|
| 203 |
'context' => array( 'edit' ),
|
| 204 |
+
'readonly' => true,
|
| 205 |
+
),
|
| 206 |
'name' => array(
|
| 207 |
+
'description' => __( 'The title for the resource.' ),
|
| 208 |
'type' => 'string',
|
| 209 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 210 |
+
'readonly' => true,
|
| 211 |
+
),
|
| 212 |
'slug' => array(
|
| 213 |
+
'description' => __( 'An alphanumeric identifier for the resource.' ),
|
| 214 |
'type' => 'string',
|
| 215 |
+
'context' => array( 'view', 'edit', 'embed' ),
|
| 216 |
+
'readonly' => true,
|
| 217 |
+
),
|
| 218 |
'show_cloud' => array(
|
| 219 |
'description' => __( 'Whether or not the term cloud should be displayed.' ),
|
| 220 |
'type' => 'boolean',
|
| 221 |
'context' => array( 'edit' ),
|
| 222 |
+
'readonly' => true,
|
| 223 |
+
),
|
| 224 |
'types' => array(
|
| 225 |
+
'description' => __( 'Types associated with resource.' ),
|
| 226 |
'type' => 'array',
|
| 227 |
'context' => array( 'view', 'edit' ),
|
| 228 |
+
'readonly' => true,
|
| 229 |
),
|
| 230 |
+
),
|
| 231 |
+
);
|
| 232 |
return $this->add_additional_fields_schema( $schema );
|
| 233 |
}
|
| 234 |
|
| 241 |
$new_params = array();
|
| 242 |
$new_params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
|
| 243 |
$new_params['type'] = array(
|
| 244 |
+
'description' => __( 'Limit results to resources associated with a specific post type.' ),
|
| 245 |
'type' => 'string',
|
| 246 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 247 |
);
|
| 248 |
return $new_params;
|
| 249 |
}
|
lib/endpoints/class-wp-rest-terms-controller.php
CHANGED
|
@@ -12,6 +12,9 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 12 |
*/
|
| 13 |
public function __construct( $taxonomy ) {
|
| 14 |
$this->taxonomy = $taxonomy;
|
|
|
|
|
|
|
|
|
|
| 15 |
}
|
| 16 |
|
| 17 |
/**
|
|
@@ -19,8 +22,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 19 |
*/
|
| 20 |
public function register_routes() {
|
| 21 |
|
| 22 |
-
|
| 23 |
-
register_rest_route( 'wp/v2', '/' . $base, array(
|
| 24 |
array(
|
| 25 |
'methods' => WP_REST_Server::READABLE,
|
| 26 |
'callback' => array( $this, 'get_items' ),
|
|
@@ -33,10 +35,9 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 33 |
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
| 34 |
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
| 35 |
),
|
| 36 |
-
|
| 37 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 38 |
));
|
| 39 |
-
register_rest_route(
|
| 40 |
array(
|
| 41 |
'methods' => WP_REST_Server::READABLE,
|
| 42 |
'callback' => array( $this, 'get_item' ),
|
|
@@ -62,7 +63,6 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 62 |
),
|
| 63 |
),
|
| 64 |
),
|
| 65 |
-
|
| 66 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 67 |
) );
|
| 68 |
}
|
|
@@ -74,7 +74,14 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 74 |
* @return WP_Error|boolean
|
| 75 |
*/
|
| 76 |
public function get_items_permissions_check( $request ) {
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
}
|
| 79 |
|
| 80 |
/**
|
|
@@ -163,7 +170,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 163 |
$max_pages = ceil( $total_terms / $per_page );
|
| 164 |
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
| 165 |
|
| 166 |
-
$base = add_query_arg( $request->get_query_params(), rest_url( '/
|
| 167 |
if ( $page > 1 ) {
|
| 168 |
$prev_page = $page - 1;
|
| 169 |
if ( $prev_page > $max_pages ) {
|
|
@@ -188,7 +195,14 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 188 |
* @return WP_Error|boolean
|
| 189 |
*/
|
| 190 |
public function get_item_permissions_check( $request ) {
|
| 191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 192 |
}
|
| 193 |
|
| 194 |
/**
|
|
@@ -201,7 +215,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 201 |
|
| 202 |
$term = get_term( (int) $request['id'], $this->taxonomy );
|
| 203 |
if ( ! $term || $term->taxonomy !== $this->taxonomy ) {
|
| 204 |
-
return new WP_Error( 'rest_term_invalid', __( "
|
| 205 |
}
|
| 206 |
if ( is_wp_error( $term ) ) {
|
| 207 |
return $term;
|
|
@@ -226,7 +240,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 226 |
|
| 227 |
$taxonomy_obj = get_taxonomy( $this->taxonomy );
|
| 228 |
if ( ! current_user_can( $taxonomy_obj->cap->manage_terms ) ) {
|
| 229 |
-
return new WP_Error( 'rest_cannot_create', __( 'Sorry, you cannot create new
|
| 230 |
}
|
| 231 |
|
| 232 |
return true;
|
|
@@ -252,13 +266,13 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 252 |
|
| 253 |
if ( isset( $request['parent'] ) ) {
|
| 254 |
if ( ! is_taxonomy_hierarchical( $this->taxonomy ) ) {
|
| 255 |
-
return new WP_Error( 'rest_taxonomy_not_hierarchical', __( 'Can not set
|
| 256 |
}
|
| 257 |
|
| 258 |
$parent = get_term( (int) $request['parent'], $this->taxonomy );
|
| 259 |
|
| 260 |
if ( ! $parent ) {
|
| 261 |
-
return new WP_Error( 'rest_term_invalid', __( "Parent
|
| 262 |
}
|
| 263 |
|
| 264 |
$args['parent'] = $parent->term_id;
|
|
@@ -294,7 +308,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 294 |
$response = $this->prepare_item_for_response( $term, $request );
|
| 295 |
$response = rest_ensure_response( $response );
|
| 296 |
$response->set_status( 201 );
|
| 297 |
-
$response->header( 'Location', rest_url( '/
|
| 298 |
return $response;
|
| 299 |
}
|
| 300 |
|
|
@@ -312,12 +326,12 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 312 |
|
| 313 |
$term = get_term( (int) $request['id'], $this->taxonomy );
|
| 314 |
if ( ! $term ) {
|
| 315 |
-
return new WP_Error( 'rest_term_invalid', __( "
|
| 316 |
}
|
| 317 |
|
| 318 |
$taxonomy_obj = get_taxonomy( $this->taxonomy );
|
| 319 |
if ( ! current_user_can( $taxonomy_obj->cap->edit_terms ) ) {
|
| 320 |
-
return new WP_Error( 'rest_cannot_update', __( 'Sorry, you cannot update
|
| 321 |
}
|
| 322 |
|
| 323 |
return true;
|
|
@@ -344,13 +358,13 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 344 |
|
| 345 |
if ( isset( $request['parent'] ) ) {
|
| 346 |
if ( ! is_taxonomy_hierarchical( $this->taxonomy ) ) {
|
| 347 |
-
return new WP_Error( 'rest_taxonomy_not_hierarchical', __( 'Can not set
|
| 348 |
}
|
| 349 |
|
| 350 |
$parent = get_term( (int) $request['parent'], $this->taxonomy );
|
| 351 |
|
| 352 |
if ( ! $parent ) {
|
| 353 |
-
return new WP_Error( 'rest_term_invalid', __( "Parent
|
| 354 |
}
|
| 355 |
|
| 356 |
$prepared_args['parent'] = $parent->term_id;
|
|
@@ -389,11 +403,11 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 389 |
}
|
| 390 |
$term = get_term( (int) $request['id'], $this->taxonomy );
|
| 391 |
if ( ! $term ) {
|
| 392 |
-
return new WP_Error( 'rest_term_invalid', __( "
|
| 393 |
}
|
| 394 |
$taxonomy_obj = get_taxonomy( $this->taxonomy );
|
| 395 |
if ( ! current_user_can( $taxonomy_obj->cap->delete_terms ) ) {
|
| 396 |
-
return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you cannot delete
|
| 397 |
}
|
| 398 |
return true;
|
| 399 |
}
|
|
@@ -410,53 +424,30 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 410 |
|
| 411 |
// We don't support trashing for this type, error out
|
| 412 |
if ( ! $force ) {
|
| 413 |
-
return new WP_Error( 'rest_trash_not_supported', __( '
|
| 414 |
}
|
| 415 |
|
| 416 |
$term = get_term( (int) $request['id'], $this->taxonomy );
|
| 417 |
$request->set_param( 'context', 'view' );
|
| 418 |
$response = $this->prepare_item_for_response( $term, $request );
|
| 419 |
|
| 420 |
-
$data = $response->get_data();
|
| 421 |
-
$data = array(
|
| 422 |
-
'data' => $data,
|
| 423 |
-
'deleted' => true,
|
| 424 |
-
);
|
| 425 |
-
$response->set_data( $data );
|
| 426 |
-
|
| 427 |
$retval = wp_delete_term( $term->term_id, $term->taxonomy );
|
| 428 |
if ( ! $retval ) {
|
| 429 |
-
return new WP_Error( 'rest_cannot_delete', __( 'The
|
| 430 |
}
|
| 431 |
|
| 432 |
/**
|
| 433 |
* Fires after a single term is deleted via the REST API.
|
| 434 |
*
|
| 435 |
-
* @param WP_Term
|
| 436 |
-
* @param
|
| 437 |
-
* @param WP_REST_Request
|
| 438 |
*/
|
| 439 |
-
do_action( "rest_delete_{$this->taxonomy}", $term, $
|
| 440 |
|
| 441 |
return $response;
|
| 442 |
}
|
| 443 |
|
| 444 |
-
/**
|
| 445 |
-
* Get the base path for a term's taxonomy endpoints.
|
| 446 |
-
*
|
| 447 |
-
* @param object|string $taxonomy
|
| 448 |
-
* @return string $base
|
| 449 |
-
*/
|
| 450 |
-
public function get_taxonomy_base( $taxonomy ) {
|
| 451 |
-
if ( ! is_object( $taxonomy ) ) {
|
| 452 |
-
$taxonomy = get_taxonomy( $taxonomy );
|
| 453 |
-
}
|
| 454 |
-
|
| 455 |
-
$base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
|
| 456 |
-
|
| 457 |
-
return $base;
|
| 458 |
-
}
|
| 459 |
-
|
| 460 |
/**
|
| 461 |
* Prepare a single term output for response
|
| 462 |
*
|
|
@@ -507,7 +498,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 507 |
* @return array Links for the given term.
|
| 508 |
*/
|
| 509 |
protected function prepare_links( $term ) {
|
| 510 |
-
$base = '/
|
| 511 |
$links = array(
|
| 512 |
'self' => array(
|
| 513 |
'href' => rest_url( trailingslashit( $base ) . $term->term_id ),
|
|
@@ -524,12 +515,32 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 524 |
$parent_term = get_term( (int) $term->parent, $term->taxonomy );
|
| 525 |
if ( $parent_term ) {
|
| 526 |
$links['up'] = array(
|
| 527 |
-
'href' => rest_url(
|
| 528 |
'embeddable' => true,
|
| 529 |
);
|
| 530 |
}
|
| 531 |
}
|
| 532 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 533 |
return $links;
|
| 534 |
}
|
| 535 |
|
|
@@ -545,54 +556,54 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 545 |
'type' => 'object',
|
| 546 |
'properties' => array(
|
| 547 |
'id' => array(
|
| 548 |
-
'description' => __( 'Unique identifier for the
|
| 549 |
'type' => 'integer',
|
| 550 |
-
'context' => array( 'view', 'embed' ),
|
| 551 |
'readonly' => true,
|
| 552 |
),
|
| 553 |
'count' => array(
|
| 554 |
-
'description' => __( 'Number of published posts for the
|
| 555 |
'type' => 'integer',
|
| 556 |
-
'context' => array( 'view' ),
|
| 557 |
'readonly' => true,
|
| 558 |
),
|
| 559 |
'description' => array(
|
| 560 |
-
'description' => __( '
|
| 561 |
'type' => 'string',
|
| 562 |
-
'context' => array( 'view' ),
|
| 563 |
'arg_options' => array(
|
| 564 |
'sanitize_callback' => 'wp_filter_post_kses',
|
| 565 |
),
|
| 566 |
),
|
| 567 |
'link' => array(
|
| 568 |
-
'description' => __( 'URL to the
|
| 569 |
'type' => 'string',
|
| 570 |
'format' => 'uri',
|
| 571 |
-
'context' => array( 'view', 'embed' ),
|
| 572 |
'readonly' => true,
|
| 573 |
),
|
| 574 |
'name' => array(
|
| 575 |
-
'description' => __( '
|
| 576 |
'type' => 'string',
|
| 577 |
-
'context' => array( 'view', 'embed' ),
|
| 578 |
'arg_options' => array(
|
| 579 |
'sanitize_callback' => 'sanitize_text_field',
|
| 580 |
),
|
| 581 |
'required' => true,
|
| 582 |
),
|
| 583 |
'slug' => array(
|
| 584 |
-
'description' => __( 'An alphanumeric identifier for the
|
| 585 |
'type' => 'string',
|
| 586 |
-
'context' => array( 'view', 'embed' ),
|
| 587 |
'arg_options' => array(
|
| 588 |
'sanitize_callback' => 'sanitize_title',
|
| 589 |
),
|
| 590 |
),
|
| 591 |
'taxonomy' => array(
|
| 592 |
-
'description' => __( 'Type attribution for the
|
| 593 |
'type' => 'string',
|
| 594 |
'enum' => array_keys( get_taxonomies() ),
|
| 595 |
-
'context' => array( 'view', 'embed' ),
|
| 596 |
'readonly' => true,
|
| 597 |
),
|
| 598 |
),
|
|
@@ -600,10 +611,10 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 600 |
$taxonomy = get_taxonomy( $this->taxonomy );
|
| 601 |
if ( $taxonomy->hierarchical ) {
|
| 602 |
$schema['properties']['parent'] = array(
|
| 603 |
-
|
| 604 |
-
|
| 605 |
-
|
| 606 |
-
|
| 607 |
}
|
| 608 |
return $this->add_additional_fields_schema( $schema );
|
| 609 |
}
|
|
@@ -636,6 +647,7 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 636 |
'description' => __( 'Offset the result set by a specific number of items.' ),
|
| 637 |
'type' => 'integer',
|
| 638 |
'sanitize_callback' => 'absint',
|
|
|
|
| 639 |
);
|
| 640 |
}
|
| 641 |
$query_params['order'] = array(
|
|
@@ -647,9 +659,10 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 647 |
'asc',
|
| 648 |
'desc',
|
| 649 |
),
|
|
|
|
| 650 |
);
|
| 651 |
$query_params['orderby'] = array(
|
| 652 |
-
'description' => __( 'Sort collection by
|
| 653 |
'type' => 'string',
|
| 654 |
'sanitize_callback' => 'sanitize_key',
|
| 655 |
'default' => 'name',
|
|
@@ -662,27 +675,32 @@ class WP_REST_Terms_Controller extends WP_REST_Controller {
|
|
| 662 |
'description',
|
| 663 |
'count',
|
| 664 |
),
|
|
|
|
| 665 |
);
|
| 666 |
$query_params['hide_empty'] = array(
|
| 667 |
-
'description' => __( 'Whether to hide
|
| 668 |
'type' => 'boolean',
|
| 669 |
'default' => false,
|
|
|
|
| 670 |
);
|
| 671 |
if ( $taxonomy->hierarchical ) {
|
| 672 |
$query_params['parent'] = array(
|
| 673 |
-
'description' => __( 'Limit result set to
|
| 674 |
'type' => 'integer',
|
| 675 |
'sanitize_callback' => 'absint',
|
|
|
|
| 676 |
);
|
| 677 |
}
|
| 678 |
$query_params['post'] = array(
|
| 679 |
-
'description' => __( 'Limit result set to
|
| 680 |
-
'type' => '
|
| 681 |
-
'default' =>
|
|
|
|
| 682 |
);
|
| 683 |
$query_params['slug'] = array(
|
| 684 |
-
'description' => __( 'Limit result set to
|
| 685 |
'type' => 'string',
|
|
|
|
| 686 |
);
|
| 687 |
return $query_params;
|
| 688 |
}
|
| 12 |
*/
|
| 13 |
public function __construct( $taxonomy ) {
|
| 14 |
$this->taxonomy = $taxonomy;
|
| 15 |
+
$this->namespace = 'wp/v2';
|
| 16 |
+
$tax_obj = get_taxonomy( $taxonomy );
|
| 17 |
+
$this->rest_base = ! empty( $tax_obj->rest_base ) ? $tax_obj->rest_base : $tax_obj->name;
|
| 18 |
}
|
| 19 |
|
| 20 |
/**
|
| 22 |
*/
|
| 23 |
public function register_routes() {
|
| 24 |
|
| 25 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
|
|
|
|
| 26 |
array(
|
| 27 |
'methods' => WP_REST_Server::READABLE,
|
| 28 |
'callback' => array( $this, 'get_items' ),
|
| 35 |
'permission_callback' => array( $this, 'create_item_permissions_check' ),
|
| 36 |
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
| 37 |
),
|
|
|
|
| 38 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 39 |
));
|
| 40 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
|
| 41 |
array(
|
| 42 |
'methods' => WP_REST_Server::READABLE,
|
| 43 |
'callback' => array( $this, 'get_item' ),
|
| 63 |
),
|
| 64 |
),
|
| 65 |
),
|
|
|
|
| 66 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 67 |
) );
|
| 68 |
}
|
| 74 |
* @return WP_Error|boolean
|
| 75 |
*/
|
| 76 |
public function get_items_permissions_check( $request ) {
|
| 77 |
+
$tax_obj = get_taxonomy( $this->taxonomy );
|
| 78 |
+
if ( ! $tax_obj || ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
|
| 79 |
+
return false;
|
| 80 |
+
}
|
| 81 |
+
if ( 'edit' === $request['context'] && ! current_user_can( $tax_obj->cap->edit_terms ) ) {
|
| 82 |
+
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you cannot view this resource with edit context.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 83 |
+
}
|
| 84 |
+
return true;
|
| 85 |
}
|
| 86 |
|
| 87 |
/**
|
| 170 |
$max_pages = ceil( $total_terms / $per_page );
|
| 171 |
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
| 172 |
|
| 173 |
+
$base = add_query_arg( $request->get_query_params(), rest_url( '/' . $this->namespace . '/' . $this->rest_base ) );
|
| 174 |
if ( $page > 1 ) {
|
| 175 |
$prev_page = $page - 1;
|
| 176 |
if ( $prev_page > $max_pages ) {
|
| 195 |
* @return WP_Error|boolean
|
| 196 |
*/
|
| 197 |
public function get_item_permissions_check( $request ) {
|
| 198 |
+
$tax_obj = get_taxonomy( $this->taxonomy );
|
| 199 |
+
if ( ! $tax_obj || ! $this->check_is_taxonomy_allowed( $this->taxonomy ) ) {
|
| 200 |
+
return false;
|
| 201 |
+
}
|
| 202 |
+
if ( 'edit' === $request['context'] && ! current_user_can( $tax_obj->cap->edit_terms ) ) {
|
| 203 |
+
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you cannot view this resource with edit context.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 204 |
+
}
|
| 205 |
+
return true;
|
| 206 |
}
|
| 207 |
|
| 208 |
/**
|
| 215 |
|
| 216 |
$term = get_term( (int) $request['id'], $this->taxonomy );
|
| 217 |
if ( ! $term || $term->taxonomy !== $this->taxonomy ) {
|
| 218 |
+
return new WP_Error( 'rest_term_invalid', __( "Resource doesn't exist." ), array( 'status' => 404 ) );
|
| 219 |
}
|
| 220 |
if ( is_wp_error( $term ) ) {
|
| 221 |
return $term;
|
| 240 |
|
| 241 |
$taxonomy_obj = get_taxonomy( $this->taxonomy );
|
| 242 |
if ( ! current_user_can( $taxonomy_obj->cap->manage_terms ) ) {
|
| 243 |
+
return new WP_Error( 'rest_cannot_create', __( 'Sorry, you cannot create new resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 244 |
}
|
| 245 |
|
| 246 |
return true;
|
| 266 |
|
| 267 |
if ( isset( $request['parent'] ) ) {
|
| 268 |
if ( ! is_taxonomy_hierarchical( $this->taxonomy ) ) {
|
| 269 |
+
return new WP_Error( 'rest_taxonomy_not_hierarchical', __( 'Can not set resource parent, taxonomy is not hierarchical.' ), array( 'status' => 400 ) );
|
| 270 |
}
|
| 271 |
|
| 272 |
$parent = get_term( (int) $request['parent'], $this->taxonomy );
|
| 273 |
|
| 274 |
if ( ! $parent ) {
|
| 275 |
+
return new WP_Error( 'rest_term_invalid', __( "Parent resource doesn't exist." ), array( 'status' => 404 ) );
|
| 276 |
}
|
| 277 |
|
| 278 |
$args['parent'] = $parent->term_id;
|
| 308 |
$response = $this->prepare_item_for_response( $term, $request );
|
| 309 |
$response = rest_ensure_response( $response );
|
| 310 |
$response->set_status( 201 );
|
| 311 |
+
$response->header( 'Location', rest_url( '/' . $this->namespace . '/' . $this->rest_base . '/' . $term->term_id ) );
|
| 312 |
return $response;
|
| 313 |
}
|
| 314 |
|
| 326 |
|
| 327 |
$term = get_term( (int) $request['id'], $this->taxonomy );
|
| 328 |
if ( ! $term ) {
|
| 329 |
+
return new WP_Error( 'rest_term_invalid', __( "Resource doesn't exist." ), array( 'status' => 404 ) );
|
| 330 |
}
|
| 331 |
|
| 332 |
$taxonomy_obj = get_taxonomy( $this->taxonomy );
|
| 333 |
if ( ! current_user_can( $taxonomy_obj->cap->edit_terms ) ) {
|
| 334 |
+
return new WP_Error( 'rest_cannot_update', __( 'Sorry, you cannot update resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 335 |
}
|
| 336 |
|
| 337 |
return true;
|
| 358 |
|
| 359 |
if ( isset( $request['parent'] ) ) {
|
| 360 |
if ( ! is_taxonomy_hierarchical( $this->taxonomy ) ) {
|
| 361 |
+
return new WP_Error( 'rest_taxonomy_not_hierarchical', __( 'Can not set resource parent, taxonomy is not hierarchical.' ), array( 'status' => 400 ) );
|
| 362 |
}
|
| 363 |
|
| 364 |
$parent = get_term( (int) $request['parent'], $this->taxonomy );
|
| 365 |
|
| 366 |
if ( ! $parent ) {
|
| 367 |
+
return new WP_Error( 'rest_term_invalid', __( "Parent resource doesn't exist." ), array( 'status' => 400 ) );
|
| 368 |
}
|
| 369 |
|
| 370 |
$prepared_args['parent'] = $parent->term_id;
|
| 403 |
}
|
| 404 |
$term = get_term( (int) $request['id'], $this->taxonomy );
|
| 405 |
if ( ! $term ) {
|
| 406 |
+
return new WP_Error( 'rest_term_invalid', __( "Resource doesn't exist." ), array( 'status' => 404 ) );
|
| 407 |
}
|
| 408 |
$taxonomy_obj = get_taxonomy( $this->taxonomy );
|
| 409 |
if ( ! current_user_can( $taxonomy_obj->cap->delete_terms ) ) {
|
| 410 |
+
return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you cannot delete resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 411 |
}
|
| 412 |
return true;
|
| 413 |
}
|
| 424 |
|
| 425 |
// We don't support trashing for this type, error out
|
| 426 |
if ( ! $force ) {
|
| 427 |
+
return new WP_Error( 'rest_trash_not_supported', __( 'Resource does not support trashing.' ), array( 'status' => 501 ) );
|
| 428 |
}
|
| 429 |
|
| 430 |
$term = get_term( (int) $request['id'], $this->taxonomy );
|
| 431 |
$request->set_param( 'context', 'view' );
|
| 432 |
$response = $this->prepare_item_for_response( $term, $request );
|
| 433 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 434 |
$retval = wp_delete_term( $term->term_id, $term->taxonomy );
|
| 435 |
if ( ! $retval ) {
|
| 436 |
+
return new WP_Error( 'rest_cannot_delete', __( 'The resource cannot be deleted.' ), array( 'status' => 500 ) );
|
| 437 |
}
|
| 438 |
|
| 439 |
/**
|
| 440 |
* Fires after a single term is deleted via the REST API.
|
| 441 |
*
|
| 442 |
+
* @param WP_Term $term The deleted term.
|
| 443 |
+
* @param WP_REST_Response $response The response data.
|
| 444 |
+
* @param WP_REST_Request $request The request sent to the API.
|
| 445 |
*/
|
| 446 |
+
do_action( "rest_delete_{$this->taxonomy}", $term, $response, $request );
|
| 447 |
|
| 448 |
return $response;
|
| 449 |
}
|
| 450 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 451 |
/**
|
| 452 |
* Prepare a single term output for response
|
| 453 |
*
|
| 498 |
* @return array Links for the given term.
|
| 499 |
*/
|
| 500 |
protected function prepare_links( $term ) {
|
| 501 |
+
$base = '/' . $this->namespace . '/' . $this->rest_base;
|
| 502 |
$links = array(
|
| 503 |
'self' => array(
|
| 504 |
'href' => rest_url( trailingslashit( $base ) . $term->term_id ),
|
| 515 |
$parent_term = get_term( (int) $term->parent, $term->taxonomy );
|
| 516 |
if ( $parent_term ) {
|
| 517 |
$links['up'] = array(
|
| 518 |
+
'href' => rest_url( trailingslashit( $base ) . $parent_term->term_id ),
|
| 519 |
'embeddable' => true,
|
| 520 |
);
|
| 521 |
}
|
| 522 |
}
|
| 523 |
|
| 524 |
+
$taxonomy_obj = get_taxonomy( $term->taxonomy );
|
| 525 |
+
if ( empty( $taxonomy_obj->object_type ) ) {
|
| 526 |
+
return $links;
|
| 527 |
+
}
|
| 528 |
+
|
| 529 |
+
$post_type_links = array();
|
| 530 |
+
foreach ( $taxonomy_obj->object_type as $type ) {
|
| 531 |
+
$post_type_object = get_post_type_object( $type );
|
| 532 |
+
if ( empty( $post_type_object->show_in_rest ) ) {
|
| 533 |
+
continue;
|
| 534 |
+
}
|
| 535 |
+
$rest_base = ! empty( $post_type_object->rest_base ) ? $post_type_object->rest_base : $post_type_object->name;
|
| 536 |
+
$post_type_links[] = array(
|
| 537 |
+
'href' => add_query_arg( $this->rest_base, $term->term_id, rest_url( sprintf( 'wp/v2/%s', $rest_base ) ) ),
|
| 538 |
+
);
|
| 539 |
+
}
|
| 540 |
+
if ( ! empty( $post_type_links ) ) {
|
| 541 |
+
$links['http://api.w.org/v2/post_type'] = $post_type_links;
|
| 542 |
+
}
|
| 543 |
+
|
| 544 |
return $links;
|
| 545 |
}
|
| 546 |
|
| 556 |
'type' => 'object',
|
| 557 |
'properties' => array(
|
| 558 |
'id' => array(
|
| 559 |
+
'description' => __( 'Unique identifier for the resource.' ),
|
| 560 |
'type' => 'integer',
|
| 561 |
+
'context' => array( 'view', 'embed', 'edit' ),
|
| 562 |
'readonly' => true,
|
| 563 |
),
|
| 564 |
'count' => array(
|
| 565 |
+
'description' => __( 'Number of published posts for the resource.' ),
|
| 566 |
'type' => 'integer',
|
| 567 |
+
'context' => array( 'view', 'edit' ),
|
| 568 |
'readonly' => true,
|
| 569 |
),
|
| 570 |
'description' => array(
|
| 571 |
+
'description' => __( 'HTML description of the resource.' ),
|
| 572 |
'type' => 'string',
|
| 573 |
+
'context' => array( 'view', 'edit' ),
|
| 574 |
'arg_options' => array(
|
| 575 |
'sanitize_callback' => 'wp_filter_post_kses',
|
| 576 |
),
|
| 577 |
),
|
| 578 |
'link' => array(
|
| 579 |
+
'description' => __( 'URL to the resource.' ),
|
| 580 |
'type' => 'string',
|
| 581 |
'format' => 'uri',
|
| 582 |
+
'context' => array( 'view', 'embed', 'edit' ),
|
| 583 |
'readonly' => true,
|
| 584 |
),
|
| 585 |
'name' => array(
|
| 586 |
+
'description' => __( 'HTML title for the resource.' ),
|
| 587 |
'type' => 'string',
|
| 588 |
+
'context' => array( 'view', 'embed', 'edit' ),
|
| 589 |
'arg_options' => array(
|
| 590 |
'sanitize_callback' => 'sanitize_text_field',
|
| 591 |
),
|
| 592 |
'required' => true,
|
| 593 |
),
|
| 594 |
'slug' => array(
|
| 595 |
+
'description' => __( 'An alphanumeric identifier for the resource unique to its type.' ),
|
| 596 |
'type' => 'string',
|
| 597 |
+
'context' => array( 'view', 'embed', 'edit' ),
|
| 598 |
'arg_options' => array(
|
| 599 |
'sanitize_callback' => 'sanitize_title',
|
| 600 |
),
|
| 601 |
),
|
| 602 |
'taxonomy' => array(
|
| 603 |
+
'description' => __( 'Type attribution for the resource.' ),
|
| 604 |
'type' => 'string',
|
| 605 |
'enum' => array_keys( get_taxonomies() ),
|
| 606 |
+
'context' => array( 'view', 'embed', 'edit' ),
|
| 607 |
'readonly' => true,
|
| 608 |
),
|
| 609 |
),
|
| 611 |
$taxonomy = get_taxonomy( $this->taxonomy );
|
| 612 |
if ( $taxonomy->hierarchical ) {
|
| 613 |
$schema['properties']['parent'] = array(
|
| 614 |
+
'description' => __( 'The id for the parent of the resource.' ),
|
| 615 |
+
'type' => 'integer',
|
| 616 |
+
'context' => array( 'view', 'edit' ),
|
| 617 |
+
);
|
| 618 |
}
|
| 619 |
return $this->add_additional_fields_schema( $schema );
|
| 620 |
}
|
| 647 |
'description' => __( 'Offset the result set by a specific number of items.' ),
|
| 648 |
'type' => 'integer',
|
| 649 |
'sanitize_callback' => 'absint',
|
| 650 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 651 |
);
|
| 652 |
}
|
| 653 |
$query_params['order'] = array(
|
| 659 |
'asc',
|
| 660 |
'desc',
|
| 661 |
),
|
| 662 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 663 |
);
|
| 664 |
$query_params['orderby'] = array(
|
| 665 |
+
'description' => __( 'Sort collection by resource attribute.' ),
|
| 666 |
'type' => 'string',
|
| 667 |
'sanitize_callback' => 'sanitize_key',
|
| 668 |
'default' => 'name',
|
| 675 |
'description',
|
| 676 |
'count',
|
| 677 |
),
|
| 678 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 679 |
);
|
| 680 |
$query_params['hide_empty'] = array(
|
| 681 |
+
'description' => __( 'Whether to hide resources not assigned to any posts.' ),
|
| 682 |
'type' => 'boolean',
|
| 683 |
'default' => false,
|
| 684 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 685 |
);
|
| 686 |
if ( $taxonomy->hierarchical ) {
|
| 687 |
$query_params['parent'] = array(
|
| 688 |
+
'description' => __( 'Limit result set to resources assigned to a specific parent.' ),
|
| 689 |
'type' => 'integer',
|
| 690 |
'sanitize_callback' => 'absint',
|
| 691 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 692 |
);
|
| 693 |
}
|
| 694 |
$query_params['post'] = array(
|
| 695 |
+
'description' => __( 'Limit result set to resources assigned to a specific post.' ),
|
| 696 |
+
'type' => 'integer',
|
| 697 |
+
'default' => null,
|
| 698 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 699 |
);
|
| 700 |
$query_params['slug'] = array(
|
| 701 |
+
'description' => __( 'Limit result set to resources with a specific slug.' ),
|
| 702 |
'type' => 'string',
|
| 703 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 704 |
);
|
| 705 |
return $query_params;
|
| 706 |
}
|
lib/endpoints/class-wp-rest-users-controller.php
CHANGED
|
@@ -5,12 +5,17 @@
|
|
| 5 |
*/
|
| 6 |
class WP_REST_Users_Controller extends WP_REST_Controller {
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
/**
|
| 9 |
* Register the routes for the objects of the controller.
|
| 10 |
*/
|
| 11 |
public function register_routes() {
|
| 12 |
|
| 13 |
-
register_rest_route(
|
| 14 |
array(
|
| 15 |
'methods' => WP_REST_Server::READABLE,
|
| 16 |
'callback' => array( $this, 'get_items' ),
|
|
@@ -26,16 +31,15 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 26 |
),
|
| 27 |
) ),
|
| 28 |
),
|
| 29 |
-
|
| 30 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 31 |
) );
|
| 32 |
-
register_rest_route( '
|
| 33 |
array(
|
| 34 |
'methods' => WP_REST_Server::READABLE,
|
| 35 |
'callback' => array( $this, 'get_item' ),
|
| 36 |
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
| 37 |
'args' => array(
|
| 38 |
-
'context' => $this->get_context_param( array( 'default' => '
|
| 39 |
),
|
| 40 |
),
|
| 41 |
array(
|
|
@@ -58,11 +62,10 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 58 |
'reassign' => array(),
|
| 59 |
),
|
| 60 |
),
|
| 61 |
-
|
| 62 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 63 |
) );
|
| 64 |
|
| 65 |
-
register_rest_route( '
|
| 66 |
'methods' => WP_REST_Server::READABLE,
|
| 67 |
'callback' => array( $this, 'get_current_item' ),
|
| 68 |
'args' => array(
|
|
@@ -101,9 +104,6 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 101 |
|
| 102 |
if ( ! current_user_can( 'list_users' ) ) {
|
| 103 |
$prepared_args['has_published_posts'] = true;
|
| 104 |
-
|
| 105 |
-
// Only display a public subset of information
|
| 106 |
-
$request['context'] = 'embed';
|
| 107 |
}
|
| 108 |
|
| 109 |
if ( '' !== $prepared_args['search'] ) {
|
|
@@ -153,7 +153,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 153 |
$max_pages = ceil( $total_users / $per_page );
|
| 154 |
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
| 155 |
|
| 156 |
-
$base = add_query_arg( $request->get_query_params(), rest_url( '
|
| 157 |
if ( $page > 1 ) {
|
| 158 |
$prev_page = $page - 1;
|
| 159 |
if ( $prev_page > $max_pages ) {
|
|
@@ -181,23 +181,20 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 181 |
|
| 182 |
$id = (int) $request['id'];
|
| 183 |
$user = get_userdata( $id );
|
|
|
|
| 184 |
|
| 185 |
if ( empty( $id ) || empty( $user->ID ) ) {
|
| 186 |
-
return new WP_Error( 'rest_user_invalid_id', __( 'Invalid
|
| 187 |
}
|
| 188 |
|
| 189 |
if ( get_current_user_id() === $id ) {
|
| 190 |
return true;
|
| 191 |
}
|
| 192 |
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
if (
|
| 196 |
-
return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you cannot view this
|
| 197 |
-
} else if ( 'view' === $context && ! current_user_can( 'list_users' ) ) {
|
| 198 |
-
return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you cannot view this user with view context' ), array( 'status' => rest_authorization_required_code() ) );
|
| 199 |
-
} else if ( 'embed' === $context && ! count_user_posts( $id ) && ! current_user_can( 'edit_user', $id ) && ! current_user_can( 'list_users' ) ) {
|
| 200 |
-
return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you cannot view this user' ), array( 'status' => rest_authorization_required_code() ) );
|
| 201 |
}
|
| 202 |
|
| 203 |
return true;
|
|
@@ -214,7 +211,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 214 |
$user = get_userdata( $id );
|
| 215 |
|
| 216 |
if ( empty( $id ) || empty( $user->ID ) ) {
|
| 217 |
-
return new WP_Error( 'rest_user_invalid_id', __( 'Invalid
|
| 218 |
}
|
| 219 |
|
| 220 |
$user = $this->prepare_item_for_response( $user, $request );
|
|
@@ -238,7 +235,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 238 |
$user = wp_get_current_user();
|
| 239 |
$response = $this->prepare_item_for_response( $user, $request );
|
| 240 |
$response = rest_ensure_response( $response );
|
| 241 |
-
$response->header( 'Location', rest_url( sprintf( '
|
| 242 |
$response->set_status( 302 );
|
| 243 |
|
| 244 |
return $response;
|
|
@@ -253,7 +250,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 253 |
public function create_item_permissions_check( $request ) {
|
| 254 |
|
| 255 |
if ( ! current_user_can( 'create_users' ) ) {
|
| 256 |
-
return new WP_Error( 'rest_cannot_create_user', __( 'Sorry, you are not allowed to create
|
| 257 |
}
|
| 258 |
|
| 259 |
return true;
|
|
@@ -269,7 +266,14 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 269 |
global $wp_roles;
|
| 270 |
|
| 271 |
if ( ! empty( $request['id'] ) ) {
|
| 272 |
-
return new WP_Error( 'rest_user_exists', __( 'Cannot create existing
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
}
|
| 274 |
|
| 275 |
$user = $this->prepare_item_for_database( $request );
|
|
@@ -284,7 +288,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 284 |
if ( is_multisite() ) {
|
| 285 |
$user_id = wpmu_create_user( $user->user_login, $user->user_pass, $user->user_email );
|
| 286 |
if ( ! $user_id ) {
|
| 287 |
-
return new WP_Error( 'rest_user_create', __( 'Error creating new
|
| 288 |
}
|
| 289 |
$user->ID = $user_id;
|
| 290 |
$user_id = wp_update_user( $user );
|
|
@@ -299,6 +303,10 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 299 |
}
|
| 300 |
|
| 301 |
$user = get_user_by( 'id', $user_id );
|
|
|
|
|
|
|
|
|
|
|
|
|
| 302 |
$this->update_additional_fields_for_object( $user, $request );
|
| 303 |
|
| 304 |
/**
|
|
@@ -314,7 +322,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 314 |
$response = $this->prepare_item_for_response( $user, $request );
|
| 315 |
$response = rest_ensure_response( $response );
|
| 316 |
$response->set_status( 201 );
|
| 317 |
-
$response->header( 'Location', rest_url( '
|
| 318 |
|
| 319 |
return $response;
|
| 320 |
}
|
|
@@ -330,11 +338,11 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 330 |
$id = (int) $request['id'];
|
| 331 |
|
| 332 |
if ( ! current_user_can( 'edit_user', $id ) ) {
|
| 333 |
-
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit
|
| 334 |
}
|
| 335 |
|
| 336 |
-
if ( ! empty( $request['
|
| 337 |
-
return new WP_Error( 'rest_cannot_edit_roles', __( 'Sorry, you are not allowed to edit roles of
|
| 338 |
}
|
| 339 |
|
| 340 |
return true;
|
|
@@ -351,7 +359,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 351 |
|
| 352 |
$user = get_userdata( $id );
|
| 353 |
if ( ! $user ) {
|
| 354 |
-
return new WP_Error( 'rest_user_invalid_id', __( '
|
| 355 |
}
|
| 356 |
|
| 357 |
if ( email_exists( $request['email'] ) && $request['email'] !== $user->user_email ) {
|
|
@@ -366,8 +374,8 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 366 |
return new WP_Error( 'rest_user_invalid_slug', __( 'Slug is invalid.' ), array( 'status' => 400 ) );
|
| 367 |
}
|
| 368 |
|
| 369 |
-
if ( ! empty( $request['
|
| 370 |
-
$check_permission = $this->check_role_update( $id, $request['
|
| 371 |
if ( is_wp_error( $check_permission ) ) {
|
| 372 |
return $check_permission;
|
| 373 |
}
|
|
@@ -384,6 +392,10 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 384 |
}
|
| 385 |
|
| 386 |
$user = get_user_by( 'id', $id );
|
|
|
|
|
|
|
|
|
|
|
|
|
| 387 |
$this->update_additional_fields_for_object( $user, $request );
|
| 388 |
|
| 389 |
/* This action is documented in lib/endpoints/class-wp-rest-users-controller.php */
|
|
@@ -406,7 +418,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 406 |
$id = (int) $request['id'];
|
| 407 |
|
| 408 |
if ( ! current_user_can( 'delete_user', $id ) ) {
|
| 409 |
-
return new WP_Error( 'rest_user_cannot_delete', __( 'Sorry, you are not allowed to delete this
|
| 410 |
}
|
| 411 |
|
| 412 |
return true;
|
|
@@ -430,24 +442,17 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 430 |
|
| 431 |
$user = get_userdata( $id );
|
| 432 |
if ( ! $user ) {
|
| 433 |
-
return new WP_Error( 'rest_user_invalid_id', __( 'Invalid
|
| 434 |
}
|
| 435 |
|
| 436 |
if ( ! empty( $reassign ) ) {
|
| 437 |
if ( $reassign === $id || ! get_userdata( $reassign ) ) {
|
| 438 |
-
return new WP_Error( 'rest_user_invalid_reassign', __( 'Invalid
|
| 439 |
}
|
| 440 |
}
|
| 441 |
|
| 442 |
$request->set_param( 'context', 'edit' );
|
| 443 |
-
$
|
| 444 |
-
|
| 445 |
-
$data = $orig_user->get_data();
|
| 446 |
-
$data = array(
|
| 447 |
-
'data' => $data,
|
| 448 |
-
'deleted' => true,
|
| 449 |
-
);
|
| 450 |
-
$orig_user->set_data( $data );
|
| 451 |
|
| 452 |
/** Include admin user functions to get access to wp_delete_user() */
|
| 453 |
require_once ABSPATH . 'wp-admin/includes/user.php';
|
|
@@ -455,18 +460,19 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 455 |
$result = wp_delete_user( $id, $reassign );
|
| 456 |
|
| 457 |
if ( ! $result ) {
|
| 458 |
-
return new WP_Error( 'rest_cannot_delete', __( 'The
|
| 459 |
}
|
| 460 |
|
| 461 |
/**
|
| 462 |
* Fires after a user is deleted via the REST API.
|
| 463 |
*
|
| 464 |
-
* @param WP_User
|
| 465 |
-
* @param
|
|
|
|
| 466 |
*/
|
| 467 |
-
do_action( 'rest_delete_user', $user, $
|
| 468 |
|
| 469 |
-
return $
|
| 470 |
}
|
| 471 |
|
| 472 |
/**
|
|
@@ -487,7 +493,6 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 487 |
'url' => $user->user_url,
|
| 488 |
'description' => $user->description,
|
| 489 |
'link' => get_author_posts_url( $user->ID ),
|
| 490 |
-
'avatar_urls' => rest_get_avatar_urls( $user->user_email ),
|
| 491 |
'nickname' => $user->nickname,
|
| 492 |
'slug' => $user->user_nicename,
|
| 493 |
'registered_date' => date( 'c', strtotime( $user->user_registered ) ),
|
|
@@ -496,6 +501,12 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 496 |
'extra_capabilities' => $user->caps,
|
| 497 |
);
|
| 498 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 499 |
$context = ! empty( $request['context'] ) ? $request['context'] : 'embed';
|
| 500 |
$data = $this->add_additional_fields_to_object( $data, $request );
|
| 501 |
$data = $this->filter_response_by_context( $data, $context );
|
|
@@ -524,10 +535,10 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 524 |
protected function prepare_links( $user ) {
|
| 525 |
$links = array(
|
| 526 |
'self' => array(
|
| 527 |
-
'href' => rest_url( sprintf( '
|
| 528 |
),
|
| 529 |
'collection' => array(
|
| 530 |
-
'href' => rest_url( '
|
| 531 |
),
|
| 532 |
);
|
| 533 |
|
|
@@ -576,13 +587,16 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 576 |
if ( isset( $request['description'] ) ) {
|
| 577 |
$prepared_user->description = $request['description'];
|
| 578 |
}
|
| 579 |
-
|
| 580 |
-
$prepared_user->role = $request['role'];
|
| 581 |
-
}
|
| 582 |
if ( isset( $request['url'] ) ) {
|
| 583 |
$prepared_user->user_url = $request['url'];
|
| 584 |
}
|
| 585 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 586 |
/**
|
| 587 |
* Filter user data before inserting user via the REST API.
|
| 588 |
*
|
|
@@ -593,20 +607,28 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 593 |
}
|
| 594 |
|
| 595 |
/**
|
| 596 |
-
* Determine if the current user is allowed to make the desired
|
| 597 |
*
|
| 598 |
* @param integer $user_id
|
| 599 |
-
* @param
|
| 600 |
* @return WP_Error|boolean
|
| 601 |
*/
|
| 602 |
-
protected function check_role_update( $user_id, $
|
| 603 |
global $wp_roles;
|
| 604 |
|
| 605 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 606 |
|
| 607 |
-
// Don't let anyone with 'edit_users' (admins) edit their own role to something without it.
|
| 608 |
-
// Multisite super admins can freely edit their blog roles -- they possess all caps.
|
| 609 |
-
if ( ( is_multisite() && current_user_can( 'manage_sites' ) ) || get_current_user_id() !== $user_id || $potential_role->has_cap( 'edit_users' ) ) {
|
| 610 |
// The new role must be editable by the logged-in user.
|
| 611 |
|
| 612 |
/** Include admin functions to get access to get_editable_roles() */
|
|
@@ -614,13 +636,12 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 614 |
|
| 615 |
$editable_roles = get_editable_roles();
|
| 616 |
if ( empty( $editable_roles[ $role ] ) ) {
|
| 617 |
-
return new WP_Error( 'rest_user_invalid_role', __( 'You cannot give
|
| 618 |
}
|
| 619 |
-
|
| 620 |
-
return true;
|
| 621 |
}
|
| 622 |
|
| 623 |
-
return
|
|
|
|
| 624 |
}
|
| 625 |
|
| 626 |
/**
|
|
@@ -629,18 +650,6 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 629 |
* @return array
|
| 630 |
*/
|
| 631 |
public function get_item_schema() {
|
| 632 |
-
$avatar_properties = array();
|
| 633 |
-
|
| 634 |
-
$avatar_sizes = rest_get_avatar_sizes();
|
| 635 |
-
foreach ( $avatar_sizes as $size ) {
|
| 636 |
-
$avatar_properties[ $size ] = array(
|
| 637 |
-
'description' => sprintf( __( 'Avatar URL with image size of %d pixels.' ), $size ),
|
| 638 |
-
'type' => 'string',
|
| 639 |
-
'format' => 'uri',
|
| 640 |
-
'context' => array( 'embed', 'view', 'edit' ),
|
| 641 |
-
);
|
| 642 |
-
}
|
| 643 |
-
|
| 644 |
global $wp_roles;
|
| 645 |
|
| 646 |
$schema = array(
|
|
@@ -649,13 +658,13 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 649 |
'type' => 'object',
|
| 650 |
'properties' => array(
|
| 651 |
'id' => array(
|
| 652 |
-
'description' => __( 'Unique identifier for the
|
| 653 |
'type' => 'integer',
|
| 654 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 655 |
'readonly' => true,
|
| 656 |
),
|
| 657 |
'username' => array(
|
| 658 |
-
'description' => __( 'Login name for the
|
| 659 |
'type' => 'string',
|
| 660 |
'context' => array( 'edit' ),
|
| 661 |
'required' => true,
|
|
@@ -664,7 +673,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 664 |
),
|
| 665 |
),
|
| 666 |
'name' => array(
|
| 667 |
-
'description' => __( 'Display name for the
|
| 668 |
'type' => 'string',
|
| 669 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 670 |
'arg_options' => array(
|
|
@@ -672,37 +681,36 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 672 |
),
|
| 673 |
),
|
| 674 |
'first_name' => array(
|
| 675 |
-
'description' => __( 'First name for the
|
| 676 |
'type' => 'string',
|
| 677 |
-
'context' => array( '
|
| 678 |
'arg_options' => array(
|
| 679 |
'sanitize_callback' => 'sanitize_text_field',
|
| 680 |
),
|
| 681 |
),
|
| 682 |
'last_name' => array(
|
| 683 |
-
'description' => __( 'Last name for the
|
| 684 |
'type' => 'string',
|
| 685 |
-
'context' => array( '
|
| 686 |
'arg_options' => array(
|
| 687 |
'sanitize_callback' => 'sanitize_text_field',
|
| 688 |
),
|
| 689 |
),
|
| 690 |
'email' => array(
|
| 691 |
-
'description' => __( 'The email address for the
|
| 692 |
'type' => 'string',
|
| 693 |
'format' => 'email',
|
| 694 |
-
'context' => array( '
|
| 695 |
'required' => true,
|
| 696 |
),
|
| 697 |
'url' => array(
|
| 698 |
-
'description' => __( 'URL of the
|
| 699 |
'type' => 'string',
|
| 700 |
'format' => 'uri',
|
| 701 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 702 |
-
'readonly' => true,
|
| 703 |
),
|
| 704 |
'description' => array(
|
| 705 |
-
'description' => __( 'Description of the
|
| 706 |
'type' => 'string',
|
| 707 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 708 |
'arg_options' => array(
|
|
@@ -710,29 +718,22 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 710 |
),
|
| 711 |
),
|
| 712 |
'link' => array(
|
| 713 |
-
'description' => __( 'Author URL to the
|
| 714 |
'type' => 'string',
|
| 715 |
'format' => 'uri',
|
| 716 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 717 |
'readonly' => true,
|
| 718 |
),
|
| 719 |
-
'avatar_urls' => array(
|
| 720 |
-
'description' => __( 'Avatar URLs for the object.' ),
|
| 721 |
-
'type' => 'object',
|
| 722 |
-
'context' => array( 'embed', 'view', 'edit' ),
|
| 723 |
-
'readonly' => true,
|
| 724 |
-
'properties' => $avatar_properties,
|
| 725 |
-
),
|
| 726 |
'nickname' => array(
|
| 727 |
-
'description' => __( 'The nickname for the
|
| 728 |
'type' => 'string',
|
| 729 |
-
'context' => array( '
|
| 730 |
'arg_options' => array(
|
| 731 |
'sanitize_callback' => 'sanitize_text_field',
|
| 732 |
),
|
| 733 |
),
|
| 734 |
'slug' => array(
|
| 735 |
-
'description' => __( 'An alphanumeric identifier for the
|
| 736 |
'type' => 'string',
|
| 737 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 738 |
'arg_options' => array(
|
|
@@ -740,35 +741,53 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 740 |
),
|
| 741 |
),
|
| 742 |
'registered_date' => array(
|
| 743 |
-
'description' => __( 'Registration date for the
|
| 744 |
'type' => 'date-time',
|
| 745 |
-
'context' => array( '
|
| 746 |
'readonly' => true,
|
| 747 |
),
|
| 748 |
'roles' => array(
|
| 749 |
-
'description' => __( 'Roles assigned to the
|
| 750 |
'type' => 'array',
|
| 751 |
-
'context' => array( '
|
| 752 |
-
'readonly' => true,
|
| 753 |
-
),
|
| 754 |
-
'role' => array(
|
| 755 |
-
'description' => __( 'Role assigned to the user.' ),
|
| 756 |
-
'type' => 'string',
|
| 757 |
-
'enum' => array_keys( $wp_roles->role_objects ),
|
| 758 |
),
|
| 759 |
'capabilities' => array(
|
| 760 |
-
'description' => __( 'All capabilities assigned to the
|
| 761 |
'type' => 'object',
|
| 762 |
-
'context' => array( '
|
| 763 |
),
|
| 764 |
'extra_capabilities' => array(
|
| 765 |
-
'description' => __( 'Any extra capabilities assigned to the
|
| 766 |
'type' => 'object',
|
| 767 |
'context' => array( 'edit' ),
|
| 768 |
'readonly' => true,
|
| 769 |
),
|
| 770 |
),
|
| 771 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 772 |
return $this->add_additional_fields_schema( $schema );
|
| 773 |
}
|
| 774 |
|
|
@@ -782,6 +801,12 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 782 |
|
| 783 |
$query_params['context']['default'] = 'view';
|
| 784 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 785 |
$query_params['include'] = array(
|
| 786 |
'description' => __( 'Limit result set to specific ids.' ),
|
| 787 |
'type' => 'array',
|
|
@@ -792,6 +817,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 792 |
'description' => __( 'Offset the result set by a specific number of items.' ),
|
| 793 |
'type' => 'integer',
|
| 794 |
'sanitize_callback' => 'absint',
|
|
|
|
| 795 |
);
|
| 796 |
$query_params['order'] = array(
|
| 797 |
'default' => 'asc',
|
|
@@ -799,6 +825,7 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 799 |
'enum' => array( 'asc', 'desc' ),
|
| 800 |
'sanitize_callback' => 'sanitize_key',
|
| 801 |
'type' => 'string',
|
|
|
|
| 802 |
);
|
| 803 |
$query_params['orderby'] = array(
|
| 804 |
'default' => 'name',
|
|
@@ -811,10 +838,12 @@ class WP_REST_Users_Controller extends WP_REST_Controller {
|
|
| 811 |
),
|
| 812 |
'sanitize_callback' => 'sanitize_key',
|
| 813 |
'type' => 'string',
|
|
|
|
| 814 |
);
|
| 815 |
$query_params['slug'] = array(
|
| 816 |
-
'description' => __( 'Limit result set to
|
| 817 |
'type' => 'string',
|
|
|
|
| 818 |
);
|
| 819 |
return $query_params;
|
| 820 |
}
|
| 5 |
*/
|
| 6 |
class WP_REST_Users_Controller extends WP_REST_Controller {
|
| 7 |
|
| 8 |
+
public function __construct() {
|
| 9 |
+
$this->namespace = 'wp/v2';
|
| 10 |
+
$this->rest_base = 'users';
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
/**
|
| 14 |
* Register the routes for the objects of the controller.
|
| 15 |
*/
|
| 16 |
public function register_routes() {
|
| 17 |
|
| 18 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
|
| 19 |
array(
|
| 20 |
'methods' => WP_REST_Server::READABLE,
|
| 21 |
'callback' => array( $this, 'get_items' ),
|
| 31 |
),
|
| 32 |
) ),
|
| 33 |
),
|
|
|
|
| 34 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 35 |
) );
|
| 36 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
|
| 37 |
array(
|
| 38 |
'methods' => WP_REST_Server::READABLE,
|
| 39 |
'callback' => array( $this, 'get_item' ),
|
| 40 |
'permission_callback' => array( $this, 'get_item_permissions_check' ),
|
| 41 |
'args' => array(
|
| 42 |
+
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
|
| 43 |
),
|
| 44 |
),
|
| 45 |
array(
|
| 62 |
'reassign' => array(),
|
| 63 |
),
|
| 64 |
),
|
|
|
|
| 65 |
'schema' => array( $this, 'get_public_item_schema' ),
|
| 66 |
) );
|
| 67 |
|
| 68 |
+
register_rest_route( $this->namespace, '/' . $this->rest_base . '/me', array(
|
| 69 |
'methods' => WP_REST_Server::READABLE,
|
| 70 |
'callback' => array( $this, 'get_current_item' ),
|
| 71 |
'args' => array(
|
| 104 |
|
| 105 |
if ( ! current_user_can( 'list_users' ) ) {
|
| 106 |
$prepared_args['has_published_posts'] = true;
|
|
|
|
|
|
|
|
|
|
| 107 |
}
|
| 108 |
|
| 109 |
if ( '' !== $prepared_args['search'] ) {
|
| 153 |
$max_pages = ceil( $total_users / $per_page );
|
| 154 |
$response->header( 'X-WP-TotalPages', (int) $max_pages );
|
| 155 |
|
| 156 |
+
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
|
| 157 |
if ( $page > 1 ) {
|
| 158 |
$prev_page = $page - 1;
|
| 159 |
if ( $prev_page > $max_pages ) {
|
| 181 |
|
| 182 |
$id = (int) $request['id'];
|
| 183 |
$user = get_userdata( $id );
|
| 184 |
+
$types = get_post_types( array( 'public' => true ), 'names' );
|
| 185 |
|
| 186 |
if ( empty( $id ) || empty( $user->ID ) ) {
|
| 187 |
+
return new WP_Error( 'rest_user_invalid_id', __( 'Invalid resource id.' ), array( 'status' => 404 ) );
|
| 188 |
}
|
| 189 |
|
| 190 |
if ( get_current_user_id() === $id ) {
|
| 191 |
return true;
|
| 192 |
}
|
| 193 |
|
| 194 |
+
if ( 'edit' === $request['context'] && ! current_user_can( 'list_users' ) ) {
|
| 195 |
+
return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you cannot view this resource with view context.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 196 |
+
} else if ( ! count_user_posts( $id, $types ) && ! current_user_can( 'edit_user', $id ) && ! current_user_can( 'list_users' ) ) {
|
| 197 |
+
return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you cannot view this resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
}
|
| 199 |
|
| 200 |
return true;
|
| 211 |
$user = get_userdata( $id );
|
| 212 |
|
| 213 |
if ( empty( $id ) || empty( $user->ID ) ) {
|
| 214 |
+
return new WP_Error( 'rest_user_invalid_id', __( 'Invalid resource id.' ), array( 'status' => 404 ) );
|
| 215 |
}
|
| 216 |
|
| 217 |
$user = $this->prepare_item_for_response( $user, $request );
|
| 235 |
$user = wp_get_current_user();
|
| 236 |
$response = $this->prepare_item_for_response( $user, $request );
|
| 237 |
$response = rest_ensure_response( $response );
|
| 238 |
+
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $current_user_id ) ) );
|
| 239 |
$response->set_status( 302 );
|
| 240 |
|
| 241 |
return $response;
|
| 250 |
public function create_item_permissions_check( $request ) {
|
| 251 |
|
| 252 |
if ( ! current_user_can( 'create_users' ) ) {
|
| 253 |
+
return new WP_Error( 'rest_cannot_create_user', __( 'Sorry, you are not allowed to create resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 254 |
}
|
| 255 |
|
| 256 |
return true;
|
| 266 |
global $wp_roles;
|
| 267 |
|
| 268 |
if ( ! empty( $request['id'] ) ) {
|
| 269 |
+
return new WP_Error( 'rest_user_exists', __( 'Cannot create existing resource.' ), array( 'status' => 400 ) );
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
if ( ! empty( $request['roles'] ) ) {
|
| 273 |
+
$check_permission = $this->check_role_update( $request['id'], $request['roles'] );
|
| 274 |
+
if ( is_wp_error( $check_permission ) ) {
|
| 275 |
+
return $check_permission;
|
| 276 |
+
}
|
| 277 |
}
|
| 278 |
|
| 279 |
$user = $this->prepare_item_for_database( $request );
|
| 288 |
if ( is_multisite() ) {
|
| 289 |
$user_id = wpmu_create_user( $user->user_login, $user->user_pass, $user->user_email );
|
| 290 |
if ( ! $user_id ) {
|
| 291 |
+
return new WP_Error( 'rest_user_create', __( 'Error creating new resource.' ), array( 'status' => 500 ) );
|
| 292 |
}
|
| 293 |
$user->ID = $user_id;
|
| 294 |
$user_id = wp_update_user( $user );
|
| 303 |
}
|
| 304 |
|
| 305 |
$user = get_user_by( 'id', $user_id );
|
| 306 |
+
if ( ! empty( $request['roles'] ) ) {
|
| 307 |
+
array_map( array( $user, 'add_role' ), $request['roles'] );
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
$this->update_additional_fields_for_object( $user, $request );
|
| 311 |
|
| 312 |
/**
|
| 322 |
$response = $this->prepare_item_for_response( $user, $request );
|
| 323 |
$response = rest_ensure_response( $response );
|
| 324 |
$response->set_status( 201 );
|
| 325 |
+
$response->header( 'Location', rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $user_id ) ) );
|
| 326 |
|
| 327 |
return $response;
|
| 328 |
}
|
| 338 |
$id = (int) $request['id'];
|
| 339 |
|
| 340 |
if ( ! current_user_can( 'edit_user', $id ) ) {
|
| 341 |
+
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 342 |
}
|
| 343 |
|
| 344 |
+
if ( ! empty( $request['roles'] ) && ! current_user_can( 'edit_users' ) ) {
|
| 345 |
+
return new WP_Error( 'rest_cannot_edit_roles', __( 'Sorry, you are not allowed to edit roles of this resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 346 |
}
|
| 347 |
|
| 348 |
return true;
|
| 359 |
|
| 360 |
$user = get_userdata( $id );
|
| 361 |
if ( ! $user ) {
|
| 362 |
+
return new WP_Error( 'rest_user_invalid_id', __( 'Invalid resource id.' ), array( 'status' => 400 ) );
|
| 363 |
}
|
| 364 |
|
| 365 |
if ( email_exists( $request['email'] ) && $request['email'] !== $user->user_email ) {
|
| 374 |
return new WP_Error( 'rest_user_invalid_slug', __( 'Slug is invalid.' ), array( 'status' => 400 ) );
|
| 375 |
}
|
| 376 |
|
| 377 |
+
if ( ! empty( $request['roles'] ) ) {
|
| 378 |
+
$check_permission = $this->check_role_update( $id, $request['roles'] );
|
| 379 |
if ( is_wp_error( $check_permission ) ) {
|
| 380 |
return $check_permission;
|
| 381 |
}
|
| 392 |
}
|
| 393 |
|
| 394 |
$user = get_user_by( 'id', $id );
|
| 395 |
+
if ( ! empty( $request['roles'] ) ) {
|
| 396 |
+
array_map( array( $user, 'add_role' ), $request['roles'] );
|
| 397 |
+
}
|
| 398 |
+
|
| 399 |
$this->update_additional_fields_for_object( $user, $request );
|
| 400 |
|
| 401 |
/* This action is documented in lib/endpoints/class-wp-rest-users-controller.php */
|
| 418 |
$id = (int) $request['id'];
|
| 419 |
|
| 420 |
if ( ! current_user_can( 'delete_user', $id ) ) {
|
| 421 |
+
return new WP_Error( 'rest_user_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 422 |
}
|
| 423 |
|
| 424 |
return true;
|
| 442 |
|
| 443 |
$user = get_userdata( $id );
|
| 444 |
if ( ! $user ) {
|
| 445 |
+
return new WP_Error( 'rest_user_invalid_id', __( 'Invalid resource id.' ), array( 'status' => 400 ) );
|
| 446 |
}
|
| 447 |
|
| 448 |
if ( ! empty( $reassign ) ) {
|
| 449 |
if ( $reassign === $id || ! get_userdata( $reassign ) ) {
|
| 450 |
+
return new WP_Error( 'rest_user_invalid_reassign', __( 'Invalid resource id for reassignment.' ), array( 'status' => 400 ) );
|
| 451 |
}
|
| 452 |
}
|
| 453 |
|
| 454 |
$request->set_param( 'context', 'edit' );
|
| 455 |
+
$response = $this->prepare_item_for_response( $user, $request );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 456 |
|
| 457 |
/** Include admin user functions to get access to wp_delete_user() */
|
| 458 |
require_once ABSPATH . 'wp-admin/includes/user.php';
|
| 460 |
$result = wp_delete_user( $id, $reassign );
|
| 461 |
|
| 462 |
if ( ! $result ) {
|
| 463 |
+
return new WP_Error( 'rest_cannot_delete', __( 'The resource cannot be deleted.' ), array( 'status' => 500 ) );
|
| 464 |
}
|
| 465 |
|
| 466 |
/**
|
| 467 |
* Fires after a user is deleted via the REST API.
|
| 468 |
*
|
| 469 |
+
* @param WP_User $user The user data.
|
| 470 |
+
* @param WP_REST_Response $response The response returned from the API.
|
| 471 |
+
* @param WP_REST_Request $request The request sent to the API.
|
| 472 |
*/
|
| 473 |
+
do_action( 'rest_delete_user', $user, $response, $request );
|
| 474 |
|
| 475 |
+
return $response;
|
| 476 |
}
|
| 477 |
|
| 478 |
/**
|
| 493 |
'url' => $user->user_url,
|
| 494 |
'description' => $user->description,
|
| 495 |
'link' => get_author_posts_url( $user->ID ),
|
|
|
|
| 496 |
'nickname' => $user->nickname,
|
| 497 |
'slug' => $user->user_nicename,
|
| 498 |
'registered_date' => date( 'c', strtotime( $user->user_registered ) ),
|
| 501 |
'extra_capabilities' => $user->caps,
|
| 502 |
);
|
| 503 |
|
| 504 |
+
$schema = $this->get_item_schema();
|
| 505 |
+
|
| 506 |
+
if ( ! empty( $schema['properties']['avatar_urls'] ) ) {
|
| 507 |
+
$data['avatar_urls'] = rest_get_avatar_urls( $user->user_email );
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
$context = ! empty( $request['context'] ) ? $request['context'] : 'embed';
|
| 511 |
$data = $this->add_additional_fields_to_object( $data, $request );
|
| 512 |
$data = $this->filter_response_by_context( $data, $context );
|
| 535 |
protected function prepare_links( $user ) {
|
| 536 |
$links = array(
|
| 537 |
'self' => array(
|
| 538 |
+
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $user->ID ) ),
|
| 539 |
),
|
| 540 |
'collection' => array(
|
| 541 |
+
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ),
|
| 542 |
),
|
| 543 |
);
|
| 544 |
|
| 587 |
if ( isset( $request['description'] ) ) {
|
| 588 |
$prepared_user->description = $request['description'];
|
| 589 |
}
|
| 590 |
+
|
|
|
|
|
|
|
| 591 |
if ( isset( $request['url'] ) ) {
|
| 592 |
$prepared_user->user_url = $request['url'];
|
| 593 |
}
|
| 594 |
|
| 595 |
+
// setting roles will be handled outside of this function.
|
| 596 |
+
if ( isset( $request['roles'] ) ) {
|
| 597 |
+
$prepared_user->role = false;
|
| 598 |
+
}
|
| 599 |
+
|
| 600 |
/**
|
| 601 |
* Filter user data before inserting user via the REST API.
|
| 602 |
*
|
| 607 |
}
|
| 608 |
|
| 609 |
/**
|
| 610 |
+
* Determine if the current user is allowed to make the desired roles change.
|
| 611 |
*
|
| 612 |
* @param integer $user_id
|
| 613 |
+
* @param array $roles
|
| 614 |
* @return WP_Error|boolean
|
| 615 |
*/
|
| 616 |
+
protected function check_role_update( $user_id, $roles ) {
|
| 617 |
global $wp_roles;
|
| 618 |
|
| 619 |
+
foreach ( $roles as $role ) {
|
| 620 |
+
|
| 621 |
+
if ( ! isset( $wp_roles->role_objects[ $role ] ) ) {
|
| 622 |
+
return new WP_Error( 'rest_user_invalid_role', sprintf( __( 'The role %s does not exist.' ), $role ), array( 'status' => 400 ) );
|
| 623 |
+
}
|
| 624 |
+
|
| 625 |
+
$potential_role = $wp_roles->role_objects[ $role ];
|
| 626 |
+
// Don't let anyone with 'edit_users' (admins) edit their own role to something without it.
|
| 627 |
+
// Multisite super admins can freely edit their blog roles -- they possess all caps.
|
| 628 |
+
if ( ! ( is_multisite() && current_user_can( 'manage_sites' ) ) && get_current_user_id() === $user_id && ! $potential_role->has_cap( 'edit_users' ) ) {
|
| 629 |
+
return new WP_Error( 'rest_user_invalid_role', __( 'You cannot give resource that role.' ), array( 'status' => rest_authorization_required_code() ) );
|
| 630 |
+
}
|
| 631 |
|
|
|
|
|
|
|
|
|
|
| 632 |
// The new role must be editable by the logged-in user.
|
| 633 |
|
| 634 |
/** Include admin functions to get access to get_editable_roles() */
|
| 636 |
|
| 637 |
$editable_roles = get_editable_roles();
|
| 638 |
if ( empty( $editable_roles[ $role ] ) ) {
|
| 639 |
+
return new WP_Error( 'rest_user_invalid_role', __( 'You cannot give resource that role.' ), array( 'status' => 403 ) );
|
| 640 |
}
|
|
|
|
|
|
|
| 641 |
}
|
| 642 |
|
| 643 |
+
return true;
|
| 644 |
+
|
| 645 |
}
|
| 646 |
|
| 647 |
/**
|
| 650 |
* @return array
|
| 651 |
*/
|
| 652 |
public function get_item_schema() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 653 |
global $wp_roles;
|
| 654 |
|
| 655 |
$schema = array(
|
| 658 |
'type' => 'object',
|
| 659 |
'properties' => array(
|
| 660 |
'id' => array(
|
| 661 |
+
'description' => __( 'Unique identifier for the resource.' ),
|
| 662 |
'type' => 'integer',
|
| 663 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 664 |
'readonly' => true,
|
| 665 |
),
|
| 666 |
'username' => array(
|
| 667 |
+
'description' => __( 'Login name for the resource.' ),
|
| 668 |
'type' => 'string',
|
| 669 |
'context' => array( 'edit' ),
|
| 670 |
'required' => true,
|
| 673 |
),
|
| 674 |
),
|
| 675 |
'name' => array(
|
| 676 |
+
'description' => __( 'Display name for the resource.' ),
|
| 677 |
'type' => 'string',
|
| 678 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 679 |
'arg_options' => array(
|
| 681 |
),
|
| 682 |
),
|
| 683 |
'first_name' => array(
|
| 684 |
+
'description' => __( 'First name for the resource.' ),
|
| 685 |
'type' => 'string',
|
| 686 |
+
'context' => array( 'edit' ),
|
| 687 |
'arg_options' => array(
|
| 688 |
'sanitize_callback' => 'sanitize_text_field',
|
| 689 |
),
|
| 690 |
),
|
| 691 |
'last_name' => array(
|
| 692 |
+
'description' => __( 'Last name for the resource.' ),
|
| 693 |
'type' => 'string',
|
| 694 |
+
'context' => array( 'edit' ),
|
| 695 |
'arg_options' => array(
|
| 696 |
'sanitize_callback' => 'sanitize_text_field',
|
| 697 |
),
|
| 698 |
),
|
| 699 |
'email' => array(
|
| 700 |
+
'description' => __( 'The email address for the resource.' ),
|
| 701 |
'type' => 'string',
|
| 702 |
'format' => 'email',
|
| 703 |
+
'context' => array( 'edit' ),
|
| 704 |
'required' => true,
|
| 705 |
),
|
| 706 |
'url' => array(
|
| 707 |
+
'description' => __( 'URL of the resource.' ),
|
| 708 |
'type' => 'string',
|
| 709 |
'format' => 'uri',
|
| 710 |
'context' => array( 'embed', 'view', 'edit' ),
|
|
|
|
| 711 |
),
|
| 712 |
'description' => array(
|
| 713 |
+
'description' => __( 'Description of the resource.' ),
|
| 714 |
'type' => 'string',
|
| 715 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 716 |
'arg_options' => array(
|
| 718 |
),
|
| 719 |
),
|
| 720 |
'link' => array(
|
| 721 |
+
'description' => __( 'Author URL to the resource.' ),
|
| 722 |
'type' => 'string',
|
| 723 |
'format' => 'uri',
|
| 724 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 725 |
'readonly' => true,
|
| 726 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 727 |
'nickname' => array(
|
| 728 |
+
'description' => __( 'The nickname for the resource.' ),
|
| 729 |
'type' => 'string',
|
| 730 |
+
'context' => array( 'edit' ),
|
| 731 |
'arg_options' => array(
|
| 732 |
'sanitize_callback' => 'sanitize_text_field',
|
| 733 |
),
|
| 734 |
),
|
| 735 |
'slug' => array(
|
| 736 |
+
'description' => __( 'An alphanumeric identifier for the resource.' ),
|
| 737 |
'type' => 'string',
|
| 738 |
'context' => array( 'embed', 'view', 'edit' ),
|
| 739 |
'arg_options' => array(
|
| 741 |
),
|
| 742 |
),
|
| 743 |
'registered_date' => array(
|
| 744 |
+
'description' => __( 'Registration date for the resource.' ),
|
| 745 |
'type' => 'date-time',
|
| 746 |
+
'context' => array( 'edit' ),
|
| 747 |
'readonly' => true,
|
| 748 |
),
|
| 749 |
'roles' => array(
|
| 750 |
+
'description' => __( 'Roles assigned to the resource.' ),
|
| 751 |
'type' => 'array',
|
| 752 |
+
'context' => array( 'edit' ),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 753 |
),
|
| 754 |
'capabilities' => array(
|
| 755 |
+
'description' => __( 'All capabilities assigned to the resource.' ),
|
| 756 |
'type' => 'object',
|
| 757 |
+
'context' => array( 'edit' ),
|
| 758 |
),
|
| 759 |
'extra_capabilities' => array(
|
| 760 |
+
'description' => __( 'Any extra capabilities assigned to the resource.' ),
|
| 761 |
'type' => 'object',
|
| 762 |
'context' => array( 'edit' ),
|
| 763 |
'readonly' => true,
|
| 764 |
),
|
| 765 |
),
|
| 766 |
);
|
| 767 |
+
|
| 768 |
+
if ( get_option( 'show_avatars' ) ) {
|
| 769 |
+
$avatar_properties = array();
|
| 770 |
+
|
| 771 |
+
$avatar_sizes = rest_get_avatar_sizes();
|
| 772 |
+
foreach ( $avatar_sizes as $size ) {
|
| 773 |
+
$avatar_properties[ $size ] = array(
|
| 774 |
+
'description' => sprintf( __( 'Avatar URL with image size of %d pixels.' ), $size ),
|
| 775 |
+
'type' => 'string',
|
| 776 |
+
'format' => 'uri',
|
| 777 |
+
'context' => array( 'embed', 'view', 'edit' ),
|
| 778 |
+
);
|
| 779 |
+
}
|
| 780 |
+
|
| 781 |
+
$schema['properties']['avatar_urls'] = array(
|
| 782 |
+
'description' => __( 'Avatar URLs for the resource.' ),
|
| 783 |
+
'type' => 'object',
|
| 784 |
+
'context' => array( 'embed', 'view', 'edit' ),
|
| 785 |
+
'readonly' => true,
|
| 786 |
+
'properties' => $avatar_properties,
|
| 787 |
+
);
|
| 788 |
+
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
return $this->add_additional_fields_schema( $schema );
|
| 792 |
}
|
| 793 |
|
| 801 |
|
| 802 |
$query_params['context']['default'] = 'view';
|
| 803 |
|
| 804 |
+
$query_params['exclude'] = array(
|
| 805 |
+
'description' => __( 'Ensure result set excludes specific ids.' ),
|
| 806 |
+
'type' => 'array',
|
| 807 |
+
'default' => array(),
|
| 808 |
+
'sanitize_callback' => 'wp_parse_id_list',
|
| 809 |
+
);
|
| 810 |
$query_params['include'] = array(
|
| 811 |
'description' => __( 'Limit result set to specific ids.' ),
|
| 812 |
'type' => 'array',
|
| 817 |
'description' => __( 'Offset the result set by a specific number of items.' ),
|
| 818 |
'type' => 'integer',
|
| 819 |
'sanitize_callback' => 'absint',
|
| 820 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 821 |
);
|
| 822 |
$query_params['order'] = array(
|
| 823 |
'default' => 'asc',
|
| 825 |
'enum' => array( 'asc', 'desc' ),
|
| 826 |
'sanitize_callback' => 'sanitize_key',
|
| 827 |
'type' => 'string',
|
| 828 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 829 |
);
|
| 830 |
$query_params['orderby'] = array(
|
| 831 |
'default' => 'name',
|
| 838 |
),
|
| 839 |
'sanitize_callback' => 'sanitize_key',
|
| 840 |
'type' => 'string',
|
| 841 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 842 |
);
|
| 843 |
$query_params['slug'] = array(
|
| 844 |
+
'description' => __( 'Limit result set to resources with a specific slug.' ),
|
| 845 |
'type' => 'string',
|
| 846 |
+
'validate_callback' => 'rest_validate_request_arg',
|
| 847 |
);
|
| 848 |
return $query_params;
|
| 849 |
}
|
plugin.php
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
<?php
|
| 2 |
/**
|
| 3 |
* Plugin Name: WP REST API
|
| 4 |
-
* Description: JSON-based REST API for WordPress, developed as part of GSoC 2013.
|
| 5 |
* Author: WP REST API Team
|
| 6 |
* Author URI: http://wp-api.org
|
| 7 |
-
* Version: 2.0-
|
| 8 |
* Plugin URI: https://github.com/WP-API/WP-API
|
| 9 |
* License: GPL2+
|
| 10 |
*/
|
|
@@ -79,24 +79,11 @@ if ( ! class_exists( 'WP_REST_Comments_Controller' ) ) {
|
|
| 79 |
require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-comments-controller.php';
|
| 80 |
}
|
| 81 |
|
| 82 |
-
/**
|
| 83 |
-
* WP_REST_Meta_Controller class.
|
| 84 |
-
*/
|
| 85 |
-
if ( ! class_exists( 'WP_REST_Meta_Controller' ) ) {
|
| 86 |
-
require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-meta-controller.php';
|
| 87 |
-
}
|
| 88 |
-
|
| 89 |
-
/**
|
| 90 |
-
* WP_REST_Meta_Posts_Controller class.
|
| 91 |
-
*/
|
| 92 |
-
if ( ! class_exists( 'WP_REST_Meta_Posts_Controller' ) ) {
|
| 93 |
-
require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-meta-posts-controller.php';
|
| 94 |
-
}
|
| 95 |
-
|
| 96 |
/**
|
| 97 |
* REST extras.
|
| 98 |
*/
|
| 99 |
include_once( dirname( __FILE__ ) . '/extras.php' );
|
|
|
|
| 100 |
|
| 101 |
add_filter( 'init', '_add_extra_api_post_type_arguments', 11 );
|
| 102 |
add_action( 'init', '_add_extra_api_taxonomy_arguments', 11 );
|
|
@@ -179,10 +166,6 @@ if ( ! function_exists( 'create_initial_rest_routes' ) ) {
|
|
| 179 |
|
| 180 |
$controller->register_routes();
|
| 181 |
|
| 182 |
-
if ( post_type_supports( $post_type->name, 'custom-fields' ) ) {
|
| 183 |
-
$meta_controller = new WP_REST_Meta_Posts_Controller( $post_type->name );
|
| 184 |
-
$meta_controller->register_routes();
|
| 185 |
-
}
|
| 186 |
if ( post_type_supports( $post_type->name, 'revisions' ) ) {
|
| 187 |
$revisions_controller = new WP_REST_Revisions_Controller( $post_type->name );
|
| 188 |
$revisions_controller->register_routes();
|
|
@@ -288,3 +271,130 @@ if ( ! function_exists( 'register_api_field' ) ) {
|
|
| 288 |
register_rest_field( $object_type, $attributes, $args );
|
| 289 |
}
|
| 290 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
<?php
|
| 2 |
/**
|
| 3 |
* Plugin Name: WP REST API
|
| 4 |
+
* Description: JSON-based REST API for WordPress, originally developed as part of GSoC 2013.
|
| 5 |
* Author: WP REST API Team
|
| 6 |
* Author URI: http://wp-api.org
|
| 7 |
+
* Version: 2.0-beta12
|
| 8 |
* Plugin URI: https://github.com/WP-API/WP-API
|
| 9 |
* License: GPL2+
|
| 10 |
*/
|
| 79 |
require_once dirname( __FILE__ ) . '/lib/endpoints/class-wp-rest-comments-controller.php';
|
| 80 |
}
|
| 81 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
/**
|
| 83 |
* REST extras.
|
| 84 |
*/
|
| 85 |
include_once( dirname( __FILE__ ) . '/extras.php' );
|
| 86 |
+
require_once( dirname( __FILE__ ) . '/core-integration.php' );
|
| 87 |
|
| 88 |
add_filter( 'init', '_add_extra_api_post_type_arguments', 11 );
|
| 89 |
add_action( 'init', '_add_extra_api_taxonomy_arguments', 11 );
|
| 166 |
|
| 167 |
$controller->register_routes();
|
| 168 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
if ( post_type_supports( $post_type->name, 'revisions' ) ) {
|
| 170 |
$revisions_controller = new WP_REST_Revisions_Controller( $post_type->name );
|
| 171 |
$revisions_controller->register_routes();
|
| 271 |
register_rest_field( $object_type, $attributes, $args );
|
| 272 |
}
|
| 273 |
}
|
| 274 |
+
|
| 275 |
+
if ( ! function_exists( 'rest_validate_request_arg' ) ) {
|
| 276 |
+
/**
|
| 277 |
+
* Validate a request argument based on details registered to the route.
|
| 278 |
+
*
|
| 279 |
+
* @param mixed $value
|
| 280 |
+
* @param WP_REST_Request $request
|
| 281 |
+
* @param string $param
|
| 282 |
+
* @return WP_Error|boolean
|
| 283 |
+
*/
|
| 284 |
+
function rest_validate_request_arg( $value, $request, $param ) {
|
| 285 |
+
|
| 286 |
+
$attributes = $request->get_attributes();
|
| 287 |
+
if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) {
|
| 288 |
+
return true;
|
| 289 |
+
}
|
| 290 |
+
$args = $attributes['args'][ $param ];
|
| 291 |
+
|
| 292 |
+
if ( ! empty( $args['enum'] ) ) {
|
| 293 |
+
if ( ! in_array( $value, $args['enum'] ) ) {
|
| 294 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not one of %s' ), $param, implode( ', ', $args['enum'] ) ) );
|
| 295 |
+
}
|
| 296 |
+
}
|
| 297 |
+
|
| 298 |
+
if ( 'integer' === $args['type'] && ! is_numeric( $value ) ) {
|
| 299 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not of type %s' ), $param, 'integer' ) );
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
if ( 'string' === $args['type'] && ! is_string( $value ) ) {
|
| 303 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not of type %s' ), $param, 'string' ) );
|
| 304 |
+
}
|
| 305 |
+
|
| 306 |
+
if ( isset( $args['format'] ) ) {
|
| 307 |
+
switch ( $args['format'] ) {
|
| 308 |
+
case 'date-time' :
|
| 309 |
+
if ( ! rest_parse_date( $value ) ) {
|
| 310 |
+
return new WP_Error( 'rest_invalid_date', __( 'The date you provided is invalid.' ) );
|
| 311 |
+
}
|
| 312 |
+
break;
|
| 313 |
+
|
| 314 |
+
case 'email' :
|
| 315 |
+
if ( ! is_email( $value ) ) {
|
| 316 |
+
return new WP_Error( 'rest_invalid_email', __( 'The email address you provided is invalid.' ) );
|
| 317 |
+
}
|
| 318 |
+
break;
|
| 319 |
+
}
|
| 320 |
+
}
|
| 321 |
+
|
| 322 |
+
if ( in_array( $args['type'], array( 'numeric', 'integer' ) ) && ( isset( $args['minimum'] ) || isset( $args['maximum'] ) ) ) {
|
| 323 |
+
if ( isset( $args['minimum'] ) && ! isset( $args['maximum'] ) ) {
|
| 324 |
+
if ( ! empty( $args['exclusiveMinimum'] ) && $value <= $args['minimum'] ) {
|
| 325 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be greater than %d (exclusive)' ), $param, $args['minimum'] ) );
|
| 326 |
+
} else if ( empty( $args['exclusiveMinimum'] ) && $value < $args['minimum'] ) {
|
| 327 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be greater than %d (inclusive)' ), $param, $args['minimum'] ) );
|
| 328 |
+
}
|
| 329 |
+
} else if ( isset( $args['maximum'] ) && ! isset( $args['minimum'] ) ) {
|
| 330 |
+
if ( ! empty( $args['exclusiveMaximum'] ) && $value >= $args['maximum'] ) {
|
| 331 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be less than %d (exclusive)' ), $param, $args['maximum'] ) );
|
| 332 |
+
} else if ( empty( $args['exclusiveMaximum'] ) && $value > $args['maximum'] ) {
|
| 333 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be less than %d (inclusive)' ), $param, $args['maximum'] ) );
|
| 334 |
+
}
|
| 335 |
+
} else if ( isset( $args['maximum'] ) && isset( $args['minimum'] ) ) {
|
| 336 |
+
if ( ! empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
|
| 337 |
+
if ( $value >= $args['maximum'] || $value <= $args['minimum'] ) {
|
| 338 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be between %d (exclusive) and %d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
|
| 339 |
+
}
|
| 340 |
+
} else if ( empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) {
|
| 341 |
+
if ( $value >= $args['maximum'] || $value < $args['minimum'] ) {
|
| 342 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be between %d (inclusive) and %d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
|
| 343 |
+
}
|
| 344 |
+
} else if ( ! empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
|
| 345 |
+
if ( $value > $args['maximum'] || $value <= $args['minimum'] ) {
|
| 346 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be between %d (exclusive) and %d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
|
| 347 |
+
}
|
| 348 |
+
} else if ( empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) {
|
| 349 |
+
if ( $value > $args['maximum'] || $value < $args['minimum'] ) {
|
| 350 |
+
return new WP_Error( 'rest_invalid_param', sprintf( __( '%s must be between %d (inclusive) and %d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) );
|
| 351 |
+
}
|
| 352 |
+
}
|
| 353 |
+
}
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
return true;
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
if ( ! function_exists( 'rest_sanitize_request_arg' ) ) {
|
| 361 |
+
/**
|
| 362 |
+
* Sanitize a request argument based on details registered to the route.
|
| 363 |
+
*
|
| 364 |
+
* @param mixed $value
|
| 365 |
+
* @param WP_REST_Request $request
|
| 366 |
+
* @param string $param
|
| 367 |
+
* @return mixed
|
| 368 |
+
*/
|
| 369 |
+
function rest_sanitize_request_arg( $value, $request, $param ) {
|
| 370 |
+
|
| 371 |
+
$attributes = $request->get_attributes();
|
| 372 |
+
if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) {
|
| 373 |
+
return $value;
|
| 374 |
+
}
|
| 375 |
+
$args = $attributes['args'][ $param ];
|
| 376 |
+
|
| 377 |
+
if ( 'integer' === $args['type'] ) {
|
| 378 |
+
return (int) $value;
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
+
if ( isset( $args['format'] ) ) {
|
| 382 |
+
switch ( $args['format'] ) {
|
| 383 |
+
case 'date-time' :
|
| 384 |
+
return sanitize_text_field( $value );
|
| 385 |
+
|
| 386 |
+
case 'email' :
|
| 387 |
+
/*
|
| 388 |
+
* sanitize_email() validates, which would be unexpected
|
| 389 |
+
*/
|
| 390 |
+
return sanitize_text_field( $value );
|
| 391 |
+
|
| 392 |
+
case 'uri' :
|
| 393 |
+
return esc_url_raw( $value );
|
| 394 |
+
}
|
| 395 |
+
}
|
| 396 |
+
|
| 397 |
+
return $value;
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
}
|
readme.txt
CHANGED
|
@@ -3,7 +3,7 @@ Contributors: rmccue, rachelbaker, danielbachhuber, joehoyle
|
|
| 3 |
Tags: json, rest, api, rest-api
|
| 4 |
Requires at least: 4.4
|
| 5 |
Tested up to: 4.5-alpha
|
| 6 |
-
Stable tag: 2.0-
|
| 7 |
License: GPLv2 or later
|
| 8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
| 9 |
|
|
@@ -30,13 +30,151 @@ All tickets for the project are being tracked on [GitHub][]. You can also take a
|
|
| 30 |
|
| 31 |
== Installation ==
|
| 32 |
|
| 33 |
-
|
| 34 |
|
| 35 |
For full-flavoured API support, you'll need to be using pretty permalinks to use the plugin, as it uses custom rewrite rules to power the API.
|
| 36 |
|
|
|
|
|
|
|
| 37 |
== Changelog ==
|
| 38 |
|
| 39 |
-
= 2.0 Beta
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
* BREAKING CHANGE: Moves Post->Term relations to the Post Resource
|
| 42 |
|
|
@@ -183,7 +321,7 @@ unnecessary call to `get_item()`.
|
|
| 183 |
|
| 184 |
(props @danielbachhuber, [#1990](https://github.com/WP-API/WP-API/pull/1990))
|
| 185 |
|
| 186 |
-
= 2.0 Beta 10.0 =
|
| 187 |
|
| 188 |
* SECURITY: Ensure media of private posts are private too.
|
| 189 |
|
|
@@ -315,7 +453,7 @@ unnecessary call to `get_item()`.
|
|
| 315 |
|
| 316 |
(props @danielbachhuber, [#1852](https://github.com/WP-API/WP-API/pull/1852))
|
| 317 |
|
| 318 |
-
= 2.0 Beta 9.0 =
|
| 319 |
|
| 320 |
* BREAKING CHANGE: Move tags and categories to top-level endpoints.
|
| 321 |
|
|
@@ -429,7 +567,7 @@ unnecessary call to `get_item()`.
|
|
| 429 |
|
| 430 |
(props @danielbachhuber, [#1833](https://github.com/WP-API/WP-API/pull/1833))
|
| 431 |
|
| 432 |
-
= 2.0 Beta 8.0 =
|
| 433 |
|
| 434 |
* Prevent fatals when uploading attachment by including admin utilities.
|
| 435 |
|
|
@@ -465,7 +603,7 @@ unnecessary call to `get_item()`.
|
|
| 465 |
|
| 466 |
(props @wpsmith, [#1759](https://github.com/WP-API/WP-API/pull/1759))
|
| 467 |
|
| 468 |
-
= 2.0 Beta 7.0 =
|
| 469 |
|
| 470 |
* Sync infrastructure from WordPress core as of r35691.
|
| 471 |
|
|
@@ -496,7 +634,7 @@ unnecessary call to `get_item()`.
|
|
| 496 |
|
| 497 |
(props @danielbachhuber, [#1726](https://github.com/WP-API/WP-API/pull/1726))
|
| 498 |
|
| 499 |
-
= 2.0 Beta 6.0 =
|
| 500 |
|
| 501 |
* Remove global inclusion of wp-admin/includes/admin.php
|
| 502 |
|
|
@@ -592,7 +730,7 @@ unnecessary call to `get_item()`.
|
|
| 592 |
|
| 593 |
(props @rachelbaker, [#1497](https://github.com/WP-API/WP-API/pull/1497))
|
| 594 |
|
| 595 |
-
= 2.0 Beta 5.0 =
|
| 596 |
|
| 597 |
* Load api-core as a compatibility library
|
| 598 |
|
|
@@ -626,7 +764,7 @@ unnecessary call to `get_item()`.
|
|
| 626 |
|
| 627 |
(props @joehoyle)
|
| 628 |
|
| 629 |
-
= 2.0 Beta 4.0 =
|
| 630 |
|
| 631 |
* Show public user information through the user controller.
|
| 632 |
|
|
@@ -859,7 +997,7 @@ unnecessary call to `get_item()`.
|
|
| 859 |
[gh-1467]: https://github.com/WP-API/WP-API/issues/1467
|
| 860 |
[gh-1472]: https://github.com/WP-API/WP-API/issues/1472
|
| 861 |
|
| 862 |
-
= 2.0 Beta 3.0 =
|
| 863 |
|
| 864 |
* Add ability to declare sanitization and default options for schema fields.
|
| 865 |
|
|
@@ -924,7 +1062,7 @@ unnecessary call to `get_item()`.
|
|
| 924 |
[gh-1347]: https://github.com/WP-API/WP-API/issues/1347
|
| 925 |
[gh-1348]: https://github.com/WP-API/WP-API/issues/1348
|
| 926 |
|
| 927 |
-
= 2.0 Beta 2.0 =
|
| 928 |
|
| 929 |
* Load the WP REST API before the main query runs.
|
| 930 |
|
|
@@ -1144,7 +1282,7 @@ unnecessary call to `get_item()`.
|
|
| 1144 |
|
| 1145 |
Reported by @kacperszurek on 2015-05-16.
|
| 1146 |
|
| 1147 |
-
= 2.0 Beta 1 =
|
| 1148 |
|
| 1149 |
Partial rewrite and evolution of the REST API to prepare for core integration.
|
| 1150 |
|
| 3 |
Tags: json, rest, api, rest-api
|
| 4 |
Requires at least: 4.4
|
| 5 |
Tested up to: 4.5-alpha
|
| 6 |
+
Stable tag: 2.0-beta12
|
| 7 |
License: GPLv2 or later
|
| 8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
| 9 |
|
| 30 |
|
| 31 |
== Installation ==
|
| 32 |
|
| 33 |
+
Install the WP REST API via the plugin directory, or by uploading the files manually to your server.
|
| 34 |
|
| 35 |
For full-flavoured API support, you'll need to be using pretty permalinks to use the plugin, as it uses custom rewrite rules to power the API.
|
| 36 |
|
| 37 |
+
Once you've installed and activated the plugin, [check out the documentation](http://v2.wp-api.org/) for details on your newly available endpoints.
|
| 38 |
+
|
| 39 |
== Changelog ==
|
| 40 |
|
| 41 |
+
= 2.0 Beta 12.0 (February 9, 2016) =
|
| 42 |
+
|
| 43 |
+
* BREAKING CHANGE: Removes meta endpoints from primary plugin.
|
| 44 |
+
|
| 45 |
+
If your project depends on post meta endpoints, please install [WP REST API Meta Endpoints](https://wordpress.org/plugins/rest-api-meta-endpoints/). For the gory history of meta, read [#1425](https://github.com/WP-API/WP-API/issues/1425) and linked issues. At this time, we recommend using `register_rest_field()` to expose meta ([docs](http://v2.wp-api.org/extending/modifying/)).
|
| 46 |
+
|
| 47 |
+
(props @danielbachhuber, [#2172](https://github.com/WP-API/WP-API/pull/2172))
|
| 48 |
+
|
| 49 |
+
* BREAKING CHANGE: Returns original resource when deleting PTCU.
|
| 50 |
+
|
| 51 |
+
Now that all resources require the `force` param, we don't need to wrap delete responses with the `trash` state.
|
| 52 |
+
|
| 53 |
+
(props @danielbachhuber, [#2163](https://github.com/WP-API/WP-API/pull/2163))
|
| 54 |
+
|
| 55 |
+
* BREAKING CHANGE: Uses `roles` rather than `role` in the Users controller.
|
| 56 |
+
|
| 57 |
+
Building the REST API gives us the opportunity to standardize on `roles`, instead of having both `roles` and `role`.
|
| 58 |
+
|
| 59 |
+
(props @joehoyle, [#2177](https://github.com/WP-API/WP-API/pull/2177))
|
| 60 |
+
|
| 61 |
+
* BREAKING CHANGES: Moves to consistent use of `context` throughout controllers.
|
| 62 |
+
|
| 63 |
+
Contexts limit the data present in the response. Here's how to think of them: `embed` correlates with sidebar representation, `view` represents the primary public view, and `edit` is the data expected for an editor.
|
| 64 |
+
|
| 65 |
+
(props @danielbachhuber, [#2205](https://github.com/WP-API/WP-API/pull/2205), [#2204](https://github.com/WP-API/WP-API/pull/2204), [#2203](https://github.com/WP-API/WP-API/pull/2203), [#2218](https://github.com/WP-API/WP-API/pull/2218), [#2216](https://github.com/WP-API/WP-API/pull/2216), [#2230](https://github.com/WP-API/WP-API/pull/2230), [#2184](https://github.com/WP-API/WP-API/pull/2184), [#2235](https://github.com/WP-API/WP-API/pull/2235))
|
| 66 |
+
|
| 67 |
+
* BREAKING CHANGE: Removes `post_*` query param support for `GET /wp/v2/comments`.
|
| 68 |
+
|
| 69 |
+
The proper pattern is to use `GET /wp/v2/posts` to fetch the post IDs to limit the request to.
|
| 70 |
+
|
| 71 |
+
(props @danielbachhuber, [#2165](https://github.com/WP-API/WP-API/pull/2165))
|
| 72 |
+
|
| 73 |
+
* BREAKING CHANGE: Introduces `rest_validate_request_arg()`/`rest_sanitize_request_arg()`.
|
| 74 |
+
|
| 75 |
+
Dedicated functions means we can use them for validating / sanitizing query args too. Removes `WP_REST_Controller::validate_schema_property()` and `WP_REST_Controller::sanitize_schema_property()`.
|
| 76 |
+
|
| 77 |
+
(props @danielbachhuber, [#2166](https://github.com/WP-API/WP-API/pull/2166), [#2213](https://github.com/WP-API/WP-API/pull/2213))
|
| 78 |
+
|
| 79 |
+
* Requires minimum value of 1 for `page` param.
|
| 80 |
+
|
| 81 |
+
(props @danielbachhuber, [#2241](https://github.com/WP-API/WP-API/pull/2241))
|
| 82 |
+
|
| 83 |
+
* Introduces `media_type` and `mime_type` params for `GET /wp/v2/media`.
|
| 84 |
+
|
| 85 |
+
(props @danielbachhuber, [#2231](https://github.com/WP-API/WP-API/pull/2231))
|
| 86 |
+
|
| 87 |
+
* Uses the term cache for post data.
|
| 88 |
+
|
| 89 |
+
(props @rmccue, [#2234](https://github.com/WP-API/WP-API/pull/2234))
|
| 90 |
+
|
| 91 |
+
* Supports for querying comments where `post=0`.
|
| 92 |
+
|
| 93 |
+
(props @danielbachhuber, [#1865](https://github.com/WP-API/WP-API/pull/1865))
|
| 94 |
+
|
| 95 |
+
* Exposes taxonomy and post type capabilities in `context=edit`.
|
| 96 |
+
|
| 97 |
+
(props @danielbachhuber, [#2216](https://github.com/WP-API/WP-API/pull/2216))
|
| 98 |
+
|
| 99 |
+
* Errors early when user can't GET types or taxonomies when `context=edit`.
|
| 100 |
+
|
| 101 |
+
(props @danielbachhuber, [#2218](https://github.com/WP-API/WP-API/pull/2218))
|
| 102 |
+
|
| 103 |
+
* Passes original $request context to `prepare_items_query`.
|
| 104 |
+
|
| 105 |
+
(props @danielbachhuber, [#2211](https://github.com/WP-API/WP-API/pull/2211))
|
| 106 |
+
|
| 107 |
+
* Adds `parent` and `parent_exclude` params to GET Comments.
|
| 108 |
+
|
| 109 |
+
(props @danielbachhuber, [#2206](https://github.com/WP-API/WP-API/pull/2206))
|
| 110 |
+
|
| 111 |
+
* Enforces minimum 1 and maximum 100 values for `per_page` parameter.
|
| 112 |
+
|
| 113 |
+
(props @danielbachhuber, [#2209](https://github.com/WP-API/WP-API/pull/2209))
|
| 114 |
+
|
| 115 |
+
* Adds `author` and `author_exclude` params to GET Posts and Comments.
|
| 116 |
+
|
| 117 |
+
(props @danielbachhuber, [#2200](https://github.com/WP-API/WP-API/pull/2202), [#2200](https://github.com/WP-API/WP-API/pull/2202))
|
| 118 |
+
|
| 119 |
+
* Adds `menu_order` param for `GET` Pages; support `menu_order` orderby.
|
| 120 |
+
|
| 121 |
+
(props @danielbachhuber, [#2193](https://github.com/WP-API/WP-API/pull/2193))
|
| 122 |
+
|
| 123 |
+
* Only calls `sanitize_text_field()` when sanitizing `type=string,format=email`.
|
| 124 |
+
|
| 125 |
+
(props @danielbachhuber, [#2185](https://github.com/WP-API/WP-API/pull/2185))
|
| 126 |
+
|
| 127 |
+
* Validates `GET /wp/v2/comments` private query params.
|
| 128 |
+
|
| 129 |
+
Returns an error when user doesn't have permission to use them, instead of silently discarding.
|
| 130 |
+
|
| 131 |
+
(props @danielbachhuber, [#2178](https://github.com/WP-API/WP-API/pull/2178))
|
| 132 |
+
|
| 133 |
+
* Explicitly prevents uploading attachments to other attachments or revisions.
|
| 134 |
+
|
| 135 |
+
(props @danielbachhuber, [#2180](https://github.com/WP-API/WP-API/pull/2180))
|
| 136 |
+
|
| 137 |
+
* Permits user urls to be edited through the API.
|
| 138 |
+
|
| 139 |
+
(props @danielbachhuber, [#2182](https://github.com/WP-API/WP-API/pull/2182))
|
| 140 |
+
|
| 141 |
+
* Marks all Status, Type and Taxonomy fields as `readonly`.
|
| 142 |
+
|
| 143 |
+
(props @danielbachhuber, [#2181](https://github.com/WP-API/WP-API/pull/2181))
|
| 144 |
+
|
| 145 |
+
* Adds validation callbacks to collection query params.
|
| 146 |
+
|
| 147 |
+
(props @danielbachhuber, [#2170](https://github.com/WP-API/WP-API/pull/2170), [#2171](https://github.com/WP-API/WP-API/pull/2171), [#2176](https://github.com/WP-API/WP-API/pull/2176), [#2174](https://github.com/WP-API/WP-API/pull/2174), [#2175](https://github.com/WP-API/WP-API/pull/2175))
|
| 148 |
+
|
| 149 |
+
* Links taxonomy terms to the post type collections they support.
|
| 150 |
+
|
| 151 |
+
(props @danielbachhuber, [#2167](https://github.com/WP-API/WP-API/pull/2167))
|
| 152 |
+
|
| 153 |
+
* Returns error when making a `GET` request with invalid context.
|
| 154 |
+
|
| 155 |
+
(props @danielbachhuber, [#2169](https://github.com/WP-API/WP-API/pull/2169))
|
| 156 |
+
|
| 157 |
+
* Adds `trash` status to `GET /wp/v2/statuses`.
|
| 158 |
+
|
| 159 |
+
(props @danielbachhuber, [#2158](https://github.com/WP-API/WP-API/pull/2158))
|
| 160 |
+
|
| 161 |
+
* Indicates when fields have HTML in schema.
|
| 162 |
+
|
| 163 |
+
(props @joehoyle, [#2159](https://github.com/WP-API/WP-API/pull/2159))
|
| 164 |
+
|
| 165 |
+
* Permits viewing of User who has published any Public posts.
|
| 166 |
+
|
| 167 |
+
(props @danielbachhuber, [#2155](https://github.com/WP-API/WP-API/pull/2155))
|
| 168 |
+
|
| 169 |
+
* Respects `show_avatars` option when adding avatars to Users.
|
| 170 |
+
|
| 171 |
+
(props @nullvariable, [#2151](https://github.com/WP-API/WP-API/pull/2151))
|
| 172 |
+
|
| 173 |
+
* Controllers use `$namespace` and `$rest_base` class variables for easier subclassing.
|
| 174 |
+
|
| 175 |
+
(props @danielbachhuber, [#2119](https://github.com/WP-API/WP-API/pull/2119), [#2130](https://github.com/WP-API/WP-API/pull/2130), [#2131](https://github.com/WP-API/WP-API/pull/2131), [#2132](https://github.com/WP-API/WP-API/pull/2132), [#2133](https://github.com/WP-API/WP-API/pull/2133), [#2134](https://github.com/WP-API/WP-API/pull/2134), [#2139](https://github.com/WP-API/WP-API/pull/2139), [#2141](https://github.com/WP-API/WP-API/pull/2141), [#2142](https://github.com/WP-API/WP-API/pull/2142))
|
| 176 |
+
|
| 177 |
+
= 2.0 Beta 11.0 (January 25, 2016) =
|
| 178 |
|
| 179 |
* BREAKING CHANGE: Moves Post->Term relations to the Post Resource
|
| 180 |
|
| 321 |
|
| 322 |
(props @danielbachhuber, [#1990](https://github.com/WP-API/WP-API/pull/1990))
|
| 323 |
|
| 324 |
+
= 2.0 Beta 10.0 (January 11, 2016) =
|
| 325 |
|
| 326 |
* SECURITY: Ensure media of private posts are private too.
|
| 327 |
|
| 453 |
|
| 454 |
(props @danielbachhuber, [#1852](https://github.com/WP-API/WP-API/pull/1852))
|
| 455 |
|
| 456 |
+
= 2.0 Beta 9.0 (December 11, 2015) =
|
| 457 |
|
| 458 |
* BREAKING CHANGE: Move tags and categories to top-level endpoints.
|
| 459 |
|
| 567 |
|
| 568 |
(props @danielbachhuber, [#1833](https://github.com/WP-API/WP-API/pull/1833))
|
| 569 |
|
| 570 |
+
= 2.0 Beta 8.0 (December 1, 2015) =
|
| 571 |
|
| 572 |
* Prevent fatals when uploading attachment by including admin utilities.
|
| 573 |
|
| 603 |
|
| 604 |
(props @wpsmith, [#1759](https://github.com/WP-API/WP-API/pull/1759))
|
| 605 |
|
| 606 |
+
= 2.0 Beta 7.0 (November 17, 2015) =
|
| 607 |
|
| 608 |
* Sync infrastructure from WordPress core as of r35691.
|
| 609 |
|
| 634 |
|
| 635 |
(props @danielbachhuber, [#1726](https://github.com/WP-API/WP-API/pull/1726))
|
| 636 |
|
| 637 |
+
= 2.0 Beta 6.0 (November 12, 2015) =
|
| 638 |
|
| 639 |
* Remove global inclusion of wp-admin/includes/admin.php
|
| 640 |
|
| 730 |
|
| 731 |
(props @rachelbaker, [#1497](https://github.com/WP-API/WP-API/pull/1497))
|
| 732 |
|
| 733 |
+
= 2.0 Beta 5.0 (October 23, 2015) =
|
| 734 |
|
| 735 |
* Load api-core as a compatibility library
|
| 736 |
|
| 764 |
|
| 765 |
(props @joehoyle)
|
| 766 |
|
| 767 |
+
= 2.0 Beta 4.0 (August 14, 2015) =
|
| 768 |
|
| 769 |
* Show public user information through the user controller.
|
| 770 |
|
| 997 |
[gh-1467]: https://github.com/WP-API/WP-API/issues/1467
|
| 998 |
[gh-1472]: https://github.com/WP-API/WP-API/issues/1472
|
| 999 |
|
| 1000 |
+
= 2.0 Beta 3.0 (July 1, 2015) =
|
| 1001 |
|
| 1002 |
* Add ability to declare sanitization and default options for schema fields.
|
| 1003 |
|
| 1062 |
[gh-1347]: https://github.com/WP-API/WP-API/issues/1347
|
| 1063 |
[gh-1348]: https://github.com/WP-API/WP-API/issues/1348
|
| 1064 |
|
| 1065 |
+
= 2.0 Beta 2.0 (May 28, 2015) =
|
| 1066 |
|
| 1067 |
* Load the WP REST API before the main query runs.
|
| 1068 |
|
| 1282 |
|
| 1283 |
Reported by @kacperszurek on 2015-05-16.
|
| 1284 |
|
| 1285 |
+
= 2.0 Beta 1 (April 28, 2015) =
|
| 1286 |
|
| 1287 |
Partial rewrite and evolution of the REST API to prepare for core integration.
|
| 1288 |
|
