PluginProbe
UpdraftCentral Dashboard / 0.8.13
UpdraftCentral Dashboard v0.8.13
0.8.33 0.7.2 0.7.3 0.7.4 0.8.0 0.8.1 0.8.10 0.8.11 0.8.12 0.8.13 0.8.14 0.8.15 0.8.16 0.8.17 0.8.18 0.8.19 0.8.2 0.8.20 0.8.21 0.8.22 0.8.23 0.8.24 0.8.25 0.8.26 0.8.27 All 51 releases
updraftcentral / classes / class-rest-posts-controller.php

class-rest-posts-controller.php in UpdraftCentral Dashboard 0.8.13, at classes/class-rest-posts-controller.php

427 lines 15.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) die('Access denied.');
3
4 if (!class_exists('WP_REST_Posts_Controller')) {
5 include_once ABSPATH . 'wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php';
6 }
7
8 /**
9 * UpdraftCentral_REST_Posts_Controller class. Used to override some basic response
10 * details to integrate the remote post information.
11 *
12 * Originally copied and edited from WP_REST_Posts_Controller (WordPress 5.0.3). Updated
13 * to support higher versions up to WordPress 5.4.
14 *
15 * @see WP_REST_Posts_Controller
16 */
17 class UpdraftCentral_REST_Posts_Controller extends WP_REST_Posts_Controller {
18
19 public function __construct($post_type) {
20 parent::__construct($post_type);
21 }
22
23 /**
24 * Prepares a single post output for response.
25 *
26 * @since 4.7.0
27 *
28 * @param object $post_obj A simple (stdClass) object containing basic (public) properties of a remote post object.
29 * @param WP_REST_Request $request Request object.
30 * @param array $misc Array containing remote post data.
31 * @return WP_REST_Response Response object.
32 */
33 public function prepare_remote_item_for_response($post_obj, $request, $misc) {
34 // Make sure that we have a WP_Post object before proceeding
35 // with the rest of the process below.
36 $post = new WP_Post($post_obj);
37
38 $fields = $this->get_fields_for_response($request);
39
40 // Base fields for every post.
41 $data = array();
42
43 if ((function_exists('rest_is_field_included') && rest_is_field_included('id', $fields)) || in_array('id', $fields, true)) {
44 $data['id'] = (int) $post->ID;
45 }
46
47 if ((function_exists('rest_is_field_included') && rest_is_field_included('date', $fields)) || in_array('date', $fields, true)) {
48 $data['date'] = $this->prepare_date_response($post->post_date_gmt, $post->post_date);
49 }
50
51 if ((function_exists('rest_is_field_included') && rest_is_field_included('date_gmt', $fields)) || in_array('date_gmt', $fields, true)) {
52 /*
53 * For drafts, `post_date_gmt` may not be set, indicating that the date
54 * of the draft should be updated each time it is saved (see #38883).
55 * In this case, shim the value based on the `post_date` field
56 * with the site's timezone offset applied.
57 */
58 if ('0000-00-00 00:00:00' === $post->post_date_gmt) {
59 $post_date_gmt = get_gmt_from_date($post->post_date);
60 } else {
61 $post_date_gmt = $post->post_date_gmt;
62 }
63 $data['date_gmt'] = $this->prepare_date_response($post_date_gmt);
64 }
65
66 if ((function_exists('rest_is_field_included') && rest_is_field_included('guid', $fields)) || in_array('guid', $fields, true)) {
67 $data['guid'] = array(
68 /** This filter is documented in wp-includes/post-template.php */
69 'rendered' => $misc['guid_rendered'],
70 'raw' => $post->guid,
71 );
72 }
73
74 if ((function_exists('rest_is_field_included') && rest_is_field_included('modified', $fields)) || in_array('modified', $fields, true)) {
75 $data['modified'] = $this->prepare_date_response($post->post_modified_gmt, $post->post_modified);
76 }
77
78 if ((function_exists('rest_is_field_included') && rest_is_field_included('modified_gmt', $fields)) || in_array('modified_gmt', $fields, true)) {
79 /*
80 * For drafts, `post_modified_gmt` may not be set (see `post_date_gmt` comments
81 * above). In this case, shim the value based on the `post_modified` field
82 * with the site's timezone offset applied.
83 */
84 if ('0000-00-00 00:00:00' === $post->post_modified_gmt) {
85 $post_modified_gmt = gmdate('Y-m-d H:i:s', strtotime($post->post_modified) - (get_option('gmt_offset') * 3600));
86 } else {
87 $post_modified_gmt = $post->post_modified_gmt;
88 }
89 $data['modified_gmt'] = $this->prepare_date_response($post_modified_gmt);
90 }
91
92 if ((function_exists('rest_is_field_included') && rest_is_field_included('password', $fields)) || in_array('password', $fields, true)) {
93 $data['password'] = $post->post_password;
94 }
95
96 if ((function_exists('rest_is_field_included') && rest_is_field_included('slug', $fields)) || in_array('slug', $fields, true)) {
97 $data['slug'] = $post->post_name;
98 }
99
100 if ((function_exists('rest_is_field_included') && rest_is_field_included('status', $fields)) || in_array('status', $fields, true)) {
101 $data['status'] = $post->post_status;
102 }
103
104 if ((function_exists('rest_is_field_included') && rest_is_field_included('type', $fields)) || in_array('type', $fields, true)) {
105 $data['type'] = $post->post_type;
106 }
107
108 if ((function_exists('rest_is_field_included') && rest_is_field_included('link', $fields)) || in_array('link', $fields, true)) {
109 $data['link'] = $misc['link'];
110 }
111
112 if ((function_exists('rest_is_field_included') && rest_is_field_included('title', $fields)) || in_array('title', $fields, true)) {
113 $data['title'] = array(
114 'raw' => $post->post_title,
115 'rendered' => $misc['title_rendered'],
116 );
117 }
118
119 if ((function_exists('rest_is_field_included') && rest_is_field_included('content', $fields)) || in_array('content', $fields, true)) {
120 $data['content'] = array(
121 'raw' => $post->post_content,
122 /** This filter is documented in wp-includes/post-template.php */
123 'rendered' => $misc['post_password_required'] ? '' : $misc['content_rendered'],
124 'protected' => (bool) $post->post_password,
125 'block_version' => block_version($post->post_content),
126 );
127 }
128
129 if ((function_exists('rest_is_field_included') && rest_is_field_included('excerpt', $fields)) || in_array('excerpt', $fields, true)) {
130 /** This filter is documented in wp-includes/post-template.php */
131 $excerpt = $misc['excerpt'];
132 $data['excerpt'] = array(
133 'raw' => $post->post_excerpt,
134 'rendered' => $misc['post_password_required'] ? '' : $excerpt,
135 'protected' => (bool) $post->post_password,
136 );
137 }
138
139 if ((function_exists('rest_is_field_included') && rest_is_field_included('author', $fields)) || in_array('author', $fields, true)) {
140 $data['author'] = (int) $post->post_author;
141 }
142
143 if ((function_exists('rest_is_field_included') && rest_is_field_included('featured_media', $fields)) || in_array('featured_media', $fields, true)) {
144 $data['featured_media'] = (int) $misc['featured_media'];
145 }
146
147 if ((function_exists('rest_is_field_included') && rest_is_field_included('parent', $fields)) || in_array('parent', $fields, true)) {
148 $data['parent'] = (int) $post->post_parent;
149 }
150
151 if ((function_exists('rest_is_field_included') && rest_is_field_included('menu_order', $fields)) || in_array('menu_order', $fields, true)) {
152 $data['menu_order'] = (int) $post->menu_order;
153 }
154
155 if ((function_exists('rest_is_field_included') && rest_is_field_included('comment_status', $fields)) || in_array('comment_status', $fields, true)) {
156 $data['comment_status'] = $post->comment_status;
157 }
158
159 if ((function_exists('rest_is_field_included') && rest_is_field_included('ping_status', $fields)) || in_array('ping_status', $fields, true)) {
160 $data['ping_status'] = $post->ping_status;
161 }
162
163 if ((function_exists('rest_is_field_included') && rest_is_field_included('sticky', $fields)) || in_array('sticky', $fields, true)) {
164 $data['sticky'] = (bool) $misc['sticky'];
165 }
166
167 if ((function_exists('rest_is_field_included') && rest_is_field_included('template', $fields)) || in_array('template', $fields, true)) {
168 $template = $misc['template'];
169 if ($template) {
170 $data['template'] = $template;
171 } else {
172 $data['template'] = '';
173 }
174 }
175
176 if ((function_exists('rest_is_field_included') && rest_is_field_included('format', $fields)) || in_array('format', $fields, true)) {
177 $data['format'] = $misc['format'];
178 if ('false' == $data['format']) $data['format'] = (bool) $data['format'];
179
180 // Fill in blank post format.
181 if (empty($data['format'])) {
182 $data['format'] = 'standard';
183 }
184 }
185
186 if ((function_exists('rest_is_field_included') && rest_is_field_included('meta', $fields)) || in_array('meta', $fields, true)) {
187 $data['meta'] = $this->meta->get_value($post->ID, $request);
188 }
189
190 // We need categories and tags to show up in all WP version starting from WP 3.4, thus,
191 // we're going pass a "show_ui = true" filter to the wp_list_filter function. Filtering other
192 // taxonomy that are not meant to be shown in any UI elements or section.
193 $taxonomies = wp_list_filter($misc['taxonomy_objects'], array('show_ui' => 'true'));
194
195 foreach ($taxonomies as $taxonomy) {
196 $tax_name = $taxonomy['name'];
197 $base = !empty($taxonomy['rest_base']) ? $taxonomy['rest_base'] : $tax_name;
198
199 if ((function_exists('rest_is_field_included') && rest_is_field_included($base, $fields)) || in_array($base, $fields, true)) {
200 $terms = $misc['taxonomy_terms'][$tax_name];
201
202 // Making sure that the terms collection is not empty before we add its data to the response.
203 if (!empty($terms)) {
204 $terms = array_values(wp_list_pluck($terms, 'term_id'));
205 foreach ($terms as $key => $value) {
206 if (!empty($value)) {
207 $terms[$key] = (int) $value;
208 } else {
209 // If value is empty, then we remove the empty entry
210 // from the terms collection before returning.
211 unset($terms[$key]);
212 }
213 }
214 }
215 $data[$base] = $terms ? $terms : array();
216 }
217 }
218
219 if ((bool) $misc['post_type_viewable'] && (bool) $misc['post_type_public']) {
220 $sample_permalink = $misc['sample_permalink'];
221 if ((function_exists('rest_is_field_included') && rest_is_field_included('permalink_template', $fields)) || in_array('permalink_template', $fields, true)) {
222 $data['permalink_template'] = $sample_permalink[0];
223 }
224 if ((function_exists('rest_is_field_included') && rest_is_field_included('generated_slug', $fields)) || in_array('generated_slug', $fields, true)) {
225 $data['generated_slug'] = $sample_permalink[1];
226 }
227 }
228
229 $context = !empty($request['context']) ? $request['context'] : 'view';
230 $data = $this->add_additional_fields_to_object($data, $request);
231 $data = $this->filter_response_by_context($data, $context);
232
233 // Wrap the data in a response object.
234 $response = rest_ensure_response($data);
235
236 $links = $this->prepare_remote_links($post, $misc);
237 $response->add_links($links);
238
239 if (!empty($links['self']['href'])) {
240 $actions = $this->get_available_remote_actions($post, $request, $misc);
241
242 $self = $links['self']['href'];
243 foreach ($actions as $rel) {
244 $response->add_link($rel, $self);
245 }
246 }
247
248 return $response;
249 }
250
251 /**
252 * Prepares remote links for the request.
253 *
254 * @param WP_Post $post Post object.
255 * @param array $misc Miscellaneous data for the Post object
256 * @return array Links for the given post.
257 */
258 private function prepare_remote_links($post, $misc) {
259 $base = sprintf('%s/%s', $this->namespace, $this->rest_base);
260
261 // Entity meta.
262 $links = array(
263 'self' => array(
264 'href' => rest_url(trailingslashit($base) . $post->ID),
265 ),
266 'collection' => array(
267 'href' => rest_url($base),
268 ),
269 'about' => array(
270 'href' => rest_url('wp/v2/types/' . $this->post_type),
271 ),
272 );
273
274 if ((in_array($post->post_type, array('post', 'page'), true) || (bool) $misc['post_type_supports_authors'])
275 && !empty($post->post_author)) {// phpcs:ignore PEAR.ControlStructures.MultiLineCondition.CloseBracketNewLine
276 $links['author'] = array(
277 'href' => rest_url('wp/v2/users/' . $post->post_author),
278 'embeddable' => true,
279 );
280 }
281
282 if (in_array($post->post_type, array('post', 'page'), true) || (bool) $misc['post_type_supports_comments']) {
283 $replies_url = rest_url('wp/v2/comments');
284 $replies_url = add_query_arg('post', $post->ID, $replies_url);
285
286 $links['replies'] = array(
287 'href' => $replies_url,
288 'embeddable' => true,
289 );
290 }
291
292 if (in_array($post->post_type, array('post', 'page'), true) || (bool) $misc['post_type_supports_revisions']) {
293 $revisions = $misc['post_revisions'];
294 $revisions_count = count($revisions);
295
296 $links['version-history'] = array(
297 'href' => rest_url(trailingslashit($base) . $post->ID . '/revisions'),
298 'count' => $revisions_count,
299 );
300
301 if ($revisions_count > 0) {
302 $last_revision = array_shift($revisions);
303
304 $links['predecessor-version'] = array(
305 'href' => rest_url(trailingslashit($base) . $post->ID . '/revisions/' . $last_revision),
306 'id' => $last_revision,
307 );
308 }
309
310 }
311
312 if ((bool) $misc['post_type_hierarchical'] && !empty($post->post_parent)) {
313 $links['up'] = array(
314 'href' => rest_url(trailingslashit($base) . (int) $post->post_parent),
315 'embeddable' => true,
316 );
317 }
318
319 // If we have a featured media, add that.
320 if ($featured_media = $misc['post_thumbnail_id']) {
321 $image_url = rest_url('wp/v2/media/' . $featured_media);
322
323 $links['https://api.w.org/featuredmedia'] = array(
324 'href' => $image_url,
325 'embeddable' => true,
326 );
327 }
328
329 if (!in_array($post->post_type, array('attachment', 'nav_menu_item', 'revision'), true)) {
330 $attachments_url = rest_url('wp/v2/media');
331 $attachments_url = add_query_arg('parent', $post->ID, $attachments_url);
332
333 $links['https://api.w.org/attachment'] = array(
334 'href' => $attachments_url,
335 );
336 }
337
338 $taxonomies = $misc['taxonomy_names'];
339 if (!empty($taxonomies)) {
340 $links['https://api.w.org/term'] = array();
341
342 foreach ($taxonomies as $tax) {
343 if (!empty($misc['taxonomy_objects']) && isset($misc['taxonomy_objects'][$tax])) {
344 $taxonomy_obj = $misc['taxonomy_objects'][$tax];
345
346 // Skip taxonomies that are not public.
347 if (empty($taxonomy_obj['show_in_rest']) || !json_decode($taxonomy_obj['show_in_rest'])) {
348 continue;
349 }
350
351 $tax_base = !empty($taxonomy_obj['rest_base']) ? $taxonomy_obj['rest_base'] : $tax;
352 $terms_url = add_query_arg(
353 'post',
354 $post->ID,
355 rest_url('wp/v2/' . $tax_base)
356 );
357
358 $links['https://api.w.org/term'][] = array(
359 'href' => $terms_url,
360 'taxonomy' => $tax,
361 'embeddable' => true,
362 );
363 }
364 }
365 }
366
367 return $links;
368 }
369
370 /**
371 * Get available remote actions
372 *
373 * @param WP_Post $post Post object.
374 * @param WP_REST_Request $request Request object.
375 * @param array $misc Miscellaneous data for the Post object
376 * @return array Action links for the given post.
377 */
378 private function get_available_remote_actions($post, $request, $misc) {
379 if ('edit' !== $request['context']) {
380 return array();
381 }
382
383 $rels = array();
384
385 if ('attachment' !== $this->post_type && (bool) $misc['can_publish_posts']) {
386 $rels[] = 'https://api.w.org/action-publish';
387 }
388
389 if ((bool) $misc['can_unfiltered_html']) {
390 $rels[] = 'https://api.w.org/action-unfiltered-html';
391 }
392
393 if ('post' === $misc['post_type_name']) {
394 if ((bool) $misc['can_edit_others_posts'] && (bool) $misc['can_publish_posts']) {
395 $rels[] = 'https://api.w.org/action-sticky';
396 }
397 }
398
399 if ((bool) $misc['post_type_supports_authors']) {
400 if ((bool) $misc['can_edit_others_posts']) {
401 $rels[] = 'https://api.w.org/action-assign-author';
402 }
403 }
404
405 $taxonomies = wp_list_filter($misc['taxonomy_objects'], array('show_in_rest' => 'true'));
406 foreach ($taxonomies as $tax) {
407 $tax_name = $tax['name'];
408 $tax_base = !empty($tax['rest_base']) ? $tax['rest_base'] : $tax_name;
409
410 if (!empty($misc['taxonomy_caps']) && isset($misc['taxonomy_caps'][$tax_name])) {
411 $tax_caps = $misc['taxonomy_caps'][$tax_name];
412 $create_cap = (bool) $tax_caps['hierarchical'] ? (bool) $tax_caps['edit_terms'] : (bool) $tax_caps['assign_terms'];
413
414 if ($create_cap) {
415 $rels[] = 'https://api.w.org/action-create-' . $tax_base;
416 }
417
418 if ((bool) $tax_caps['assign_terms']) {
419 $rels[] = 'https://api.w.org/action-assign-' . $tax_base;
420 }
421 }
422 }
423
424 return $rels;
425 }
426 }
427