PluginProbe
Elementor Website Builder – more than just a page builder / 3.0.2
Elementor Website Builder – more than just a page builder v3.0.2
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 4.0.7 All 451 releases
← All changes | includes/template-library/manager.php +58 -636 4.2.33.0.2 View file →
@@ -3,14 +3,11 @@
3 3
4 4 use Elementor\Api;
5 5 use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
6 6 use Elementor\Core\Settings\Manager as SettingsManager;
7 -use Elementor\Includes\TemplateLibrary\Data\Controller;
8 7 use Elementor\TemplateLibrary\Classes\Import_Images;
9 -use Elementor\Core\Utils\Template_Library_Import_Export_Utils;
10 8 use Elementor\Plugin;
11 9 use Elementor\User;
12 -use Elementor\Utils;
13 10
14 11 if ( ! defined( 'ABSPATH' ) ) {
15 12 exit; // Exit if accessed directly.
16 13 }
@@ -24,12 +21,8 @@
24 21 * @since 1.0.0
25 22 */
26 23 class Manager {
27 24
28 - const ERROR_TEMPLATE_SOURCE_NOT_FOUND = 'Template source not found.';
29 - const ERROR_TEMPLATE_IDS_MISSING = 'Template IDs are missing.';
30 - const ERROR_JSON_UPLOAD_NOT_ALLOWED = 'Uploading JSON files is not allowed for this user.';
31 -
32 25 /**
33 26 * Registered template sources.
34 27 *
35 28 * Holds a list of all the supported sources with their instances.
@@ -37,9 +30,9 @@
37 30 * @access protected
38 31 *
39 32 * @var Source_Base[]
40 33 */
41 - protected $_registered_sources = []; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
34 + protected $_registered_sources = [];
42 35
43 36 /**
44 37 * Imported template images.
45 38 *
@@ -48,9 +41,9 @@
48 41 * @access private
49 42 *
50 43 * @var Import_Images
51 44 */
52 - private $_import_images = null; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
45 + private $_import_images = null;
53 46
54 47 /**
55 48 * Template library manager constructor.
56 49 *
@@ -60,10 +53,8 @@
60 53 * @since 1.0.0
61 54 * @access public
62 55 */
63 56 public function __construct() {
64 - Plugin::$instance->data_manager_v2->register_controller( new Controller() );
65 -
66 57 $this->register_default_sources();
67 58
68 59 $this->add_actions();
69 60 }
@@ -74,8 +65,25 @@
74 65 */
75 66 public function add_actions() {
76 67 add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_actions' ] );
77 68 add_action( 'wp_ajax_elementor_library_direct_actions', [ $this, 'handle_direct_actions' ] );
69 +
70 + // TODO: bc since 2.3.0
71 + add_action( 'wp_ajax_elementor_update_templates', function() {
72 + if ( ! isset( $_POST['templates'] ) ) {
73 + return;
74 + }
75 +
76 + foreach ( $_POST['templates'] as & $template ) {
77 + if ( ! isset( $template['content'] ) ) {
78 + return;
79 + }
80 +
81 + $template['content'] = stripslashes( $template['content'] );
82 + }
83 +
84 + wp_send_json_success( $this->handle_ajax_request( 'update_templates', $_POST ) );
85 + } );
78 86 }
79 87
80 88 /**
81 89 * Get `Import_Images` instance.
@@ -137,10 +145,11 @@
137 145 *
138 146 * Remove an existing template sources from the list of registered template
139 147 * sources.
140 148 *
149 + * @deprecated 2.7.0
150 + *
141 151 * @since 1.0.0
142 - * @deprecated 2.7.0
143 152 * @access public
144 153 *
145 154 * @param string $id The source ID.
146 155 *
@@ -190,21 +199,18 @@
190 199 * Get templates.
191 200 *
192 201 * Retrieve all the templates from all the registered sources.
193 202 *
194 - * @param array $filter_sources
195 - * @param bool $force_update
196 - * @return array
203 + * @since 1.0.0
204 + * @access public
205 + *
206 + * @return array Templates array.
197 207 */
198 - public function get_templates( array $filter_sources = [], bool $force_update = false ): array {
208 + public function get_templates() {
199 209 $templates = [];
200 210
201 211 foreach ( $this->get_registered_sources() as $source ) {
202 - if ( ! empty( $filter_sources ) && ! in_array( $source->get_id(), $filter_sources, true ) ) {
203 - continue;
204 - }
205 -
206 - $templates = array_merge( $templates, $source->get_items( [ 'force_update' => $force_update ] ) );
212 + $templates = array_merge( $templates, $source->get_items() );
207 213 }
208 214
209 215 return $templates;
210 216 }
@@ -221,33 +227,17 @@
221 227 *
222 228 * @return array Library data.
223 229 */
224 230 public function get_library_data( array $args ) {
225 - $force_update = ! empty( $args['sync'] );
231 + $library_data = Api::get_library_data( ! empty( $args['sync'] ) );
226 232
227 - $library_data = Api::get_library_data( $force_update );
228 -
229 - if ( empty( $library_data ) ) {
230 - return $library_data;
231 - }
232 -
233 233 // Ensure all document are registered.
234 234 Plugin::$instance->documents->get_document_types();
235 235
236 - $filter_sources = ! empty( $args['filter_sources'] ) ? $args['filter_sources'] : [];
237 -
238 - $full_library_data = [
239 - 'templates' => $this->get_templates( $filter_sources, $force_update ),
236 + return [
237 + 'templates' => $this->get_templates(),
240 238 'config' => $library_data['types_data'],
241 239 ];
242 -
243 - /**
244 - * Filter the full library data.
245 - *
246 - * @since 3.32.2
247 - * @param-out $full_library_data - 'templates' and 'config' data ('config' holds the list of categories).
248 - */
249 - return apply_filters( 'elementor/library/full-data', $full_library_data );
250 240 }
251 241
252 242 /**
253 243 * Save template.
@@ -267,25 +257,12 @@
267 257 if ( is_wp_error( $validate_args ) ) {
268 258 return $validate_args;
269 259 }
270 260
271 - $sources = (array) $args['source']; // BC
272 - $results = [];
273 -
274 - foreach ( $sources as $source ) {
275 - $args_copy = $args;
276 - $args_copy['source'] = $source;
277 - $results[] = $this->save_template_item( $args_copy );
278 - }
279 -
280 - return 1 === count( $results ) ? $results[0] : $results;
281 - }
282 -
283 - private function save_template_item( array $args ) {
284 261 $source = $this->get_source( $args['source'] );
285 262
286 263 if ( ! $source ) {
287 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
264 + return new \WP_Error( 'template_error', 'Template source not found.' );
288 265 }
289 266
290 267 $args['content'] = json_decode( $args['content'], true );
291 268
@@ -301,97 +278,8 @@
301 278
302 279 return $source->get_item( $template_id );
303 280 }
304 281
305 - public function move_template( array $args ) {
306 - $validate_args = $this->ensure_args( [ 'source', 'from_source', 'from_template_id' ], $args );
307 -
308 - if ( is_wp_error( $validate_args ) ) {
309 - return $validate_args;
310 - }
311 -
312 - $args['source'] = $args['source'][0];
313 -
314 - $result = $this->move_template_item( $args );
315 -
316 - if ( ! $this->is_action_to_same_source( $args ) ) {
317 - $this->delete_template( [
318 - 'source' => $args['from_source'],
319 - 'template_id' => $args['from_template_id'],
320 - ] );
321 - }
322 -
323 - return $result;
324 - }
325 -
326 - private function move_template_item( array $args ) {
327 - $validate_args = $this->ensure_args( [ 'source', 'from_source', 'from_template_id' ], $args );
328 -
329 - if ( is_wp_error( $validate_args ) ) {
330 - return $validate_args;
331 - }
332 -
333 - $source = $this->get_source( $args['source'] );
334 -
335 - if ( ! $source ) {
336 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
337 - }
338 -
339 - if ( $this->is_action_to_same_source( $args ) ) {
340 - return $source->move_template_to_folder( $args );
341 - }
342 -
343 - $from_source = $this->get_source( $args['from_source'] );
344 -
345 - if ( ! $from_source ) {
346 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
347 - }
348 -
349 - $args = $from_source->format_args_for_single_action( $args );
350 -
351 - $template_id = $source->save_item( $args );
352 -
353 - if ( is_wp_error( $template_id ) ) {
354 - return $template_id;
355 - }
356 -
357 - return $source->get_item( $template_id );
358 - }
359 -
360 - public function copy_template( array $args ) {
361 - $validate_args = $this->ensure_args( [ 'source', 'from_source', 'from_template_id' ], $args );
362 -
363 - if ( is_wp_error( $validate_args ) ) {
364 - return $validate_args;
365 - }
366 -
367 - $source = $this->get_source( $args['source'][0] );
368 -
369 - if ( ! $source ) {
370 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
371 - }
372 -
373 - $from_source = $this->get_source( $args['from_source'] );
374 -
375 - if ( ! $from_source ) {
376 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
377 - }
378 -
379 - $args = $from_source->format_args_for_single_action( $args );
380 -
381 - $template_id = $source->save_item( $args );
382 -
383 - if ( is_wp_error( $template_id ) ) {
384 - return $template_id;
385 - }
386 -
387 - return $source->get_item( $template_id );
388 - }
389 -
390 - private function is_action_to_same_source( $args ) {
391 - return $args['source'] === $args['from_source'];
392 - }
393 -
394 282 /**
395 283 * Update template.
396 284 *
397 285 * Update template on the database.
@@ -413,9 +301,9 @@
413 301
414 302 $source = $this->get_source( $template_data['source'] );
415 303
416 304 if ( ! $source ) {
417 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
305 + return new \WP_Error( 'template_error', 'Template source not found.' );
418 306 }
419 307
420 308 $template_data['content'] = json_decode( $template_data['content'], true );
421 309
@@ -427,30 +315,8 @@
427 315
428 316 return $source->get_item( $template_data['id'] );
429 317 }
430 318
431 - public function rename_template( array $template_data ) {
432 - $validate_args = $this->ensure_args( [ 'source', 'title', 'id' ], $template_data );
433 -
434 - if ( is_wp_error( $validate_args ) ) {
435 - return $validate_args;
436 - }
437 -
438 - $source = $this->get_source( $template_data['source'] );
439 -
440 - if ( ! $source ) {
441 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
442 - }
443 -
444 - $update = $source->update_item( $template_data );
445 -
446 - if ( is_wp_error( $update ) ) {
447 - return $update;
448 - }
449 -
450 - return $source->get_item( $template_data['id'] );
451 - }
452 -
453 319 /**
454 320 * Update templates.
455 321 *
456 322 * Update template on the database.
@@ -492,25 +358,18 @@
492 358 if ( is_wp_error( $validate_args ) ) {
493 359 return $validate_args;
494 360 }
495 361
362 + if ( isset( $args['edit_mode'] ) ) {
363 + Plugin::$instance->editor->set_edit_mode( $args['edit_mode'] );
364 + }
365 +
496 366 $source = $this->get_source( $args['source'] );
497 367
498 368 if ( ! $source ) {
499 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
369 + return new \WP_Error( 'template_error', 'Template source not found.' );
500 370 }
501 371
502 - if ( method_exists( $source, 'is_allowed_to_read_template' ) && ! $source->is_allowed_to_read_template( $args ) ) {
503 - return new \WP_Error(
504 - 'template_error',
505 - esc_html__( 'You do not have permission to access this template.', 'elementor' )
506 - );
507 - }
508 -
509 - if ( isset( $args['edit_mode'] ) ) {
510 - Plugin::$instance->editor->set_edit_mode( $args['edit_mode'] );
511 - }
512 -
513 372 do_action( 'elementor/template-library/before_get_source_data', $args, $source );
514 373
515 374 $data = $source->get_data( $args );
516 375
@@ -541,9 +400,9 @@
541 400
542 401 $source = $this->get_source( $args['source'] );
543 402
544 403 if ( ! $source ) {
545 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
404 + return new \WP_Error( 'template_error', 'Template source not found.' );
546 405 }
547 406
548 407 return $source->delete_template( $args['template_id'] );
549 408 }
@@ -550,10 +409,9 @@
550 409
551 410 /**
552 411 * Export template.
553 412 *
554 - * Export template to a file after ensuring it is a valid Elementor template
555 - * and checking user permissions for private posts.
413 + * Export template to a file.
556 414 *
557 415 * @since 1.0.0
558 416 * @access public
559 417 *
@@ -570,9 +428,9 @@
570 428
571 429 $source = $this->get_source( $args['source'] );
572 430
573 431 if ( ! $source ) {
574 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
432 + return new \WP_Error( 'template_error', 'Template source not found' );
575 433 }
576 434
577 435 return $source->export_template( $args['template_id'] );
578 436 }
@@ -583,10 +441,10 @@
583 441 */
584 442 public function direct_import_template() {
585 443 /** @var Source_Local $source */
586 444 $source = $this->get_source( 'local' );
587 - $file = Utils::get_super_global_value( $_FILES, 'file' ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
588 - return $source->import_template( $file['name'], $file['tmp_name'] );
445 +
446 + return $source->import_template( $_FILES['file']['name'], $_FILES['file']['tmp_name'] );
589 447 }
590 448
591 449 /**
592 450 * Import template.
@@ -600,52 +458,25 @@
600 458 *
601 459 * @return mixed Whether the export succeeded or failed.
602 460 */
603 461 public function import_template( array $data ) {
604 - if ( ! User::is_current_user_can_upload_json() ) {
605 - return new \WP_Error( 'template_error', self::ERROR_JSON_UPLOAD_NOT_ALLOWED );
606 - }
462 + /** @var Source_Local $source */
463 + $file_content = base64_decode( $data['fileData'] );
607 464
608 - // If the template is a JSON file, allow uploading it.
609 - add_filter( 'elementor/files/allow-file-type/json', [ $this, 'enable_json_template_upload' ] );
610 - add_filter( 'elementor/files/allow_unfiltered_upload', [ $this, 'enable_json_template_upload' ] );
465 + $tmp_file = tmpfile();
611 466
612 - // Imported templates can be either JSON files, or Zip files containing multiple JSON files
613 - $upload_result = Plugin::$instance->uploads_manager->handle_elementor_upload( $data, [ 'zip', 'json' ] );
467 + fwrite( $tmp_file, $file_content );
614 468
615 - remove_filter( 'elementor/files/allow-file-type/json', [ $this, 'enable_json_template_upload' ] );
616 - remove_filter( 'elementor/files/allow_unfiltered_upload', [ $this, 'enable_json_template_upload' ] );
469 + $source = $this->get_source( 'local' );
617 470
618 - if ( is_wp_error( $upload_result ) ) {
619 - return $upload_result;
620 - }
471 + $result = $source->import_template( $data['fileName'], stream_get_meta_data( $tmp_file )['uri'] );
621 472
622 - $source = $this->get_source( $data['source'] ?? 'local' );
473 + fclose( $tmp_file );
623 474
624 - $import_mode = $data['import_mode'] ?? 'match_site';
625 - $import_result = $source->import_template( $upload_result['name'], $upload_result['tmp_name'], $import_mode );
626 -
627 - // Remove the temporary directory generated for the stream-uploaded file.
628 - Plugin::$instance->uploads_manager->remove_file_or_dir( dirname( $upload_result['tmp_name'] ) );
629 -
630 - return $import_result;
475 + return $result;
631 476 }
632 477
633 478 /**
634 - * Enable JSON Template Upload
635 - *
636 - * Runs on the 'elementor/files/allow-file-type/json' Uploads Manager filter.
637 - *
638 - * @since 3.5.0
639 - * @access public
640 - *
641 - * return bool
642 - */
643 - public function enable_json_template_upload() {
644 - return true;
645 - }
646 -
647 - /**
648 479 * Mark template as favorite.
649 480 *
650 481 * Add the template to the user favorite templates.
651 482 *
@@ -667,201 +498,8 @@
667 498
668 499 return $source->mark_as_favorite( $args['template_id'], filter_var( $args['favorite'], FILTER_VALIDATE_BOOLEAN ) );
669 500 }
670 501
671 - public function import_from_json( array $args ) {
672 - $validate_args = $this->ensure_args( [ 'editor_post_id', 'elements' ], $args );
673 -
674 - if ( is_wp_error( $validate_args ) ) {
675 - return $validate_args;
676 - }
677 -
678 - $elements = json_decode( $args['elements'], true );
679 -
680 - $document = Plugin::$instance->documents->get( $args['editor_post_id'] );
681 - if ( ! $document ) {
682 - return new \WP_Error( 'template_error', 'Document not found.' );
683 - }
684 -
685 - $import_data = $document->get_import_data( [ 'content' => $elements ] );
686 -
687 - $content = $document::on_import_update_dynamic_content(
688 - $import_data['content'],
689 - [ 'post_ids' => [] ]
690 - );
691 -
692 - return Plugin::$instance->db->iterate_data( $content, function( $element_data ) {
693 - unset( $element_data['htmlCache'] );
694 - return $element_data;
695 - } );
696 - }
697 -
698 - public function process_global_styles( array $args ) {
699 - $validate_args = $this->ensure_args( [ 'content', 'import_mode' ], $args );
700 -
701 - if ( is_wp_error( $validate_args ) ) {
702 - return $validate_args;
703 - }
704 -
705 - $import_mode = Template_Library_Import_Export_Utils::sanitize_import_mode( $args['import_mode'] );
706 -
707 - $content = $this->get_validated_json_arg( $args, 'content' );
708 - if ( is_wp_error( $content ) ) {
709 - return $content;
710 - }
711 -
712 - $global_classes = $this->get_validated_json_arg( $args, 'global_classes', true );
713 - if ( is_wp_error( $global_classes ) ) {
714 - return $global_classes;
715 - }
716 -
717 - $global_variables = $this->get_validated_json_arg( $args, 'global_variables', true );
718 - if ( is_wp_error( $global_variables ) ) {
719 - return $global_variables;
720 - }
721 -
722 - $data = [
723 - 'global_classes' => $global_classes,
724 - 'global_variables' => $global_variables,
725 - ];
726 -
727 - $result = apply_filters(
728 - 'elementor/template_library/import/process_content',
729 - [ 'content' => $content ],
730 - $import_mode,
731 - $data,
732 - null
733 - );
734 -
735 - $response = [
736 - 'content' => $result['content'],
737 - ];
738 -
739 - if ( ! empty( $result['updated_global_classes'] ) ) {
740 - $response['updated_global_classes'] = $result['updated_global_classes'];
741 - }
742 -
743 - if ( ! empty( $result['updated_global_variables'] ) ) {
744 - $response['updated_global_variables'] = $result['updated_global_variables'];
745 - }
746 -
747 - $classes_to_flatten = $result['classes_to_flatten'] ?? [];
748 - $variables_to_flatten = $result['variables_to_flatten'] ?? [];
749 -
750 - if ( ! empty( $classes_to_flatten ) ) {
751 - $response['flattened_classes_count'] = count( $classes_to_flatten );
752 - }
753 -
754 - if ( ! empty( $variables_to_flatten ) ) {
755 - $response['flattened_variables_count'] = count( $variables_to_flatten );
756 - }
757 -
758 - return $response;
759 - }
760 -
761 - private function get_validated_json_arg( array $args, string $key, bool $is_optional = false ) {
762 - if ( ! array_key_exists( $key, $args ) || null === $args[ $key ] || '' === $args[ $key ] ) {
763 - return $is_optional ? null : new \WP_Error( "invalid_$key", "Invalid $key." );
764 - }
765 -
766 - $value = $args[ $key ];
767 - if ( is_string( $value ) ) {
768 - $decoded = json_decode( $value, true );
769 - if ( JSON_ERROR_NONE !== json_last_error() ) {
770 - return new \WP_Error( "invalid_$key", "Invalid JSON $key." );
771 - }
772 - return $decoded;
773 - }
774 -
775 - if ( ! is_array( $value ) ) {
776 - return new \WP_Error( "invalid_$key", "Invalid $key format." );
777 - }
778 -
779 - return $value;
780 - }
781 -
782 - public function get_item_children( array $args ) {
783 - $validate_args = $this->ensure_args( [ 'source', 'template_id' ], $args );
784 -
785 - if ( is_wp_error( $validate_args ) ) {
786 - return $validate_args;
787 - }
788 -
789 - $source = $this->get_source( $args['source'] );
790 -
791 - if ( ! $source ) {
792 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
793 - }
794 -
795 - return $source->get_item_children( $args );
796 - }
797 -
798 - public function search_templates( array $args ) {
799 - $validate_args = $this->ensure_args( [ 'source', 'search' ], $args );
800 -
801 - if ( is_wp_error( $validate_args ) ) {
802 - return $validate_args;
803 - }
804 -
805 - $source = $this->get_source( $args['source'] );
806 -
807 - if ( ! $source ) {
808 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
809 - }
810 -
811 - return $source->search_templates( $args );
812 - }
813 -
814 - public function load_more_templates( array $args ) {
815 - $validate_args = $this->ensure_args( [ 'source', 'offset' ], $args );
816 -
817 - if ( is_wp_error( $validate_args ) ) {
818 - return $validate_args;
819 - }
820 -
821 - $source = $this->get_source( $args['source'] );
822 -
823 - if ( ! $source ) {
824 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
825 - }
826 -
827 - return $source->get_items( $args );
828 - }
829 -
830 - public function create_folder( array $args ) {
831 - $validate_args = $this->ensure_args( [ 'source', 'title' ], $args );
832 -
833 - if ( is_wp_error( $validate_args ) ) {
834 - return $validate_args;
835 - }
836 -
837 - $source = $this->get_source( $args['source'] );
838 -
839 - if ( ! $source ) {
840 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
841 - }
842 -
843 - return $source->save_folder( $args );
844 - }
845 -
846 - public function get_folders( array $args ) {
847 - $validate_args = $this->ensure_args( [ 'source', 'offset' ], $args );
848 -
849 - if ( is_wp_error( $validate_args ) ) {
850 - return $validate_args;
851 - }
852 -
853 - $source = $this->get_source( $args['source'] );
854 -
855 - if ( ! $source ) {
856 - return new \WP_Error( 'template_error', 'Folder source not found.' );
857 - }
858 -
859 - $args['templateType'] = 'folder';
860 -
861 - return $source->get_items( $args );
862 - }
863 -
864 502 /**
865 503 * Register default template sources.
866 504 *
867 505 * Register the 'local' and 'remote' template sources that Elementor use by
@@ -873,9 +511,8 @@
873 511 private function register_default_sources() {
874 512 $sources = [
875 513 'local',
876 514 'remote',
877 - 'cloud',
878 515 ];
879 516
880 517 foreach ( $sources as $source_filename ) {
881 518 $class_name = ucwords( $source_filename );
@@ -894,27 +531,23 @@
894 531 * @access private
895 532 *
896 533 * @param string $ajax_request Ajax request.
897 534 *
898 - * @param array $data
535 + * @param array $data
899 536 *
900 537 * @return mixed
901 - * @throws \Exception If current user has no permission or the post is not found.
538 + * @throws \Exception
902 539 */
903 540 private function handle_ajax_request( $ajax_request, array $data ) {
904 541 if ( ! User::is_current_user_can_edit_post_type( Source_Local::CPT ) ) {
905 - throw new \Exception( 'Access denied.' );
542 + throw new \Exception( 'Access Denied' );
906 543 }
907 544
908 - if ( 'import_template' === $ajax_request && ! User::is_current_user_can_upload_json() ) {
909 - throw new \Exception( 'Access denied.' );
910 - }
911 -
912 545 if ( ! empty( $data['editor_post_id'] ) ) {
913 546 $editor_post_id = absint( $data['editor_post_id'] );
914 547
915 548 if ( ! get_post( $editor_post_id ) ) {
916 - throw new \Exception( 'Post not found.' );
549 + throw new \Exception( __( 'Post not found.', 'elementor' ) );
917 550 }
918 551
919 552 Plugin::$instance->db->switch_to_post( $editor_post_id );
920 553 }
@@ -921,9 +554,9 @@
921 554
922 555 $result = call_user_func( [ $this, $ajax_request ], $data );
923 556
924 557 if ( is_wp_error( $result ) ) {
925 - throw new \Exception( esc_html( $result->get_error_message() ) );
558 + throw new \Exception( $result->get_error_message() );
926 559 }
927 560
928 561 return $result;
929 562 }
@@ -928,76 +561,8 @@
928 561 return $result;
929 562 }
930 563
931 564 /**
932 - * @throws \Exception If template import fails, file validation errors occur, or processing encounters issues.
933 - */
934 - public function save_template_screenshot( $data ): string {
935 - $validate_args = $this->ensure_args( [ 'template_id', 'screenshot' ], $data );
936 -
937 - if ( is_wp_error( $validate_args ) ) {
938 - return $validate_args;
939 - }
940 -
941 - $raw_binary = base64_decode( substr( $data['screenshot'], strlen( 'data:image/png;base64,' ) ) );
942 -
943 - return $this->get_source( 'cloud' )->save_item_preview( $data['template_id'], $raw_binary );
944 - }
945 -
946 - /**
947 - * @throws \Exception If template processing fails or data validation errors occur.
948 - */
949 - public function template_screenshot_failed( $data ): string {
950 - $validate_args = $this->ensure_args( [ 'template_id' ], $data );
951 -
952 - if ( is_wp_error( $validate_args ) ) {
953 - return $validate_args;
954 - }
955 -
956 - return $this->get_source( 'cloud' )->mark_preview_as_failed( $data['template_id'], $data['error'] );
957 - }
958 -
959 - public function bulk_delete_templates( $data ) {
960 - $validate_args = $this->ensure_args( [ 'template_ids', 'source' ], $data );
961 -
962 - if ( is_wp_error( $validate_args ) ) {
963 - return $validate_args;
964 - }
965 -
966 - $source = $this->get_source( $data['source'] );
967 -
968 - if ( ! $source ) {
969 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
970 - }
971 -
972 - if ( empty( $data['template_ids'] ) || ! is_array( $data['template_ids'] ) ) {
973 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_IDS_MISSING );
974 - }
975 -
976 - return $source->bulk_delete_items( $data['template_ids'] );
977 - }
978 -
979 - public function bulk_undo_delete_items( $data ) {
980 - $validate_args = $this->ensure_args( [ 'template_ids', 'source' ], $data );
981 -
982 - if ( is_wp_error( $validate_args ) ) {
983 - return $validate_args;
984 - }
985 -
986 - $source = $this->get_source( $data['source'] );
987 -
988 - if ( ! $source ) {
989 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
990 - }
991 -
992 - if ( empty( $data['template_ids'] ) || ! is_array( $data['template_ids'] ) ) {
993 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_IDS_MISSING );
994 - }
995 -
996 - return $source->bulk_undo_delete_items( $data['template_ids'] );
997 - }
998 -
999 - /**
1000 565 * Init ajax calls.
1001 566 *
1002 567 * Initialize template library ajax calls for allowed ajax requests.
1003 568 *
@@ -1014,25 +579,8 @@
1014 579 'update_templates',
1015 580 'delete_template',
1016 581 'import_template',
1017 582 'mark_template_as_favorite',
1018 - 'import_from_json',
1019 - 'get_item_children',
1020 - 'search_templates',
1021 - 'rename_template',
1022 - 'load_more_templates',
1023 - 'create_folder',
1024 - 'get_folders',
1025 - 'save_template_screenshot',
1026 - 'move_template',
1027 - 'copy_template',
1028 - 'bulk_move_templates',
1029 - 'bulk_delete_templates',
1030 - 'bulk_copy_templates',
1031 - 'bulk_undo_delete_items',
1032 - 'get_templates_quota',
1033 - 'template_screenshot_failed',
1034 - 'process_global_styles',
1035 583 ];
1036 584
1037 585 foreach ( $library_ajax_requests as $ajax_request ) {
1038 586 $ajax->register_ajax_action( $ajax_request, function( $data ) use ( $ajax_request ) {
@@ -1056,25 +604,12 @@
1056 604 if ( ! $ajax->verify_request_nonce() ) {
1057 605 $this->handle_direct_action_error( 'Access Denied' );
1058 606 }
1059 607
1060 - $action = Utils::get_super_global_value( $_REQUEST, 'library_action' ); // phpcs:ignore -- Nonce already verified.
608 + $action = $_REQUEST['library_action'];
1061 609
1062 - $whitelist_methods = [
1063 - 'export_template',
1064 - 'direct_import_template',
1065 - ];
610 + $result = $this->$action( $_REQUEST );
1066 611
1067 - if ( 'direct_import_template' === $action && ! User::is_current_user_can_upload_json() ) {
1068 - return;
1069 - }
1070 -
1071 - if ( in_array( $action, $whitelist_methods, true ) ) {
1072 - $result = $this->$action( $_REQUEST ); // phpcs:ignore -- Nonce already verified.
1073 - } else {
1074 - $result = new \WP_Error( 'method_not_exists', 'Method Not exists' );
1075 - }
1076 -
1077 612 if ( is_wp_error( $result ) ) {
1078 613 /** @var \WP_Error $result */
1079 614 $this->handle_direct_action_error( $result->get_error_message() . '.' );
1080 615 }
@@ -1124,9 +659,9 @@
1124 659 *
1125 660 * @return \WP_Error|true True on success, 'WP_Error' otherwise.
1126 661 */
1127 662 private function ensure_args( array $required_args, array $specified_args ) {
1128 - $not_specified_args = array_diff( $required_args, array_keys( $specified_args ) );
663 + $not_specified_args = array_diff( $required_args, array_keys( array_filter( $specified_args ) ) );
1129 664
1130 665 if ( $not_specified_args ) {
1131 666 return new \WP_Error( 'arguments_not_specified', sprintf( 'The required argument(s) "%s" not specified.', implode( ', ', $not_specified_args ) ) );
1132 667 }
@@ -1131,119 +666,6 @@
1131 666 return new \WP_Error( 'arguments_not_specified', sprintf( 'The required argument(s) "%s" not specified.', implode( ', ', $not_specified_args ) ) );
1132 667 }
1133 668
1134 669 return true;
1135 - }
1136 -
1137 - public function bulk_move_templates( array $args ) {
1138 - $validate_args = $this->ensure_args( [ 'source', 'from_source', 'from_template_id' ], $args );
1139 -
1140 - if ( is_wp_error( $validate_args ) ) {
1141 - return $validate_args;
1142 - }
1143 -
1144 - $args['source'] = $args['source'][0];
1145 -
1146 - return $this->bulk_move_template_items( $args );
1147 - }
1148 -
1149 - private function bulk_move_template_items( array $args ) {
1150 - $source = $this->get_source( $args['source'] );
1151 -
1152 - if ( ! $source ) {
1153 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
1154 - }
1155 -
1156 - if ( $this->is_action_to_same_source( $args ) ) {
1157 - return $source->move_bulk_templates_to_folder( $args );
1158 - }
1159 -
1160 - $from_source = $this->get_source( $args['from_source'] );
1161 -
1162 - if ( ! $from_source ) {
1163 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
1164 - }
1165 -
1166 - $bulk_args = $from_source->format_args_for_bulk_action( $args );
1167 -
1168 - if ( $source->supports_quota() && ! $this->is_action_to_same_source( $args ) ) {
1169 - $quota_validation = $source->validate_quota( $bulk_args );
1170 -
1171 - if ( is_wp_error( $quota_validation ) ) {
1172 - return $quota_validation;
1173 - }
1174 -
1175 - if ( false === $quota_validation ) {
1176 - return new \WP_Error( 'quota_error', 'The moving failed because it will pass the maximum templates you can save.' );
1177 - }
1178 - }
1179 -
1180 - $bulk_save = $source->save_bulk_items( $bulk_args );
1181 -
1182 - if ( ! empty( $bulk_save ) ) {
1183 - $this->bulk_delete_templates( [
1184 - 'template_ids' => $args['from_template_id'],
1185 - 'source' => $args['from_source'],
1186 - ] );
1187 - }
1188 -
1189 - return $bulk_save;
1190 - }
1191 -
1192 - public function bulk_copy_templates( array $args ) {
1193 - $validate_args = $this->ensure_args( [ 'source', 'from_source', 'from_template_id' ], $args );
1194 -
1195 - if ( is_wp_error( $validate_args ) ) {
1196 - return $validate_args;
1197 - }
1198 -
1199 - $args['source'] = $args['source'][0];
1200 -
1201 - return $this->bulk_copy_template_items( $args );
1202 - }
1203 -
1204 - private function bulk_copy_template_items( array $args ) {
1205 - $source = $this->get_source( $args['source'] );
1206 -
1207 - if ( ! $source ) {
1208 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
1209 - }
1210 -
1211 - $from_source = $this->get_source( $args['from_source'] );
1212 -
1213 - if ( ! $from_source ) {
1214 - return new \WP_Error( 'template_error', self::ERROR_TEMPLATE_SOURCE_NOT_FOUND );
1215 - }
1216 -
1217 - $bulk_args = $from_source->format_args_for_bulk_action( $args );
1218 -
1219 - if ( $source->supports_quota() && ! $this->is_action_to_same_source( $args ) ) {
1220 - $quota_validation = $source->validate_quota( $bulk_args );
1221 -
1222 - if ( is_wp_error( $quota_validation ) ) {
1223 - return $quota_validation;
1224 - }
1225 -
1226 - if ( false === $quota_validation ) {
1227 - return new \WP_Error( 'quota_error', 'The copying failed because it will pass the maximum templates you can save.' );
1228 - }
1229 - }
1230 -
1231 - return $source->save_bulk_items( $bulk_args );
1232 - }
1233 -
1234 - public function get_templates_quota( array $args ) {
1235 - $validate_args = $this->ensure_args( [ 'source' ], $args );
1236 -
1237 - if ( is_wp_error( $validate_args ) ) {
1238 - return $validate_args;
1239 - }
1240 -
1241 - $source = $this->get_source( $args['source'] );
1242 -
1243 - if ( ! $source ) {
1244 - return new \WP_Error( 'template_error', 'Source not found.' );
1245 - }
1246 -
1247 - return $source->get_quota();
1248 670 }
1249 671 }