Version Description
Download this release
Release Info
Developer | danielbachhuber |
Plugin | WordPress REST API (Version 2) |
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 |
|