PluginProbe
Elementor Website Builder – more than just a page builder / 3.31.2
Elementor Website Builder – more than just a page builder v3.31.2
4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 All 452 releases
← All changes | includes/template-library/manager.php +227 -164 4.0.83.31.2 View file →
@@ -2,12 +2,15 @@
2 2 namespace Elementor\TemplateLibrary;
3 3
4 4 use Elementor\Api;
5 5 use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
6 +use Elementor\Core\Isolation\Wordpress_Adapter;
7 +use Elementor\Core\Isolation\Wordpress_Adapter_Interface;
8 +use Elementor\Core\Isolation\Elementor_Adapter;
9 +use Elementor\Core\Isolation\Elementor_Adapter_Interface;
6 10 use Elementor\Core\Settings\Manager as SettingsManager;
7 11 use Elementor\Includes\TemplateLibrary\Data\Controller;
8 12 use Elementor\TemplateLibrary\Classes\Import_Images;
9 -use Elementor\Core\Utils\Template_Library_Import_Export_Utils;
10 13 use Elementor\Plugin;
11 14 use Elementor\User;
12 15 use Elementor\Utils;
13 16
@@ -24,11 +27,8 @@
24 27 * @since 1.0.0
25 28 */
26 29 class Manager {
27 30
28 - const ERROR_TEMPLATE_SOURCE_NOT_FOUND = 'Template source not found.';
29 - const ERROR_TEMPLATE_IDS_MISSING = 'Template IDs are missing.';
30 -
31 31 /**
32 32 * Registered template sources.
33 33 *
34 34 * Holds a list of all the supported sources with their instances.
@@ -50,8 +50,18 @@
50 50 */
51 51 private $_import_images = null; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
52 52
53 53 /**
54 + * @var Wordpress_Adapter_Interface
55 + */
56 + protected $wordpress_adapter = null;
57 +
58 + /**
59 + * @var Elementor_Adapter_Interface
60 + */
61 + protected $elementor_adapter = null;
62 +
63 + /**
54 64 * Template library manager constructor.
55 65 *
56 66 * Initializing the template library manager by registering default template
57 67 * sources and initializing ajax calls.
@@ -93,8 +103,16 @@
93 103
94 104 return $this->_import_images;
95 105 }
96 106
107 + public function set_wordpress_adapter( Wordpress_Adapter_Interface $wordpress_adapter ) {
108 + $this->wordpress_adapter = $wordpress_adapter;
109 + }
110 +
111 + public function set_elementor_adapter( Elementor_Adapter_Interface $elementor_adapter ): void {
112 + $this->elementor_adapter = $elementor_adapter;
113 + }
114 +
97 115 /**
98 116 * Register template source.
99 117 *
100 118 * Used to register new template sources displayed in the template library.
@@ -220,12 +238,10 @@
220 238 *
221 239 * @return array Library data.
222 240 */
223 241 public function get_library_data( array $args ) {
224 - $force_update = ! empty( $args['sync'] );
242 + $library_data = Api::get_library_data( ! empty( $args['sync'] ) );
225 243
226 - $library_data = Api::get_library_data( $force_update );
227 -
228 244 if ( empty( $library_data ) ) {
229 245 return $library_data;
230 246 }
231 247
@@ -232,21 +248,14 @@
232 248 // Ensure all document are registered.
233 249 Plugin::$instance->documents->get_document_types();
234 250
235 251 $filter_sources = ! empty( $args['filter_sources'] ) ? $args['filter_sources'] : [];
252 + $force_update = ! empty( $args['sync'] );
236 253
237 - $full_library_data = [
254 + return [
238 255 'templates' => $this->get_templates( $filter_sources, $force_update ),
239 256 'config' => $library_data['types_data'],
240 257 ];
241 -
242 - /**
243 - * Filter the full library data.
244 - *
245 - * @since 3.32.2
246 - * @param-out $full_library_data - 'templates' and 'config' data ('config' holds the list of categories).
247 - */
248 - return apply_filters( 'elementor/library/full-data', $full_library_data );
249 258 }
250 259
251 260 /**
252 261 * Save template.
@@ -282,9 +291,9 @@
282 291 private function save_template_item( array $args ) {
283 292 $source = $this->get_source( $args['source'] );
284 293
285 294 if ( ! $source ) {
286 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
295 + return new \WP_Error( 'template_error', 'Template source not found.' );
287 296 }
288 297
289 298 $args['content'] = json_decode( $args['content'], true );
290 299
@@ -331,9 +340,9 @@
331 340
332 341 $source = $this->get_source( $args['source'] );
333 342
334 343 if ( ! $source ) {
335 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
344 + return new \WP_Error( 'template_error', 'Template source not found.' );
336 345 }
337 346
338 347 if ( $this->is_action_to_same_source( $args ) ) {
339 348 return $source->move_template_to_folder( $args );
@@ -338,16 +347,16 @@
338 347 if ( $this->is_action_to_same_source( $args ) ) {
339 348 return $source->move_template_to_folder( $args );
340 349 }
341 350
342 - $from_source = $this->get_source( $args['from_source'] );
351 + if ( 'local' === $args['from_source'] ) {
352 + $args = $this->format_args_for_single_action_from_local_to_cloud( $args );
353 + }
343 354
344 - if ( ! $from_source ) {
345 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
355 + if ( 'cloud' === $args['from_source'] ) {
356 + $args = $this->format_args_for_single_action_from_cloud_to_local( $args );
346 357 }
347 358
348 - $args = $from_source->format_args_for_single_action( $args );
349 -
350 359 $template_id = $source->save_item( $args );
351 360
352 361 if ( is_wp_error( $template_id ) ) {
353 362 return $template_id;
@@ -365,19 +374,19 @@
365 374
366 375 $source = $this->get_source( $args['source'][0] );
367 376
368 377 if ( ! $source ) {
369 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
378 + return new \WP_Error( 'template_error', 'Template source not found.' );
370 379 }
371 380
372 - $from_source = $this->get_source( $args['from_source'] );
381 + if ( 'local' === $args['from_source'] ) {
382 + $args = $this->format_args_for_single_action_from_local_to_cloud( $args );
383 + }
373 384
374 - if ( ! $from_source ) {
375 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
385 + if ( 'cloud' === $args['from_source'] ) {
386 + $args = $this->format_args_for_single_action_from_cloud_to_local( $args );
376 387 }
377 388
378 - $args = $from_source->format_args_for_single_action( $args );
379 -
380 389 $template_id = $source->save_item( $args );
381 390
382 391 if ( is_wp_error( $template_id ) ) {
383 392 return $template_id;
@@ -389,8 +398,53 @@
389 398 private function is_action_to_same_source( $args ) {
390 399 return $args['source'] === $args['from_source'];
391 400 }
392 401
402 + private function format_args_for_single_action_from_local_to_cloud( $args ) {
403 + if ( ! $this->is_allowed_to_read_template( [
404 + 'source' => $args['from_source'],
405 + 'template_id' => $args['from_template_id'],
406 + ] ) ) {
407 + return new \WP_Error(
408 + 'template_error',
409 + esc_html__( 'You do not have permission to access this template.', 'elementor' )
410 + );
411 + }
412 +
413 + $document = Plugin::$instance->documents->get( $args['from_template_id'] );
414 +
415 + if ( ! $document ) {
416 + return new \WP_Error( 'template_error', 'Document not found.' );
417 + }
418 +
419 + $args['content'] = $document->get_elements_data();
420 +
421 + $page = SettingsManager::get_settings_managers( 'page' )->get_model( $args['from_template_id'] );
422 + $args['page_settings'] = $page->get_data( 'settings' );
423 +
424 + return $args;
425 + }
426 +
427 + private function format_args_for_single_action_from_cloud_to_local( $args ) {
428 + $from_source = $this->get_source( $args['from_source'] );
429 +
430 + if ( ! $from_source ) {
431 + return new \WP_Error( 'template_error', 'Template source not found.' );
432 + }
433 +
434 + $data = $from_source->get_item( $args['from_template_id'] );
435 +
436 + if ( is_wp_error( $data ) || empty( $data['content'] ) ) {
437 + return new \WP_Error( 'template_error', 'Unable to format template args.' );
438 + }
439 +
440 + $decoded_data = json_decode( $data['content'], true );
441 + $args['content'] = $decoded_data['content'];
442 + $args['page_settings'] = $decoded_data['page_settings'];
443 +
444 + return $args;
445 + }
446 +
393 447 /**
394 448 * Update template.
395 449 *
396 450 * Update template on the database.
@@ -412,9 +466,9 @@
412 466
413 467 $source = $this->get_source( $template_data['source'] );
414 468
415 469 if ( ! $source ) {
416 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
470 + return new \WP_Error( 'template_error', 'Template source not found.' );
417 471 }
418 472
419 473 $template_data['content'] = json_decode( $template_data['content'], true );
420 474
@@ -436,9 +490,9 @@
436 490
437 491 $source = $this->get_source( $template_data['source'] );
438 492
439 493 if ( ! $source ) {
440 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
494 + return new \WP_Error( 'template_error', 'Template source not found.' );
441 495 }
442 496
443 497 $update = $source->update_item( $template_data );
444 498
@@ -491,15 +545,9 @@
491 545 if ( is_wp_error( $validate_args ) ) {
492 546 return $validate_args;
493 547 }
494 548
495 - $source = $this->get_source( $args['source'] );
496 -
497 - if ( ! $source ) {
498 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
499 - }
500 -
501 - if ( method_exists( $source, 'is_allowed_to_read_template' ) && ! $source->is_allowed_to_read_template( $args ) ) {
549 + if ( ! $this->is_allowed_to_read_template( $args ) ) {
502 550 return new \WP_Error(
503 551 'template_error',
504 552 esc_html__( 'You do not have permission to access this template.', 'elementor' )
505 553 );
@@ -508,8 +556,14 @@
508 556 if ( isset( $args['edit_mode'] ) ) {
509 557 Plugin::$instance->editor->set_edit_mode( $args['edit_mode'] );
510 558 }
511 559
560 + $source = $this->get_source( $args['source'] );
561 +
562 + if ( ! $source ) {
563 + return new \WP_Error( 'template_error', 'Template source not found.' );
564 + }
565 +
512 566 do_action( 'elementor/template-library/before_get_source_data', $args, $source );
513 567
514 568 $data = $source->get_data( $args );
515 569
@@ -540,9 +594,9 @@
540 594
541 595 $source = $this->get_source( $args['source'] );
542 596
543 597 if ( ! $source ) {
544 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
598 + return new \WP_Error( 'template_error', 'Template source not found.' );
545 599 }
546 600
547 601 return $source->delete_template( $args['template_id'] );
548 602 }
@@ -569,9 +623,9 @@
569 623
570 624 $source = $this->get_source( $args['source'] );
571 625
572 626 if ( ! $source ) {
573 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
627 + return new \WP_Error( 'template_error', 'Template source not found' );
574 628 }
575 629
576 630 return $source->export_template( $args['template_id'] );
577 631 }
@@ -610,15 +664,16 @@
610 664 remove_filter( 'elementor/files/allow-file-type/json', [ $this, 'enable_json_template_upload' ] );
611 665 remove_filter( 'elementor/files/allow_unfiltered_upload', [ $this, 'enable_json_template_upload' ] );
612 666
613 667 if ( is_wp_error( $upload_result ) ) {
668 + Plugin::$instance->uploads_manager->remove_file_or_dir( dirname( $upload_result['tmp_name'] ) );
669 +
614 670 return $upload_result;
615 671 }
616 672
617 673 $source = $this->get_source( $data['source'] ?? 'local' );
618 674
619 - $import_mode = $data['import_mode'] ?? 'match_site';
620 - $import_result = $source->import_template( $upload_result['name'], $upload_result['tmp_name'], $import_mode );
675 + $import_result = $source->import_template( $upload_result['name'], $upload_result['tmp_name'] );
621 676
622 677 // Remove the temporary directory generated for the stream-uploaded file.
623 678 Plugin::$instance->uploads_manager->remove_file_or_dir( dirname( $upload_result['tmp_name'] ) );
624 679
@@ -681,92 +736,8 @@
681 736
682 737 return $import_data['content'];
683 738 }
684 739
685 - public function process_global_styles( array $args ) {
686 - $validate_args = $this->ensure_args( [ 'content', 'import_mode' ], $args );
687 -
688 - if ( is_wp_error( $validate_args ) ) {
689 - return $validate_args;
690 - }
691 -
692 - $import_mode = Template_Library_Import_Export_Utils::sanitize_import_mode( $args['import_mode'] );
693 -
694 - $content = $this->get_validated_json_arg( $args, 'content' );
695 - if ( is_wp_error( $content ) ) {
696 - return $content;
697 - }
698 -
699 - $global_classes = $this->get_validated_json_arg( $args, 'global_classes', true );
700 - if ( is_wp_error( $global_classes ) ) {
701 - return $global_classes;
702 - }
703 -
704 - $global_variables = $this->get_validated_json_arg( $args, 'global_variables', true );
705 - if ( is_wp_error( $global_variables ) ) {
706 - return $global_variables;
707 - }
708 -
709 - $data = [
710 - 'global_classes' => $global_classes,
711 - 'global_variables' => $global_variables,
712 - ];
713 -
714 - $result = apply_filters(
715 - 'elementor/template_library/import/process_content',
716 - [ 'content' => $content ],
717 - $import_mode,
718 - $data,
719 - null
720 - );
721 -
722 - $response = [
723 - 'content' => $result['content'],
724 - ];
725 -
726 - if ( ! empty( $result['updated_global_classes'] ) ) {
727 - $response['updated_global_classes'] = $result['updated_global_classes'];
728 - }
729 -
730 - if ( ! empty( $result['updated_global_variables'] ) ) {
731 - $response['updated_global_variables'] = $result['updated_global_variables'];
732 - }
733 -
734 - $classes_to_flatten = $result['classes_to_flatten'] ?? [];
735 - $variables_to_flatten = $result['variables_to_flatten'] ?? [];
736 -
737 - if ( ! empty( $classes_to_flatten ) ) {
738 - $response['flattened_classes_count'] = count( $classes_to_flatten );
739 - }
740 -
741 - if ( ! empty( $variables_to_flatten ) ) {
742 - $response['flattened_variables_count'] = count( $variables_to_flatten );
743 - }
744 -
745 - return $response;
746 - }
747 -
748 - private function get_validated_json_arg( array $args, string $key, bool $is_optional = false ) {
749 - if ( ! array_key_exists( $key, $args ) || null === $args[ $key ] || '' === $args[ $key ] ) {
750 - return $is_optional ? null : new \WP_Error( "invalid_$key", "Invalid $key." );
751 - }
752 -
753 - $value = $args[ $key ];
754 - if ( is_string( $value ) ) {
755 - $decoded = json_decode( $value, true );
756 - if ( JSON_ERROR_NONE !== json_last_error() ) {
757 - return new \WP_Error( "invalid_$key", "Invalid JSON $key." );
758 - }
759 - return $decoded;
760 - }
761 -
762 - if ( ! is_array( $value ) ) {
763 - return new \WP_Error( "invalid_$key", "Invalid $key format." );
764 - }
765 -
766 - return $value;
767 - }
768 -
769 740 public function get_item_children( array $args ) {
770 741 $validate_args = $this->ensure_args( [ 'source', 'template_id' ], $args );
771 742
772 743 if ( is_wp_error( $validate_args ) ) {
@@ -775,9 +746,9 @@
775 746
776 747 $source = $this->get_source( $args['source'] );
777 748
778 749 if ( ! $source ) {
779 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
750 + return new \WP_Error( 'template_error', 'Template source not found.' );
780 751 }
781 752
782 753 return $source->get_item_children( $args );
783 754 }
@@ -791,9 +762,9 @@
791 762
792 763 $source = $this->get_source( $args['source'] );
793 764
794 765 if ( ! $source ) {
795 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
766 + return new \WP_Error( 'template_error', 'Template source not found.' );
796 767 }
797 768
798 769 return $source->search_templates( $args );
799 770 }
@@ -807,9 +778,9 @@
807 778
808 779 $source = $this->get_source( $args['source'] );
809 780
810 781 if ( ! $source ) {
811 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
782 + return new \WP_Error( 'template_error', 'Template source not found.' );
812 783 }
813 784
814 785 return $source->get_items( $args );
815 786 }
@@ -823,9 +794,9 @@
823 794
824 795 $source = $this->get_source( $args['source'] );
825 796
826 797 if ( ! $source ) {
827 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
798 + return new \WP_Error( 'template_error', 'Template source not found.' );
828 799 }
829 800
830 801 return $source->save_folder( $args );
831 802 }
@@ -860,11 +831,14 @@
860 831 private function register_default_sources() {
861 832 $sources = [
862 833 'local',
863 834 'remote',
864 - 'cloud',
865 835 ];
866 836
837 + if ( Plugin::$instance->experiments->is_feature_active( 'cloud-library' ) ) {
838 + $sources[] = 'cloud';
839 + }
840 +
867 841 foreach ( $sources as $source_filename ) {
868 842 $class_name = ucwords( $source_filename );
869 843 $class_name = str_replace( '-', '_', $class_name );
870 844
@@ -884,9 +858,9 @@
884 858 *
885 859 * @param array $data
886 860 *
887 861 * @return mixed
888 - * @throws \Exception If current user has no permission or the post is not found.
862 + * @throws \Exception If the user has no permission or the post is not found.
889 863 */
890 864 private function handle_ajax_request( $ajax_request, array $data ) {
891 865 if ( ! User::is_current_user_can_edit_post_type( Source_Local::CPT ) ) {
892 866 throw new \Exception( 'Access denied.' );
@@ -907,13 +881,13 @@
907 881 if ( is_wp_error( $result ) ) {
908 882 throw new \Exception( esc_html( $result->get_error_message() ) );
909 883 }
910 884
911 - return $result;
885 + return $result; // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
912 886 }
913 887
914 888 /**
915 - * @throws \Exception If template import fails, file validation errors occur, or processing encounters issues.
889 + * @throws \Exception
916 890 */
917 891 public function save_template_screenshot( $data ): string {
918 892 $validate_args = $this->ensure_args( [ 'template_id', 'screenshot' ], $data );
919 893
@@ -926,9 +900,9 @@
926 900 return $this->get_source( 'cloud' )->save_item_preview( $data['template_id'], $raw_binary );
927 901 }
928 902
929 903 /**
930 - * @throws \Exception If template processing fails or data validation errors occur.
904 + * @throws \Exception
931 905 */
932 906 public function template_screenshot_failed( $data ): string {
933 907 $validate_args = $this->ensure_args( [ 'template_id' ], $data );
934 908
@@ -948,13 +922,13 @@
948 922
949 923 $source = $this->get_source( $data['source'] );
950 924
951 925 if ( ! $source ) {
952 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
926 + return new \WP_Error( 'template_error', 'Template source not found.' );
953 927 }
954 928
955 929 if ( empty( $data['template_ids'] ) || ! is_array( $data['template_ids'] ) ) {
956 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_IDS_MISSING );
930 + return new \WP_Error( 'template_error', 'Template IDs are missing.' );
957 931 }
958 932
959 933 return $source->bulk_delete_items( $data['template_ids'] );
960 934 }
@@ -968,13 +942,13 @@
968 942
969 943 $source = $this->get_source( $data['source'] );
970 944
971 945 if ( ! $source ) {
972 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
946 + return new \WP_Error( 'template_error', 'Template source not found.' );
973 947 }
974 948
975 949 if ( empty( $data['template_ids'] ) || ! is_array( $data['template_ids'] ) ) {
976 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_IDS_MISSING );
950 + return new \WP_Error( 'template_error', 'Template IDs are missing.' );
977 951 }
978 952
979 953 return $source->bulk_undo_delete_items( $data['template_ids'] );
980 954 }
@@ -1013,9 +987,8 @@
1013 987 'bulk_copy_templates',
1014 988 'bulk_undo_delete_items',
1015 989 'get_templates_quota',
1016 990 'template_screenshot_failed',
1017 - 'process_global_styles',
1018 991 ];
1019 992
1020 993 foreach ( $library_ajax_requests as $ajax_request ) {
1021 994 $ajax->register_ajax_action( $ajax_request, function( $data ) use ( $ajax_request ) {
@@ -1116,8 +1089,46 @@
1116 1089
1117 1090 return true;
1118 1091 }
1119 1092
1093 + private function is_allowed_to_read_template( array $args ): bool {
1094 + if ( 'remote' === $args['source'] || 'cloud' === $args['source'] ) {
1095 + return true;
1096 + }
1097 +
1098 + if ( null === $this->wordpress_adapter ) {
1099 + $this->set_wordpress_adapter( new WordPress_Adapter() );
1100 + }
1101 +
1102 + if ( ! $this->should_check_permissions( $args ) ) {
1103 + return true;
1104 + }
1105 +
1106 + $post_id = intval( $args['template_id'] );
1107 + $post_status = $this->wordpress_adapter->get_post_status( $post_id );
1108 + $is_private_or_non_published = ( 'private' === $post_status && ! $this->wordpress_adapter->current_user_can( 'read_private_posts', $post_id ) ) || ( 'publish' !== $post_status );
1109 +
1110 + $can_read_template = $is_private_or_non_published || $this->wordpress_adapter->current_user_can( 'edit_post', $post_id );
1111 +
1112 + return apply_filters( 'elementor/template-library/is_allowed_to_read_template', $can_read_template, $args );
1113 + }
1114 +
1115 + private function should_check_permissions( array $args ): bool {
1116 + if ( null === $this->elementor_adapter ) {
1117 + $this->set_elementor_adapter( new Elementor_Adapter() );
1118 + }
1119 +
1120 + // TODO: Remove $isWidgetTemplate in 3.28.0 as there is a Pro dependency
1121 + $check_permissions = isset( $args['check_permissions'] ) && false === $args['check_permissions'];
1122 + $is_widget_template = 'widget' === $this->elementor_adapter->get_template_type( $args['template_id'] );
1123 +
1124 + if ( $check_permissions || $is_widget_template ) {
1125 + return false;
1126 + }
1127 +
1128 + return true;
1129 + }
1130 +
1120 1131 public function bulk_move_templates( array $args ) {
1121 1132 $validate_args = $this->ensure_args( [ 'source', 'from_source', 'from_template_id' ], $args );
1122 1133
1123 1134 if ( is_wp_error( $validate_args ) ) {
@@ -1132,9 +1143,9 @@
1132 1143 private function bulk_move_template_items( array $args ) {
1133 1144 $source = $this->get_source( $args['source'] );
1134 1145
1135 1146 if ( ! $source ) {
1136 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
1147 + return new \WP_Error( 'template_error', 'Template source not found.' );
1137 1148 }
1138 1149
1139 1150 if ( $this->is_action_to_same_source( $args ) ) {
1140 1151 return $source->move_bulk_templates_to_folder( $args );
@@ -1139,24 +1150,20 @@
1139 1150 if ( $this->is_action_to_same_source( $args ) ) {
1140 1151 return $source->move_bulk_templates_to_folder( $args );
1141 1152 }
1142 1153
1143 - $from_source = $this->get_source( $args['from_source'] );
1154 + $bulk_args = 'local' === $args['from_source']
1155 + ? $this->format_args_for_bulk_action_from_local( $args )
1156 + : $this->format_args_for_bulk_action_from_cloud( $args );
1144 1157
1145 - if ( ! $from_source ) {
1146 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
1147 - }
1148 -
1149 - $bulk_args = $from_source->format_args_for_bulk_action( $args );
1150 -
1151 1158 if ( $source->supports_quota() && ! $this->is_action_to_same_source( $args ) ) {
1152 - $quota_validation = $source->validate_quota( $bulk_args );
1159 + $is_quota_valid = $source->validate_quota( $bulk_args );
1153 1160
1154 - if ( is_wp_error( $quota_validation ) ) {
1155 - return $quota_validation;
1161 + if ( is_wp_error( $is_quota_valid ) ) {
1162 + return $is_quota_valid;
1156 1163 }
1157 1164
1158 - if ( false === $quota_validation ) {
1165 + if ( ! $is_quota_valid ) {
1159 1166 return new \WP_Error( 'quota_error', 'The moving failed because it will pass the maximum templates you can save.' );
1160 1167 }
1161 1168 }
1162 1169
@@ -1171,8 +1178,68 @@
1171 1178
1172 1179 return $bulk_save;
1173 1180 }
1174 1181
1182 + private function format_args_for_bulk_action_from_local( $args ) {
1183 + $bulk_args = [];
1184 +
1185 + foreach ( $args['from_template_id'] as $from_template_id ) {
1186 + if ( ! $this->is_allowed_to_read_template( [
1187 + 'source' => $args['from_source'],
1188 + 'template_id' => $from_template_id,
1189 + ] ) ) {
1190 + continue;
1191 + }
1192 +
1193 + $document = Plugin::$instance->documents->get( $from_template_id );
1194 +
1195 + if ( ! $document ) {
1196 + continue;
1197 + }
1198 +
1199 + $page = SettingsManager::get_settings_managers( 'page' )->get_model( $from_template_id );
1200 +
1201 + $bulk_args[] = array_merge(
1202 + $args,
1203 + [
1204 + 'title' => $document->get_post()->post_title,
1205 + 'type' => $document::get_type(),
1206 + 'content' => $document->get_elements_data(),
1207 + 'page_settings' => $page->get_data( 'settings' ),
1208 + ]
1209 + );
1210 + }
1211 +
1212 + return $bulk_args;
1213 + }
1214 +
1215 + private function format_args_for_bulk_action_from_cloud( $args ) {
1216 + $from_source = $this->get_source( $args['from_source'] );
1217 +
1218 + if ( ! $from_source ) {
1219 + return new \WP_Error( 'template_error', 'Template source not found.' );
1220 + }
1221 +
1222 + $templates = $from_source->get_bulk_items( $args );
1223 + $bulk_args = [];
1224 +
1225 + foreach ( $templates as $template ) {
1226 + $content = json_decode( $template['content'], true );
1227 +
1228 + $bulk_args[] = array_merge(
1229 + $args,
1230 + [
1231 + 'title' => $template['title'],
1232 + 'type' => $template['type'],
1233 + 'content' => $content['content'],
1234 + 'page_settings' => $content['page_settings'],
1235 + ]
1236 + );
1237 + }
1238 +
1239 + return $bulk_args;
1240 + }
1241 +
1175 1242 public function bulk_copy_templates( array $args ) {
1176 1243 $validate_args = $this->ensure_args( [ 'source', 'from_source', 'from_template_id' ], $args );
1177 1244
1178 1245 if ( is_wp_error( $validate_args ) ) {
@@ -1187,27 +1254,23 @@
1187 1254 private function bulk_copy_template_items( array $args ) {
1188 1255 $source = $this->get_source( $args['source'] );
1189 1256
1190 1257 if ( ! $source ) {
1191 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
1258 + return new \WP_Error( 'template_error', 'Template source not found.' );
1192 1259 }
1193 1260
1194 - $from_source = $this->get_source( $args['from_source'] );
1261 + $bulk_args = 'local' === $args['from_source']
1262 + ? $this->format_args_for_bulk_action_from_local( $args )
1263 + : $this->format_args_for_bulk_action_from_cloud( $args );
1195 1264
1196 - if ( ! $from_source ) {
1197 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
1198 - }
1199 -
1200 - $bulk_args = $from_source->format_args_for_bulk_action( $args );
1201 -
1202 1265 if ( $source->supports_quota() && ! $this->is_action_to_same_source( $args ) ) {
1203 - $quota_validation = $source->validate_quota( $bulk_args );
1266 + $is_quota_valid = $source->validate_quota( $bulk_args );
1204 1267
1205 - if ( is_wp_error( $quota_validation ) ) {
1206 - return $quota_validation;
1268 + if ( is_wp_error( $is_quota_valid ) ) {
1269 + return $is_quota_valid;
1207 1270 }
1208 1271
1209 - if ( false === $quota_validation ) {
1272 + if ( ! $is_quota_valid ) {
1210 1273 return new \WP_Error( 'quota_error', 'The copying failed because it will pass the maximum templates you can save.' );
1211 1274 }
1212 1275 }
1213 1276