PluginProbe
UpdraftPlus: WP Backup & Migration Plugin / 1.16.5
UpdraftPlus: WP Backup & Migration Plugin v1.16.5
1.26.7 1.26.6 1.26.5 1.26.4 1.26.3 1.9.19 1.9.25 1.9.26 1.9.30 1.9.31 1.9.32 1.9.4 1.9.40 1.9.41 1.9.42 1.9.43 1.9.44 1.9.45 1.9.46 1.9.5 1.9.50 1.9.51 1.9.60 1.9.62 1.9.63 All 371 releases
updraftplus / central / modules / posts.php

posts.php in UpdraftPlus: WP Backup & Migration Plugin 1.16.5, at central/modules/posts.php

769 lines 23.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
4
5 /**
6 * Handles Posts Commands
7 */
8 class UpdraftCentral_Posts_Commands extends UpdraftCentral_Commands {
9
10 private $switched = false;
11
12 /**
13 * Function that gets called before every action
14 *
15 * @param string $command a string that corresponds to UDC command to call a certain method for this class.
16 * @param array $data an array of data post or get fields
17 * @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
18 *
19 * link to udrpc_action main function in class UpdraftPlus_UpdraftCentral_Listener
20 */
21 public function _pre_action($command, $data, $extra_info) {// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
22 // Here we assign the current blog_id to a variable $blog_id
23 $blog_id = get_current_blog_id();
24 if (!empty($data['site_id'])) $blog_id = $data['site_id'];
25
26 if (function_exists('switch_to_blog') && is_multisite() && $blog_id) {
27 $this->switched = switch_to_blog($blog_id);
28 }
29 }
30
31 /**
32 * Function that gets called after every action
33 *
34 * @param string $command a string that corresponds to UDC command to call a certain method for this class.
35 * @param array $data an array of data post or get fields
36 * @param array $extra_info extrainfo use in the udrpc_action, e.g. user_id
37 *
38 * link to udrpc_action main function in class UpdraftPlus_UpdraftCentral_Listener
39 */
40 public function _post_action($command, $data, $extra_info) {// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
41 // Here, we're restoring to the current (default) blog before we switched
42 if ($this->switched) restore_current_blog();
43 }
44
45 /**
46 * Method to fetch all posts which depends on parameters passed in site_post.js, on success return posts object
47 *
48 * @param array $params An array containing the "site_id" and "paged" parameters needed to pull all posts
49 * @return array
50 *
51 * @link {https://developer.wordpress.org/reference/functions/get_posts/}
52 * @link {https://developer.wordpress.org/reference/functions/wp_count_posts}
53 * @link {https://developer.wordpress.org/reference/functions/get_the_author_meta/}
54 * @link {https://developer.wordpress.org/reference/functions/get_the_category}
55 */
56 public function get_requested_posts($params) {
57
58 if (empty($params['numberposts'])) return $this->_generic_error_response('numberposts_parameter_missing', $params);
59
60 // check paged parameter; if empty set to 1
61 $paged = !empty($params['paged']) ? (int) $params['paged'] : 1;
62
63 $args = array(
64 'posts_per_page' => $params['numberposts'],
65 'paged' => $paged,
66 'post_type' => 'post',
67 'post_status' => !empty($params['post_status']) ? $params['post_status'] : 'any'
68 );
69
70 if (!empty($params['category'][0])) {
71 $term_id = (int) $params['category'][0];
72 $args['category__in'] = array($term_id);
73 }
74
75 // Using default function get_posts to fetch all posts object from passed parameters
76 // Count all fetch posts objects
77 // get total fetch posts and divide to number of posts for pagination
78 $query = new WP_Query($args);
79 $result = $query->posts;
80
81 $count_posts = $query->found_posts;
82 $page_count = 0;
83 $postdata = array();
84
85 if ((int) $count_posts > 0) {
86 $page_count = absint((int) $count_posts / (int) $params['numberposts']);
87 $remainder = absint((int) $count_posts % (int) $params['numberposts']);
88
89 $page_count = ($remainder > 0) ? ++$page_count : $page_count;
90 }
91
92 $info = array(
93 'page' => $paged,
94 'pages' => $page_count,
95 'results' => $count_posts
96 );
97
98 if (empty($result)) {
99 $error_data = array(
100 'count' => $page_count,
101 'paged' => $paged,
102 'info' => $info
103 );
104 return $this->_generic_error_response('post_not_found_with_keyword', $error_data);
105 } else {
106 foreach ($result as $post) {
107 // initialize our stdclass variable data
108 $data = new stdClass();
109
110 // get the author name
111 $author = get_the_author_meta('display_name', $post->post_author);
112
113 // get categories associated with the post
114 $categories = get_the_category($post->ID);
115
116 $cat_array = array();
117 foreach ($categories as $category) {
118 $cat_array[] = $category->name;
119 }
120
121 // Adding author name and category assigned to the post object
122 $data->author_name = $author;
123 $data->category_name = $cat_array;
124 $data->post_title = $post->post_title;
125 $data->post_status = $post->post_status;
126 $data->ID = $post->ID;
127 $postdata[] = $data;
128 }
129
130 $response = array(
131 'posts' => $postdata,
132 'count' => $page_count,
133 'paged' => $paged,
134 'categories' => $this->get_requested_categories(array('parent' => 0, 'return_object' => true)),
135 'message' => "found_posts_count",
136 'params' => $params,
137 'info' => $info
138 );
139 }
140
141 return $this->_response($response);
142 }
143
144 /**
145 * Method to fetch post object based on parameter ID, on success return post object
146 *
147 * @param array $params An array containing the "site_id" and "ID" parameters needed to pull a single post
148 * @return array
149 *
150 * @link {https://developer.wordpress.org/reference/functions/get_post/}
151 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
152 */
153 public function get_requested_post($params) {
154
155 // Check parameter ID if empty
156 if (empty($params['ID'])) {
157 return $this->_generic_error_response('post_id_not_set', array());
158 }
159
160 // initialize stdclass variable data
161 $data = new stdClass();
162
163 // assign parameter ID to a variable
164 $post_id = $params['ID'];
165
166 // using default get_post to get post object by its ID
167 $post = get_post($post_id);
168
169 // assign
170 $visibility = get_post_status($post_id);
171
172 // Get all associated category of the post
173
174 $categories = $this->get_requested_post_categories($post_id);
175
176 if (is_wp_error($post)) {
177 // Return the wp_error
178 $error_data = array(
179 'visibility' => $visibility,
180 'categories' => $categories,
181 );
182 return $this->_generic_error_response('posts_not_found', $error_data);
183
184 } else {
185
186 $data->ID = $post->ID;
187 $data->post_title = $post->post_title;
188 $data->post_content = $post->post_content;
189 $data->post_status = $post->post_status;
190 $data->guid = $post->guid;
191 $data->post_date = $post->post_date;
192
193 $response = array(
194 'posts' => $data,
195 'visibility' => $visibility,
196 'categories' => $categories,
197 'message' => "found_post"
198 );
199
200 return $this->_response($response);
201 }
202
203 }
204
205 /**
206 * Method to fetch array of categories loop through all children
207 *
208 * @param array $params An array containing the "site_id" and "parent" parameters needed to pull a collection of categories
209 * @return array
210 *
211 * @link {https://developer.wordpress.org/reference/functions/get_categories/}
212 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
213 */
214 public function get_requested_categories($params) {
215
216 $parent = $params['parent'];
217
218 $categories = $this->get_taxonomy_hierarchy('category', $parent);
219 $category = new stdClass();
220 $arrobj = array();
221
222 // Add to existing category list | parent->children
223 $category->children = $categories;
224 $category->default = get_option('default_category');
225 $arrobj[] = $category;
226
227 if (!empty($params['return_object'])) {
228 return $arrobj;
229 }
230
231 return $this->_response($arrobj);
232 }
233
234 /**
235 * Method to get category on assigned to a post
236 *
237 * @param int $post_id The ID of the post where the categories are to be retrieve from
238 * @return array - returns an array of category
239 *
240 * @link {https://developer.wordpress.org/reference/functions/get_categories/}
241 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
242 */
243 public function get_requested_post_categories($post_id) {
244
245 $categories = $this->get_taxonomy_hierarchy('category');
246 $category = new stdClass();
247 $arrobj = array();
248
249 // Add to existing category list | parent->children
250 $category->children = $categories;
251 $category->default = get_option('default_category');
252
253 $arrterms = array();
254 $post_terms = get_the_terms($post_id, 'category');
255
256 foreach ($category->children as $term) {
257 foreach ($post_terms as $post_term) {
258 $arrterms[] = $post_term->term_id;
259 if ($term->term_id == $post_term->term_id) {
260 $term->selected = 1;
261 }
262 }
263 }
264
265 $arrobj[] = $category;
266
267 return $arrobj;
268 }
269
270 /**
271 * Method used to insert post from UDC to remote site
272 * Using the default wp_insert_post function
273 *
274 * @param array $post_array Default post_type "post" and basic parameters post_title, post_content, category, post_status
275 * @return array - Containing information whether the process was successful or not.
276 * Post ID on success, custom error object on failure.
277 *
278 * @link {https://developer.wordpress.org/reference/functions/wp_insert_post/}
279 * @link {https://developer.wordpress.org/reference/functions/get_current_user_id/}
280 * @link {https://developer.wordpress.org/reference/functions/current_user_can/}
281 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
282 */
283 public function insert_requested_post($post_array) {
284
285 // Check if post_title parameter is not set
286 if (empty($post_array['post_title'])) {
287 return $this->_generic_error_response('post_title_not_set', array());
288 }
289
290 // Check if user has capability
291 if (!current_user_can('edit_posts')) {
292 return $this->_generic_error_response('user_no_permission_to_edit_post', array());
293 }
294
295 $author = get_current_user_id();
296 $category = get_option('default_category');
297 $post_category = empty($post_array['post_category']) ? array($category) : $post_array['post_category'];
298 $post_title = $post_array['post_title'];
299 $post_content = $post_array['post_content'];
300 $post_status = $post_array['post_status'];
301
302 // Create post array
303 $post = array(
304 'post_title' => wp_strip_all_tags($post_title),
305 'post_content' => $post_content,
306 'post_author' => $author,
307 'post_category' => $post_category,
308 'post_status' => $post_status
309 );
310
311 // Insert the post array into the database, return post_id on success
312 $post_id = wp_insert_post($post);
313
314 // Check if result is false
315 if (is_wp_error($post_id)) {
316 $error_data = array(
317 'message' => __('Error inserting post')
318 );
319
320 return $this->_generic_error_response('post_insert_error', $error_data);
321
322 } else {
323
324 $result = array(
325 'ID' => $post_id,
326 'message' => "post_save_success",
327 'status' => $post_status
328 );
329 }
330
331 return $this->_response($result);
332
333 }
334
335 /**
336 * Method used to update post
337 * Using default wp_update_post
338 *
339 * @param array $params Post array to update specific post by ID
340 * @return array - Containing information whether the process was successful or not.
341 * Post ID on success, custom error object on failure.
342 *
343 * @link {https://developer.wordpress.org/reference/functions/wp_update_post/}
344 * @link {https://developer.wordpress.org/reference/functions/current_user_can/}
345 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
346 */
347 public function update_requested_post($params) {
348
349 // Check post_id parameter if set
350 if (empty($params['ID'])) {
351 return $this->_generic_error_response('post_id_not_set', array());
352 }
353
354 // Check if user has capability
355 if (!current_user_can('edit_posts') && !current_user_can('edit_other_posts')) {
356 return $this->_generic_error_response('user_no_permission_to_edit_post', array());
357 }
358
359 $category = get_option('default_category');
360 $post_category = empty($post_array['post_category']) ? array($category) : $post_array['post_category'];
361
362 // Assign post array values
363 $post = array(
364 'post_title' => wp_strip_all_tags($params['post_title']),
365 'post_content' => $params['post_content'],
366 'ID' => (int) $params['ID'],
367 'post_status' => $params['post_status'],
368 'post_category' => $post_category
369 );
370
371 // Do post update
372 $response = wp_update_post($post);
373
374 $result = array();
375
376 // Check if response is false
377 if (is_wp_error($response)) {
378 $error_data = array(
379 'message' => __('Error updating post')
380 );
381
382 return $this->_generic_error_response('post_update_error', $error_data);
383 }
384
385 $result = array(
386 'ID' => $response,
387 'message' => "post_update_success",
388 'status' => $params['post_status']
389 );
390
391 return $this->_response($result);
392 }
393
394 /**
395 * Method used to move post to trash, default action trash
396 * If delete set to true will delete permanently following all wp process
397 * If force_delete is true bypass process and force delete post
398 *
399 * @param array $params An array containing the ID of the post to delete and a
400 * couple of flags ("delete" and "force_delete") that will determine whether
401 * the post will be moved to trash or permanently deleted.
402 * @return array - Containing information whether the process was successful or not. True on success, false on failure.
403 *
404 * @link {https://developer.wordpress.org/reference/functions/wp_trash_post/}
405 * @link {https://developer.wordpress.org/reference/functions/wp_delete_post/}
406 * @link {https://developer.wordpress.org/reference/functions/current_user_can/}
407 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
408 */
409 public function trash_requested_post($params) {
410
411 // Check if post_id is set
412 if (empty($params['ID'])) {
413 return $this->_generic_error_response('post_id_not_set', array());
414 }
415
416 // Check user capability
417 if (!current_user_can('delete_posts')) {
418 return $this->_generic_error_response('user_no_permission_to_delete_post', array());
419 }
420
421 $post_id = (int) $params['ID'];
422 $forcedelete = !empty($params['force_delete']);
423 $trash = false;
424
425 // Here check if force_delete is set from UDC. then permanently delete bypass wp_trash_post.
426 if ($forcedelete) {
427 $response = wp_delete_post($post_id, $forcedelete);
428 } else {
429 $response = wp_trash_post($post_id);
430 $trash = true;
431 }
432
433 $result = array();
434
435 // Check if response if false
436 if (is_wp_error($response)) {
437 $error_data = array(
438 'message' => __('Error deleting post')
439 );
440 return $this->_generic_error_response('post_delete_error', $error_data);
441 }
442
443 $result = array(
444 'posts' => $response,
445 'error' => false,
446 );
447
448 if ($trash) {
449 $result["message"] = "post_has_been_moved_to_trash";
450 $status["status"] = "trash";
451 } else {
452 $result["message"] = "post_has_been_deleted_permanently";
453 $status["status"] = "delete";
454 }
455
456 return $this->_response($result);
457 }
458
459 /**
460 * Method used to insert/create a category
461 * Using default taxonomy "category"
462 * Will create slug based on cat_name parameter
463 *
464 * @param array $params cat_name parameter to insert category
465 * @return array - Containing the result of the process. Category ID, category object, etc.
466 *
467 * @link {https://developer.wordpress.org/reference/functions/wp_insert_category/}
468 * @link {https://developer.wordpress.org/reference/functions/current_user_can/}
469 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
470 */
471 public function insert_requested_category($params) {
472
473 /**
474 * Include admin taxonomy.php file to enable us to use all necessary functions for post category
475 */
476 $this->_admin_include('taxonomy.php');
477
478 $result = array();
479
480 // Check if parameter cat_name is set
481 if (empty($params['cat_name'])) {
482 return $this->_generic_error_response('category_name_not_set', array());
483 }
484
485 // Check user capability
486 if (!current_user_can('manage_categories')) {
487 return $this->_generic_error_response('user_no_permission_to_add_category', array());
488 }
489
490 // set category array
491 $args = array(
492 'cat_name' => $params["cat_name"],
493 'category_nicename' => sanitize_title($params["cat_name"])
494 );
495
496 // Do wp_insert_category
497 $term_id = wp_insert_category($args, true);
498
499 if (is_wp_error($response)) {
500 $error_data = array(
501 'message' => __('Error inserting category')
502 );
503 return $this->_generic_error_response('category_insert_error', $error_data);
504 }
505
506 $category = array(
507 'cat_name' => $params["cat_name"],
508 'term_id' => $term_id,
509 'parent' => 0
510 );
511
512 $result = array(
513 'ID' => $term_id,
514 'category' => $category,
515 'error' => false,
516 'message' => "category_added"
517 );
518
519 return $this->_response($result);
520 }
521
522 /**
523 * Method used to update/edit a category by its term_id
524 *
525 * @param array $param An array containing the "term_id" and "cat_name" parameters needed to edit the category
526 * @return array - Containing information as a result fo the process. True on success, false on failure.
527 *
528 * @link {https://developer.wordpress.org/reference/functions/wp_udpate_category/}
529 * @link {https://developer.wordpress.org/reference/functions/current_user_can/}
530 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
531 */
532 public function edit_requested_category($param) {
533 /**
534 * Include admin taxonomy.php file to enable us to use all necessary functions for post category
535 */
536 $this->_admin_include('taxonomy.php');
537
538 $result = array();
539
540 // Check if term_id is set
541 if (empty($param['term_id']) && empty($param['cat_name'])) {
542 return $this->_generic_error_response('term_id_or_category_not_set', array($params));
543 }
544
545 $term_id = $param['term_id'];
546 $cat_name = $param['cat_name'];
547
548 // Check user capability
549 if (!current_user_can('manage_categories')) {
550 return $this->_generic_error_response('user_no_permission_to_edit_category', array());
551 }
552
553 // Do term update
554 $response = wp_update_term($term_id, 'category', array('name' => $cat_name, 'slug' => sanitize_title($cat_name)));
555
556 // Check if response is false
557 if (is_wp_error($response)) {
558 $error_data = array(
559 'message' => __('Error updating category')
560 );
561 return $this->_generic_error_response('category_update_error', $error_data);
562 }
563
564 $result = array(
565 'category' => $cat_name,
566 'message' => "category_updated_to"
567 );
568
569 return $this->_response($result);
570 }
571
572 /**
573 * Method used to delete a category by term_id
574 *
575 * @param array $param An array containing the "term_id" needed to delete the category
576 * @return array - Containing information as a result fo the process. True on success, false on failure.
577 *
578 * @link {https://developer.wordpress.org/reference/functions/wp_delete_category/}
579 * @link {https://developer.wordpress.org/reference/functions/current_user_can/}
580 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
581 */
582 public function delete_requested_category($param) {
583 /**
584 * Include admin taxonomy.php file to enable us to use all necessary functions for post category
585 */
586 $this->_admin_include('taxonomy.php');
587
588 $result = array();
589
590 // Check if term_id is set
591 if (empty($param['term_id'])) {
592 return $this->_generic_error_response('term_id_not_set', array($params));
593 }
594
595 $term_id = $param['term_id'];
596
597 // Check user capability
598 if (!current_user_can('manage_categories')) {
599 return $this->_generic_error_response('user_no_permission_to_delete_category', array());
600 }
601
602 // Do wp_delete_category
603 $response = wp_delete_category($term_id);
604
605 if (is_wp_error($response)) {
606 $error_data = array(
607 'message' => __('Error deleting category')
608 );
609 return $this->_generic_error_response('user_no_permission_to_delete_category', $error_data);
610 }
611
612 $result = array(
613 'error' => false,
614 'message' => "category_deleted"
615 );
616
617 return $this->_response($result);
618 }
619
620 /**
621 * Method to fetch post search by post title
622 * Will return all posts if no match was found
623 *
624 * @param array $params An array containing the keyword to be used to search all available posts
625 * @return array - Containing the result of the process. Post object on success, a no matched message on failure.
626 *
627 * @link {https://developer.wordpress.org/reference/functions/get_post/}
628 * @link {https://developer.wordpress.org/reference/functions/switch_to_blog/}
629 */
630 public function find_post_by_title($params) {
631
632 $paged = !empty($params['paged']) ? (int) $params['paged'] : 1;
633
634 // Check if keyword is empty or null
635 if (empty($params['s'])) {
636 return $this->_generic_error_response('search_generated_no_result', array());
637 }
638
639 // Set an array with post_type to search only post
640 $query_string = array(
641 's' => $params['s'],
642 'post_type' => 'post',
643 'posts_per_page' => $params['numberposts'],
644 'paged' => $paged
645 );
646 $query = new WP_Query($query_string);
647 $postdata = array();
648
649 $count_posts = $query->found_posts;
650 if ((int) $count_posts > 0) {
651 if (empty($params['numberposts'])) return $this->_generic_error_response('numberposts_parameter_missing', $params);
652
653 $page_count = absint((int) $count_posts / (int) $params['numberposts']);
654 $remainder = absint((int) $count_posts % (int) $params['numberposts']);
655
656 $page_count = ($remainder > 0) ? ++$page_count : $page_count;
657 }
658
659 $info = array(
660 'page' => $paged,
661 'pages' => $page_count,
662 'results' => $count_posts
663 );
664
665 $response = array();
666 if ($query->have_posts()) {
667
668 foreach ($query->posts as $post) {
669
670 // initialize stdclass variable data
671 $data = new stdClass();
672
673 // get the author name
674 $author = get_the_author_meta('display_name', $post->post_author);
675
676 // get categories associated with the post
677 $categories = get_the_category($post->ID);
678
679 $cat_array = array();
680 foreach ($categories as $category) {
681 $cat_array[] = $category->name;
682 }
683
684 // Adding author name and category assigned to the post object
685 $data->author_name = $author;
686 $data->category_name = $cat_array;
687 $data->post_title = $post->post_title;
688 $data->post_status = $post->post_status;
689 $postdata[] = $data;
690 }
691
692 $response = array(
693 'categories' => $this->get_requested_categories(array('parent' => 0, 'return_object' => true)),
694 'posts' => $postdata,
695 'n' => $arr,
696 'count' => $count_posts,
697 'paged' => $paged,
698 'message' => "found_post",
699 'info' => $info
700 );
701 } else {
702 $error_data = array(
703 'count' => $count_posts,
704 'paged' => $paged,
705 'info' => $info
706 );
707 return $this->_generic_error_response('post_not_found_with_keyword', $error_data);
708 }
709
710 return $this->_response($response);
711 }
712
713 /**
714 * Recursively get taxonomy and its children
715 *
716 * @param string $taxonomy name e.g. category, post_tags
717 * @param int $parent id of the category to be fetch
718 * @return array Containing all the categories with children
719 *
720 * @link {https://developer.wordpress.org/reference/functions/get_terms/}
721 */
722 public function get_taxonomy_hierarchy($taxonomy, $parent = 0) {
723
724 // only 1 taxonomy
725 $taxonomy = is_array($taxonomy) ? array_shift($taxonomy) : $taxonomy;
726
727 // get all direct decendants of the $parent
728 $terms = get_terms($taxonomy, array( 'parent' => $parent, 'hide_empty' => false));
729
730 // prepare a new array. these are the children of $parent
731 // we'll ultimately copy all the $terms into this new array, but only after they
732 // find their own children
733 $children = array();
734
735 // go through all the direct decendants of $parent, and gather their children
736 foreach ($terms as $term) {
737 // recurse to get the direct decendants of "this" term
738 $term->children = $this->get_taxonomy_hierarchy($taxonomy, $term->term_id);
739 // add the term to our new array
740 $children[] = $term;
741 }
742
743 // send the results back to the caller
744 return $children;
745 }
746
747 /**
748 * Recursively get all taxonomies as complete hierarchies
749 *
750 * @param array $taxonomies array of taxonomy slugs
751 * @param int $parent starting id to fetch
752 *
753 * @return array Containing all the taxonomies
754 */
755 public function get_taxonomy_hierarchy_multiple($taxonomies, $parent = 0) {
756 if (!is_array($taxonomies)) {
757 $taxonomies = array($taxonomies);
758 }
759 $results = array();
760 foreach ($taxonomies as $taxonomy) {
761 $terms = $this->get_taxonomy_hierarchy($taxonomy, $parent);
762 if ($terms) {
763 $results[$taxonomy] = $terms;
764 }
765 }
766 return $results;
767 }
768 }
769