PluginProbe
Assistant – Every Day Productivity Apps / 1.5.3
Assistant – Every Day Productivity Apps v1.5.3
1.5.5 trunk 0.1.0 0.2.0 0.2.1 0.2.2 0.3.0 0.3.1 0.4 0.4.1 0.4.2 0.5.0 0.5.1 0.6.0 0.7.0 0.7.0.2 0.7.0.3 0.7.0.4 0.7.0.5 0.7.0.6 0.7.0.7 0.7.0.8 0.7.0.9 0.7.1 1.0 All 71 releases
assistant / backend / src / Controllers / Cloud / Libraries / LibraryItemPostController.php

LibraryItemPostController.php in Assistant – Every Day Productivity Apps 1.5.3, at backend/src/Controllers/Cloud/Libraries/LibraryItemPostController.php

704 lines 18.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FL\Assistant\Controllers\Cloud\Libraries;
4
5 use FL\Assistant\System\Contracts\ControllerAbstract;
6 use FL\Assistant\Data\Transformers\PostTransformer;
7 use FL\Assistant\Helpers\PreviewHelper;
8 use FL\Assistant\Helpers\JsonHelper;
9 use FL\Assistant\Helpers\MediaPathHelper;
10 use FL\Assistant\Helpers\ScreenshotHelper;
11 use FL\Assistant\Services\MediaLibraryService;
12 use FL\Assistant\Clients\Cloud\CloudClient;
13
14 class LibraryItemPostController extends ControllerAbstract {
15
16 protected $posts;
17
18 /**
19 * Controller constructor.
20 *
21 * @return void
22 */
23 public function __construct( PostTransformer $posts ) {
24 $this->posts = $posts;
25 }
26
27 /**
28 * Register routes.
29 *
30 * @return void
31 */
32 public function register_routes() {
33
34 $this->route(
35 '/posts/preview_library_post/',
36 [
37 [
38 'methods' => \WP_REST_Server::CREATABLE,
39 'callback' => [ $this, 'preview_library_post' ],
40 'permission_callback' => function () {
41 return current_user_can( 'edit_others_posts' );
42 },
43 ],
44 ]
45 );
46
47 $this->route(
48 '/posts/(?P<id>\d+)/library/(?P<library_id>\d+)',
49 [
50 [
51 'methods' => \WP_REST_Server::CREATABLE,
52 'callback' => [ $this, 'save_to_library' ],
53 'args' => [
54 'id' => [
55 'required' => true,
56 'type' => 'number',
57 ],
58 'library_id' => [
59 'required' => true,
60 'type' => 'number',
61 ],
62 ],
63 'permission_callback' => function () {
64 return current_user_can( 'edit_others_posts' );
65 },
66 ],
67 ]
68 );
69
70 $this->route(
71 '/posts/(?P<id>\d+)/sync_to_library/(?P<item_id>\d+)',
72 [
73 [
74 'methods' => \WP_REST_Server::CREATABLE,
75 'callback' => [ $this, 'sync_to_library' ],
76 'args' => [
77 'id' => [
78 'required' => true,
79 'type' => 'number',
80 ],
81 'item_id' => [
82 'required' => true,
83 'type' => 'number',
84 ],
85 ],
86 'permission_callback' => function () {
87 return current_user_can( 'edit_others_posts' );
88 },
89 ],
90 ]
91 );
92
93 $this->route(
94 '/posts/import_from_library/',
95 [
96 [
97 'methods' => \WP_REST_Server::CREATABLE,
98 'callback' => [ $this, 'import_from_library' ],
99 'permission_callback' => function () {
100 return current_user_can( 'edit_others_posts' );
101 },
102 ],
103 ]
104 );
105
106 $this->route(
107 '/posts/import_post_thumb_from_library/(?P<post_id>\d+)',
108 [
109 [
110 'methods' => \WP_REST_Server::CREATABLE,
111 'callback' => [ $this, 'import_post_thumb_from_library' ],
112 'args' => [
113 'post_id' => [
114 'required' => true,
115 'type' => 'number',
116 ],
117 ],
118 'permission_callback' => function () {
119 return current_user_can( 'edit_others_posts' );
120 },
121 ],
122 ]
123 );
124
125 $this->route(
126 '/posts/import_post_media_from_library/(?P<post_id>\d+)',
127 [
128 [
129 'methods' => \WP_REST_Server::CREATABLE,
130 'callback' => [ $this, 'import_post_media_from_library' ],
131 'args' => [
132 'post_id' => [
133 'required' => true,
134 'type' => 'number',
135 ],
136 ],
137 'permission_callback' => function () {
138 return current_user_can( 'edit_others_posts' );
139 },
140 ],
141 ]
142 );
143
144 $this->route(
145 '/posts/(?P<id>\d+)/sync_from_library/',
146 [
147 [
148 'methods' => \WP_REST_Server::CREATABLE,
149 'callback' => [ $this, 'sync_from_library' ],
150 'args' => [
151 'id' => [
152 'required' => true,
153 'type' => 'number',
154 ],
155 ],
156 'permission_callback' => function () {
157 return current_user_can( 'edit_others_posts' );
158 },
159 ],
160 ]
161 );
162 }
163
164 /**
165 * Handles previewing a post from a cloud library.
166 *
167 * @param object $request
168 * @return array
169 */
170 public function preview_library_post( $request ) {
171 global $wpdb;
172
173 $data = $request->get_param( 'item' );
174 $item = $data ? json_decode( $data ) : null;
175
176 if ( ! $item ) {
177 return rest_ensure_response(
178 [
179 'error' => true,
180 ]
181 );
182 }
183
184 $meta = $wpdb->get_row(
185 $wpdb->prepare(
186 "SELECT * FROM $wpdb->postmeta
187 WHERE meta_key = '_fl_asst_preview_library_item_id'
188 AND meta_value = %s",
189 $item->id
190 )
191 );
192
193 if ( $meta ) {
194 $request->set_param( 'id', $meta->post_id );
195 $response = $this->sync_from_library( $request );
196 } else {
197 $response = $this->import_from_library( $request );
198 }
199
200 if ( isset( $response->data['error'] ) ) {
201 return $response;
202 }
203
204 $post_id = $response->data['id'];
205
206 wp_update_post(
207 [
208 'ID' => $post_id,
209 'post_status' => 'auto-draft',
210 ]
211 );
212
213 update_post_meta( $post_id, '_fl_asst_preview_library_item_id', $item->id );
214
215 $this->replace_attachment_urls_with_cloud_urls( $item, $post_id );
216
217 return rest_ensure_response(
218 [
219 'url' => PreviewHelper::get_post_preview_url( $post_id ),
220 ]
221 );
222 }
223
224 /**
225 * Gets the data for saving to a library or updating a library item.
226 *
227 * @param object $request
228 * @param object $post
229 * @return array
230 */
231 public function get_save_data( $request, $post ) {
232 $data = [
233 'name' => $post->post_title,
234 'type' => 'post',
235 'post_data' => [
236 'post' => [
237 'comment_status' => $post->comment_status,
238 'menu_order' => $post->menu_order,
239 'ping_status' => $post->ping_status,
240 'post_content' => $post->post_content,
241 'post_excerpt' => $post->post_excerpt,
242 'post_mime_type' => $post->post_mime_type,
243 'post_name' => $post->post_name,
244 'post_title' => $post->post_title,
245 'post_type' => $post->post_type,
246 ],
247 'meta' => get_post_meta( $post->ID ),
248 'terms' => $this->get_post_terms( $post ),
249
250 ],
251 'media' => [
252 'attachments' => $this->get_post_image_paths( $post ),
253 ],
254 'screenshot' => $this->get_post_screenshot( $request, $post ),
255 ];
256
257 $thumbnail = get_attached_file( get_post_thumbnail_id( $post ) );
258
259 if ($thumbnail) {
260 $data['media']['thumb'] = $thumbnail;
261 }
262
263 return $data;
264 }
265
266 /**
267 * Saves a post to a cloud library.
268 *
269 * @param object $request
270 * @return array
271 */
272 public function save_to_library( $request ) {
273 $id = $request->get_param( 'id' );
274 $library_id = $request->get_param( 'library_id' );
275 $post = get_post( $id );
276 $client = new CloudClient;
277
278 $response = $client->libraries->create_item(
279 $library_id,
280 $this->get_save_data( $request, $post )
281 );
282
283 if (isset($response->success) && $response->success === false) {
284 return new \WP_Error( 'API Error', $response->message, [ 'status' => 400 ] );
285 }
286
287 return $response;
288 }
289
290 /**
291 * Replaces a library post with a post on this site.
292 *
293 * @param object $request
294 * @return array
295 */
296 public function sync_to_library( $request ) {
297 $id = $request->get_param( 'id' );
298 $item_id = $request->get_param( 'item_id' );
299 $post = get_post( $id );
300 $client = new CloudClient;
301 $data = $this->get_save_data( $request, $post );
302
303 $response = $client->libraries->update_item(
304 $item_id,
305 $data
306 );
307
308 if (isset($response->success) && $response->success === false) {
309 return new \WP_Error( 'API Error', $response->message, [ 'status' => 400 ] );
310 }
311
312 return $response;
313 }
314
315 /**
316 * Imports a post from a library to the site.
317 *
318 * @param object $request
319 * @return array
320 */
321 public function import_from_library( $request ) {
322 $data = $request->get_param( 'item' );
323 $item = $data ? json_decode( $data ) : null;
324
325 if ( ! $item ) {
326 return rest_ensure_response(
327 [
328 'error' => true,
329 ]
330 );
331 }
332
333 $client = new CloudClient;
334 $item = $client->libraries->get_item( $item->id );
335
336 $registered_post_types = get_post_types();
337
338 if ( ! in_array( $item->data->post->post_type, $registered_post_types ) ) {
339 return rest_ensure_response(
340 [
341 'error' => true,
342 'error_code' => 'post_type_not_registered',
343 'post_type' => $item->data->post->post_type,
344 ]
345 );
346 }
347
348 $post_data = $item->data->post;
349 $meta_data = $item->data->meta;
350 $term_data = $item->data->terms;
351
352 $new_post_id = wp_insert_post(
353 [
354 'comment_status' => $post_data->comment_status,
355 'menu_order' => $post_data->menu_order,
356 'ping_status' => $post_data->ping_status,
357 'post_author' => wp_get_current_user()->ID,
358 'post_content' => $post_data->post_content ? $post_data->post_content : '',
359 'post_excerpt' => $post_data->post_excerpt ? $post_data->post_excerpt : '',
360 'post_mime_type' => $post_data->post_mime_type ? $post_data->post_mime_type : '',
361 'post_name' => $post_data->post_name,
362 'post_status' => 'publish',
363 'post_title' => $post_data->post_title,
364 'post_type' => $post_data->post_type,
365 ]
366 );
367
368 if ( is_wp_error( $new_post_id ) ) {
369 return rest_ensure_response(
370 [
371 'error' => true,
372 ]
373 );
374 }
375
376 $this->import_post_meta_from_library( $new_post_id, $meta_data );
377 $this->import_post_terms_from_library( $new_post_id, $term_data );
378 $this->regenerate_builder_cache( $new_post_id, $item );
379
380 return rest_ensure_response(
381 $this->posts->transform(
382 get_post( $new_post_id )
383 )
384 );
385 }
386
387 /**
388 * Replaces a post on this site with a post from a library.
389 *
390 * @param object $request
391 * @return array
392 */
393 public function sync_from_library( $request ) {
394 $post_id = $request->get_param( 'id' );
395 $data = $request->get_param( 'item' );
396 $item = $data ? json_decode( $data ) : null;
397
398 if ( ! $item ) {
399 return rest_ensure_response(
400 [
401 'error' => true,
402 ]
403 );
404 }
405
406 $client = new CloudClient;
407 $item = $client->libraries->get_item( $item->id );
408 $post_data = $item->data->post;
409 $meta_data = $item->data->meta;
410 $term_data = $item->data->terms;
411
412 $updated = wp_update_post(
413 [
414 'ID' => $post_id,
415 'post_content' => $post_data->post_content,
416 ]
417 );
418
419 if ( is_wp_error( $updated ) ) {
420 return rest_ensure_response(
421 [
422 'error' => true,
423 ]
424 );
425 }
426
427 $this->import_post_meta_from_library( $post_id, $meta_data );
428 $this->import_post_terms_from_library( $post_id, $term_data );
429 $this->regenerate_builder_cache( $post_id, $item );
430
431 return rest_ensure_response(
432 $this->posts->transform(
433 get_post( $post_id )
434 )
435 );
436 }
437
438 /**
439 * Imports meta for a library post to the site.
440 *
441 * @param int $post_id
442 * @param object $meta
443 * @return void
444 */
445 public function import_post_meta_from_library( $post_id, $meta ) {
446 global $wpdb;
447
448 if ( ! $meta || ! is_object( $meta ) ) {
449 return;
450 }
451
452 if ( isset( $meta->_fl_builder_data ) ) {
453 $meta->_fl_builder_draft = $meta->_fl_builder_data;
454 $meta->_fl_builder_draft_settings = $meta->_fl_builder_data_settings;
455 }
456
457 foreach ( $meta as $meta_key => $meta_value ) {
458 if ( metadata_exists( 'post', $post_id, $meta_key ) ) {
459 delete_metadata( 'post', $post_id, $meta_key );
460 }
461 if ( is_array( $meta_value ) && count( $meta_value ) !== 0 ) {
462 foreach ( $meta_value as $value ) {
463 if ( $value !== null ) {
464 $value = addslashes( $value );
465 }
466 // @codingStandardsIgnoreStart
467 $wpdb->query( "INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) values ({$post_id}, '{$meta_key}', '{$value}')" );
468 // @codingStandardsIgnoreEnd
469 }
470 }
471 }
472 }
473
474 /**
475 * Imports terms for a library post to the site.
476 *
477 * @param int $post_id
478 * @param array $terms
479 * @return void
480 */
481 public function import_post_terms_from_library( $post_id, $terms ) {
482 $terms = is_object( $terms ) ? [ $terms ] : $terms;
483
484 if ( ! $terms || ! is_array( $terms ) || 0 === count( $terms ) ) {
485 return;
486 }
487
488 $taxonomies = get_taxonomies( '', 'objects' );
489 $taxonomy_terms = [];
490
491 foreach ( $terms as $term ) {
492 if ( ! isset( $term->name ) || ! isset( $term->taxonomy ) ) {
493 continue;
494 } elseif ( ! taxonomy_exists( $term->taxonomy ) ) {
495 continue;
496 } elseif ( ! isset( $taxonomy_terms ) ) {
497 $taxonomy_terms[ $term->taxonomy ] = [];
498 }
499
500 $existing_term = term_exists( $term->slug, $term->taxonomy );
501 $is_hierarchical = ! ! $taxonomies[ $term->taxonomy ]->hierarchical;
502
503 if ( is_array( $existing_term ) ) {
504 $term_id = $is_hierarchical ? $existing_term['term_taxonomy_id'] : $term->name;
505 } else {
506 $new_term = wp_insert_term(
507 $term->name,
508 $term->taxonomy,
509 [
510 'description' => $term->description,
511 'slug' => $term->slug,
512 ]
513 );
514 $term_id = $is_hierarchical ? $new_term['term_taxonomy_id'] : $term->name;
515 }
516
517 $taxonomy_terms[ $term->taxonomy ][] = $term_id;
518 }
519
520 foreach ( $taxonomy_terms as $taxonomy => $terms ) {
521 wp_delete_object_term_relationships( $post_id, $taxonomy );
522 wp_set_post_terms( $post_id, $terms, $taxonomy, true );
523 }
524 }
525
526 /**
527 * Returns an array of all terms for a post.
528 *
529 * @param object $post
530 * @return array
531 */
532 public function get_post_terms( $post ) {
533 $taxonomies = get_taxonomies( '', 'names' );
534 $object_terms = wp_get_object_terms( $post->ID, $taxonomies );
535 $terms = [];
536
537 foreach ( $object_terms as $term ) {
538 $terms[] = [
539 'description' => $term->description,
540 'name' => $term->name,
541 'slug' => $term->slug,
542 'taxonomy' => $term->taxonomy,
543 ];
544 }
545
546 return $terms;
547 }
548
549 /**
550 * Returns the screenshot data for a post.
551 *
552 * @param object $request
553 * @param object $post
554 * @return array
555 */
556 public function get_post_screenshot( $request, $post ) {
557 $url = PreviewHelper::get_post_preview_url( $post );
558 $url = add_query_arg( 'fl_asst_screenshot', '1', $url );
559 return ScreenshotHelper::get_for_rest_request( $request, $url );
560 }
561
562 /**
563 * Imports the featured image for a post.
564 *
565 * @param object $request
566 * @return array
567 */
568 public function import_post_thumb_from_library( $request ) {
569 $post_id = $request->get_param( 'post_id' );
570 $thumb = $request->get_param( 'thumb' );
571 $service = new MediaLibraryService();
572
573 if ( ! preg_match( '/screenshot\.(png|jpg|gif)/', $thumb['file_name'] ) ) {
574 $response = $service->import_cloud_media( $thumb, $post_id );
575 set_post_thumbnail( $post_id, $response['id'] );
576 }
577
578 return [ 'success' => true ];
579 }
580
581 /**
582 * Imports a media item for a post.
583 *
584 * @param object $request
585 * @return array
586 */
587 public function import_post_media_from_library( $request ) {
588 $post_id = $request->get_param( 'post_id' );
589 $media = $request->get_param( 'media' );
590 $service = new MediaLibraryService();
591
592 $imported = [];
593 $response = $service->import_cloud_media( $media, $post_id );
594 $imported[ $media['file_name'] ] = wp_get_attachment_metadata( $response['id'] );
595 $imported[ $media['file_name'] ]['id'] = $response['id'];
596
597 $this->replace_imported_attachment_urls_in_content( $post_id, $imported );
598 $this->replace_imported_attachment_urls_in_meta( $post_id, $imported );
599
600 return [ 'success' => true ];
601 }
602
603 /**
604 * Replace attachment urls with urls from the cloud.
605 *
606 * @param object $item
607 * @param int $post_id
608 * @return void
609 */
610 public function replace_attachment_urls_with_cloud_urls( $item, $post_id ) {
611 if ( isset( $item->media->attachments ) ) {
612 $imported = [];
613
614 foreach ( $item->media->attachments as $attachment ) {
615 $imported[ $attachment->file_name ] = $attachment;
616 }
617
618 $this->replace_imported_attachment_urls_in_content( $post_id, $imported );
619 $this->replace_imported_attachment_urls_in_meta( $post_id, $imported );
620 }
621 }
622
623 /**
624 * Replaces the imported attachment urls in post content.
625 *
626 * @param int $post_id
627 * @param array $imported
628 * @return void
629 */
630 public function replace_imported_attachment_urls_in_content( $post_id, $imported ) {
631 $content = get_post_field( 'post_content', $post_id );
632 $content = MediaPathHelper::replace_imported_attachment_urls_in_string( $content, $imported );
633
634 wp_update_post(
635 [
636 'ID' => $post_id,
637 'post_content' => $content,
638 ]
639 );
640 }
641
642 /**
643 * Replaces the imported attachment urls in post meta.
644 *
645 * @param int $post_id
646 * @param array $imported
647 * @return void
648 */
649 public function replace_imported_attachment_urls_in_meta( $post_id, $imported ) {
650 $meta = get_post_meta( $post_id );
651
652 foreach ( $meta as $key => $val ) {
653 $val = maybe_unserialize( $val[0] );
654
655 if ( is_object( $val ) || is_array( $val ) ) {
656 $val = MediaPathHelper::replace_imported_attachment_urls_in_data( $val, $imported );
657 } elseif ( JsonHelper::is_string_json( $val ) ) {
658 $val = json_decode( $val );
659 $val = MediaPathHelper::replace_imported_attachment_urls_in_data( $val, $imported );
660 $val = wp_slash( json_encode( $val ) );
661 } else {
662 $val = MediaPathHelper::replace_imported_attachment_urls_in_string( $val, $imported );
663 }
664
665 update_post_meta( $post_id, $key, $val );
666 }
667 }
668
669 /**
670 * Get the server paths to all images associated with a post.
671 *
672 * @param object $post
673 * @return array
674 */
675 public function get_post_image_paths( $post ) {
676 $content_paths = MediaPathHelper::get_image_paths_from_string( $post->post_content );
677 $meta = get_post_meta( $post->ID );
678 $meta_paths = [];
679
680 if ( $meta && count( $meta ) > 0 ) {
681 $meta_paths = MediaPathHelper::get_image_paths_from_data( $meta );
682 }
683
684 return array_unique( array_merge( $content_paths, $meta_paths ) );
685 }
686
687 /**
688 * Regenerate the asset cache for posts created with a builder.
689 *
690 * @param object $item
691 * @return void
692 */
693 public function regenerate_builder_cache( $post_id, $item ) {
694 $meta = (array) $item->data->meta;
695
696 if ( isset( $meta['_fl_builder_data'] ) && class_exists( 'FLBuilderModel' ) ) {
697 \FLBuilderModel::delete_all_asset_cache( $post_id );
698 }
699 if ( isset( $meta['_elementor_data'] ) && class_exists( 'Elementor\Plugin' ) ) {
700 \Elementor\Plugin::$instance->files_manager->clear_cache();
701 }
702 }
703 }
704