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