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-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 | app/modules/import-export-customization/module.php +96 -132 4.1.0-dev23.31.2 View file →
@@ -6,12 +6,9 @@
6 6 use Elementor\App\Modules\ImportExportCustomization\Processes\Revert;
7 7 use Elementor\Core\Base\Module as BaseModule;
8 8 use Elementor\Core\Files\Uploads_Manager;
9 9 use Elementor\Modules\CloudKitLibrary\Module as CloudKitLibrary;
10 -use Elementor\Modules\GlobalClasses\Global_Classes_REST_API;
11 10 use Elementor\Modules\System_Info\Reporters\Server;
12 -use Elementor\Modules\Variables\Storage\Constants;
13 -use Elementor\Modules\Variables\Storage\Variables_Collection;
14 11 use Elementor\Plugin;
15 12 use Elementor\Tools;
16 13 use Elementor\Utils as ElementorUtils;
17 14 use Elementor\App\Modules\ImportExportCustomization\Utils as ImportExportUtils;
@@ -27,9 +24,9 @@
27 24 *
28 25 * Responsible for initializing Elementor App functionality
29 26 */
30 27 class Module extends BaseModule {
31 - const FORMAT_VERSION = '3.0';
28 + const FORMAT_VERSION = '2.0';
32 29
33 30 const REFERRER_KIT_LIBRARY = 'kit-library';
34 31
35 32 const REFERRER_LOCAL = 'local';
@@ -39,10 +36,8 @@
39 36 const PLUGIN_PERMISSIONS_ERROR_KEY = 'plugin-installation-permissions-error';
40 37
41 38 const KIT_LIBRARY_ERROR_KEY = 'invalid-kit-library-zip-error';
42 39
43 - const CLOUD_KIT_LIBRARY_ERROR_LOADING_RESOURCE = 'error-loading-resource';
44 -
45 40 const NO_WRITE_PERMISSIONS_KEY = 'no-write-permissions';
46 41
47 42 const THIRD_PARTY_ERROR = 'third-party-error';
48 43
@@ -47,10 +42,8 @@
47 42 const THIRD_PARTY_ERROR = 'third-party-error';
48 43
49 44 const DOMDOCUMENT_MISSING = 'domdocument-missing';
50 45
51 - const MEDIA_PROCESSING_ERROR = 'media-processing-error';
52 -
53 46 const OPTION_KEY_ELEMENTOR_IMPORT_SESSIONS = 'elementor_import_sessions';
54 47
55 48 const OPTION_KEY_ELEMENTOR_REVERT_SESSIONS = 'elementor_revert_sessions';
56 49
@@ -136,17 +129,16 @@
136 129 /**
137 130 * Render the import/export tab content.
138 131 */
139 132 private function render_import_export_tab_content() {
140 - $is_cloud_kits_available = CloudKitLibrary::get_app()->check_eligibility()['is_eligible'];
133 + $is_cloud_kits_available = Plugin::$instance->experiments->is_feature_active( 'cloud-library' ) && CloudKitLibrary::get_app()->is_eligible();
141 134
142 135 $content_data = [
143 136 'export' => [
144 137 'title' => esc_html__( 'Export this website', 'elementor' ),
145 138 'button' => [
146 - 'url' => Plugin::$instance->app->get_base_url() . '#/export-customization',
139 + 'url' => Plugin::$instance->app->get_base_url() . '#/export',
147 140 'text' => esc_html__( 'Export', 'elementor' ),
148 - 'id' => 'elementor-import-export__export',
149 141 ],
150 142 'description' => esc_html__( 'You can download this website as a .zip file, or upload it to the library.', 'elementor' ),
151 143 ],
152 144 'import' => [
@@ -151,11 +143,10 @@
151 143 ],
152 144 'import' => [
153 145 'title' => esc_html__( 'Apply a Website Template', 'elementor' ),
154 146 'button' => [
155 - 'url' => Plugin::$instance->app->get_base_url() . '#/import-customization',
147 + 'url' => Plugin::$instance->app->get_base_url() . '#/import',
156 148 'text' => $is_cloud_kits_available ? esc_html__( 'Upload .zip file', 'elementor' ) : esc_html__( 'Import', 'elementor' ),
157 - 'id' => 'elementor-import-export__import',
158 149 ],
159 150 'description' => esc_html__( 'You can import design and settings from a .zip file or choose from the library.', 'elementor' ),
160 151 ],
161 152 ];
@@ -160,17 +151,11 @@
160 151 ],
161 152 ];
162 153
163 154 if ( $is_cloud_kits_available ) {
164 - $return_to_url = Tools::get_url() . '#tab-import-export-kit';
165 - $kit_library_url = add_query_arg(
166 - [ 'return_to' => rawurlencode( $return_to_url ) ],
167 - Plugin::$instance->app->get_base_url() . '#/kit-library/cloud'
168 - );
169 155 $content_data['import']['button_secondary'] = [
170 - 'url' => $kit_library_url,
171 - 'text' => esc_html__( 'Import from library', 'elementor' ),
172 - 'id' => 'elementor-import-export__import_from_library',
156 + 'url' => Plugin::$instance->app->get_base_url() . '#/kit-library/cloud',
157 + 'text' => esc_html__( 'Open the Library', 'elementor' ),
173 158 ];
174 159 }
175 160
176 161 $last_imported_kit = $this->revert->get_last_import_session();
@@ -179,14 +164,13 @@
179 164 $user_date_format = get_option( 'date_format' );
180 165 $user_time_format = get_option( 'time_format' );
181 166 $date_format = $user_date_format . ' ' . $user_time_format;
182 167
183 - $should_show_revert_section = ! empty( $last_imported_kit );
168 + $should_show_revert_section = $this->should_show_revert_section( $last_imported_kit );
184 169
185 170 if ( $should_show_revert_section ) {
186 171 if ( ! empty( $penultimate_imported_kit ) ) {
187 172 $revert_text = sprintf(
188 - /* translators: 1: kit title, 2: date, 3: line break, 4: kit title, 5: date. */
189 173 esc_html__( 'Remove all the content and site settings that came with "%1$s" on %2$s %3$s and revert to the site setting that came with "%4$s" on %5$s.', 'elementor' ),
190 174 ! empty( $last_imported_kit['kit_title'] ) ? $last_imported_kit['kit_title'] : esc_html__( 'imported kit', 'elementor' ),
191 175 gmdate( $date_format, $last_imported_kit['start_timestamp'] ),
192 176 '<br>',
@@ -194,9 +178,8 @@
194 178 gmdate( $date_format, $penultimate_imported_kit['start_timestamp'] )
195 179 );
196 180 } else {
197 181 $revert_text = sprintf(
198 - /* translators: 1: kit title, 2: date, 3: line break */
199 182 esc_html__( 'Remove all the content and site settings that came with "%1$s" on %2$s.%3$s Your original site settings will be restored.', 'elementor' ),
200 183 ! empty( $last_imported_kit['kit_title'] ) ? $last_imported_kit['kit_title'] : esc_html__( 'imported kit', 'elementor' ),
201 184 gmdate( $date_format, $last_imported_kit['start_timestamp'] ),
202 185 '<br>'
@@ -248,36 +231,49 @@
248 231 <?php
249 232 }
250 233
251 234 private function print_item_content( $data ) {
252 - $container_classes = 'tab-import-export-kit__container e-editor-one';
253 - ?>
254 - <div class="<?php echo esc_attr( $container_classes ); ?>">
255 - <div class="tab-import-export-kit__box">
256 - <h2><?php ElementorUtils::print_unescaped_internal_string( $data['title'] ); ?></h2>
235 + $is_cloud_kits_feature_active = Plugin::$instance->experiments->is_feature_active( 'cloud-library' );
236 +
237 + if ( $is_cloud_kits_feature_active ) { ?>
238 + <div class="tab-import-export-kit__container">
239 + <div class="tab-import-export-kit__box">
240 + <h2><?php ElementorUtils::print_unescaped_internal_string( $data['title'] ); ?></h2>
241 + </div>
242 + <p class="description"><?php ElementorUtils::print_unescaped_internal_string( $data['description'] ); ?></p>
243 +
244 + <?php if ( ! empty( $data['link'] ) ) : ?>
245 + <a href="<?php ElementorUtils::print_unescaped_internal_string( $data['link']['url'] ); ?>" target="_blank"><?php ElementorUtils::print_unescaped_internal_string( $data['link']['text'] ); ?></a>
246 + <?php endif; ?>
247 + <div class="tab-import-export-kit__box action-buttons">
248 + <?php if ( ! empty( $data['button_secondary'] ) ) : ?>
249 + <a href="<?php ElementorUtils::print_unescaped_internal_string( $data['button_secondary']['url'] ); ?>" class="elementor-button e-btn-txt e-btn-txt-border">
250 + <?php ElementorUtils::print_unescaped_internal_string( $data['button_secondary']['text'] ); ?>
251 + </a>
252 + <?php endif; ?>
253 + <a href="<?php ElementorUtils::print_unescaped_internal_string( $data['button']['url'] ); ?>" class="elementor-button e-primary">
254 + <?php ElementorUtils::print_unescaped_internal_string( $data['button']['text'] ); ?>
255 + </a>
256 + </div>
257 257 </div>
258 - <p class="description"><?php ElementorUtils::print_unescaped_internal_string( $data['description'] ); ?></p>
259 -
260 - <?php if ( ! empty( $data['link'] ) ) : ?>
258 + <?php } else { ?>
259 + <div class="tab-import-export-kit__container">
260 + <div class="tab-import-export-kit__box">
261 + <h2><?php ElementorUtils::print_unescaped_internal_string( $data['title'] ); ?></h2>
262 + <a href="<?php ElementorUtils::print_unescaped_internal_string( $data['button']['url'] ); ?>" class="elementor-button e-primary">
263 + <?php ElementorUtils::print_unescaped_internal_string( $data['button']['text'] ); ?>
264 + </a>
265 + </div>
266 + <p><?php ElementorUtils::print_unescaped_internal_string( $data['description'] ); ?></p>
261 267 <a href="<?php ElementorUtils::print_unescaped_internal_string( $data['link']['url'] ); ?>" target="_blank"><?php ElementorUtils::print_unescaped_internal_string( $data['link']['text'] ); ?></a>
262 - <?php endif; ?>
263 - <div class="tab-import-export-kit__box action-buttons">
264 - <?php if ( ! empty( $data['button_secondary'] ) ) : ?>
265 - <a id="<?php ElementorUtils::print_unescaped_internal_string( $data['button_secondary']['id'] ); ?>" href="<?php ElementorUtils::print_unescaped_internal_string( $data['button_secondary']['url'] ); ?>" class="elementor-button e-btn-txt e-btn-txt-border">
266 - <?php ElementorUtils::print_unescaped_internal_string( $data['button_secondary']['text'] ); ?>
267 - </a>
268 - <?php endif; ?>
269 - <a <?php ElementorUtils::print_html_attributes( [ 'id' => $data['button']['id'] ] ); ?> href="<?php ElementorUtils::print_unescaped_internal_string( $data['button']['url'] ); ?>" class="elementor-button e-primary">
270 - <?php ElementorUtils::print_unescaped_internal_string( $data['button']['text'] ); ?>
271 - </a>
272 268 </div>
273 - </div>
274 - <?php
269 + <?php }
275 270 }
276 271
277 272 private function get_revert_href(): string {
278 - $current_url = add_query_arg( null, null );
279 - return $this->maybe_add_referrer_param( $current_url );
273 + $admin_post_url = admin_url( 'admin-post.php?action=elementor_revert_kit' );
274 + $nonced_admin_post_url = wp_nonce_url( $admin_post_url, 'elementor_revert_kit' );
275 + return $this->maybe_add_referrer_param( $nonced_admin_post_url );
280 276 }
281 277
282 278 /**
283 279 * Checks if referred by a kit and adds the referrer ID to the href
@@ -296,18 +292,8 @@
296 292 return add_query_arg( $param_name, sanitize_key( $_GET[ $param_name ] ), $href );
297 293 }
298 294
299 295 /**
300 - * Get referrer kit ID from current request
301 - *
302 - * @return string
303 - */
304 - private function get_referrer_kit_id_from_request(): string {
305 - // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Called via REST API with its own authentication
306 - return sanitize_key( $_GET['referrer_kit'] ?? '' );
307 - }
308 -
309 - /**
310 296 * Render the last kit thumbnail if exists
311 297 *
312 298 * @param $last_imported_kit
313 299 *
@@ -345,9 +331,9 @@
345 331 * @param string $file Path to the file.
346 332 * @param string $referrer Referrer of the file 'local' or 'kit-library'.
347 333 * @param string $kit_id
348 334 * @return array
349 - * @throws \Exception If customization validation fails or processing errors occur.
335 + * @throws \Exception
350 336 */
351 337 public function upload_kit( $file, $referrer, $kit_id = null ) {
352 338 $this->ensure_writing_permissions();
353 339
@@ -355,10 +341,8 @@
355 341 'referrer' => $referrer,
356 342 'id' => $kit_id,
357 343 ] );
358 344
359 - $this->save_upload_session_data();
360 -
361 345 return [
362 346 'session' => $this->import->get_session_id(),
363 347 'manifest' => $this->import->get_manifest(),
364 348 'conflicts' => $this->import->get_settings_conflicts(),
@@ -375,13 +359,13 @@
375 359 * Assigning the Import process to the 'import' property,
376 360 * so it will be available to use in different places such as: WP_Cli, Pro, etc.
377 361 *
378 362 * @param string $path Path to the file or session_id.
379 - * @param array $settings Settings the import use to determine which content to import.
380 - * (e.g: include, selected_plugins, selected_cpt, selected_override_conditions, etc.)
381 - * @param bool $split_to_chunks Determine if the import process should be split into chunks.
363 + * @param array $settings Settings the import use to determine which content to import.
364 + * (e.g: include, selected_plugins, selected_cpt, selected_override_conditions, etc.)
365 + * @param bool $split_to_chunks Determine if the import process should be split into chunks.
382 366 * @return array
383 - * @throws \Exception If export configuration is invalid or processing fails.
367 + * @throws \Exception
384 368 */
385 369 public function import_kit( string $path, array $settings, bool $split_to_chunks = false ): array {
386 370 $this->ensure_writing_permissions();
387 371 $this->ensure_DOMDocument_exists();
@@ -403,12 +387,8 @@
403 387
404 388 return $this->import->run();
405 389 }
406 390
407 - private function save_upload_session_data(): void {
408 - $this->import->init_import_session();
409 - }
410 -
411 391 /**
412 392 * Resuming import process by re-creating the import instance and running the specific runner.
413 393 *
414 394 * @param string $session_id The id off the import session.
@@ -416,9 +396,9 @@
416 396 *
417 397 * @return array Two types of response.
418 398 * 1. The status and the runner name.
419 399 * 2. The imported data. (Only if the runner is the last one in the import process)
420 - * @throws \Exception If export configuration is invalid or processing fails.
400 + * @throws \Exception
421 401 */
422 402 public function import_kit_by_runner( string $session_id, string $runner_name ): array {
423 403 // Check session_id
424 404 $this->import = Import::from_session( $session_id );
@@ -441,9 +421,9 @@
441 421 *
442 422 * @param array $settings Settings the export use to determine which content to export.
443 423 * (e.g: include, kit_info, selected_plugins, selected_cpt, etc.)
444 424 * @return array
445 - * @throws \Exception If export configuration is invalid or processing fails.
425 + * @throws \Exception
446 426 */
447 427 public function export_kit( array $settings ) {
448 428 $this->ensure_writing_permissions();
449 429
@@ -455,36 +435,30 @@
455 435 return $this->export->run();
456 436 }
457 437
458 438 /**
459 - * Handle revert kit request.
439 + * Handle revert kit ajax request.
460 440 */
461 - public function revert_last_imported_kit(): array {
441 + public function revert_last_imported_kit() {
462 442 $this->revert = new Revert();
463 443 $this->revert->register_default_runners();
464 444
465 - $import_sessions = Revert::get_import_sessions();
445 + do_action( 'elementor/import-export-customization/revert-kit', $this->revert );
466 446
467 - if ( empty( $import_sessions ) ) {
468 - return [
469 - 'revert_completed' => false,
470 - 'message' => __( 'No import sessions available to revert.', 'elementor' ),
471 - 'referrer_kit_id' => $this->get_referrer_kit_id_from_request(),
472 - 'show_referrer_dialog' => false,
473 - ];
474 - }
447 + $this->revert->run();
448 + }
475 449
476 - do_action( 'elementor/import-export-customization/revert-kit', $this->revert );
477 450
478 - $this->revert->run();
451 + /**
452 + * Handle revert last imported kit ajax request.
453 + */
454 + public function handle_revert_last_imported_kit() {
455 + check_admin_referer( 'elementor_revert_kit' );
479 456
480 - $referrer_kit_id = $this->get_referrer_kit_id_from_request();
457 + $this->revert_last_imported_kit();
481 458
482 - return [
483 - 'revert_completed' => true,
484 - 'referrer_kit_id' => $referrer_kit_id,
485 - 'show_referrer_dialog' => ! empty( $referrer_kit_id ),
486 - ];
459 + wp_safe_redirect( admin_url( 'admin.php?page=' . Tools::PAGE_ID . '#tab-import-export-kit' ) );
460 + die;
487 461 }
488 462
489 463 /**
490 464 * Register appropriate actions.
@@ -489,8 +463,10 @@
489 463 /**
490 464 * Register appropriate actions.
491 465 */
492 466 private function register_actions() {
467 + add_action( 'admin_post_elementor_revert_kit', [ $this, 'handle_revert_last_imported_kit' ] );
468 +
493 469 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
494 470
495 471 $page_id = Tools::PAGE_ID;
496 472
@@ -580,16 +556,8 @@
580 556 'lastImportedSession' => $this->revert->get_last_import_session(),
581 557 'appUrl' => Plugin::$instance->app->get_base_url() . '#/kit-library',
582 558 ]
583 559 );
584 -
585 - wp_enqueue_script(
586 - 'import-export-customization-admin',
587 - $this->get_js_assets_url( 'import-export-customization-admin' ),
588 - [ 'elementor-common', 'wp-api-fetch' ],
589 - ELEMENTOR_VERSION,
590 - true
591 - );
592 560 }
593 561
594 562 protected function get_remote_kit_zip( $url ) {
595 563 $remote_zip_request = wp_safe_remote_get( $url );
@@ -626,16 +594,9 @@
626 594 'importSessions' => Revert::get_import_sessions(),
627 595 'lastImportedSession' => $this->revert->get_last_import_session(),
628 596 'kitPreviewNonce' => wp_create_nonce( 'kit_thumbnail' ),
629 597 'restApiBaseUrl' => Controller::get_base_url(),
630 - 'restNonce' => wp_create_nonce( 'wp_rest' ),
631 - 'restUrl' => rest_url(),
632 598 'uiTheme' => $this->get_elementor_ui_theme_preference(),
633 - 'exportGroups' => $this->get_export_groups(),
634 - 'manifestVersion' => self::FORMAT_VERSION,
635 - 'elementorVersion' => ELEMENTOR_VERSION,
636 - 'upgradeVersionUrl' => admin_url( 'plugins.php' ),
637 - 'limits' => $this->get_limits(),
638 599 ];
639 600 }
640 601
641 602 private function get_elementor_ui_theme_preference() {
@@ -643,34 +604,8 @@
643 604
644 605 return $editor_preferences->get_model()->get_settings( 'ui_theme' );
645 606 }
646 607
647 - private function get_export_groups() {
648 - $export_groups = [];
649 - $document_types = Plugin::$instance->documents->get_document_types();
650 -
651 - foreach ( $document_types as $name => $document_type ) {
652 - $export_groups[ $name ] = defined( $document_type . '::EXPORT_GROUP' ) ? $document_type::EXPORT_GROUP : '';
653 - }
654 -
655 - return $export_groups;
656 - }
657 -
658 - private function get_limits() {
659 - $classes_limit = class_exists( Global_Classes_REST_API::class )
660 - ? Global_Classes_REST_API::MAX_ITEMS
661 - : 100;
662 -
663 - $variables_limit = class_exists( Constants::class )
664 - ? Constants::TOTAL_VARIABLES_COUNT
665 - : 100;
666 -
667 - return [
668 - 'classes' => $classes_limit,
669 - 'variables' => $variables_limit,
670 - ];
671 - }
672 -
673 608 /**
674 609 * Get labels of Elementor document types, Elementor Post types, WordPress Post types and Custom Post types.
675 610 */
676 611 private function get_summary_titles() {
@@ -717,11 +652,40 @@
717 652 ];
718 653 }
719 654 }
720 655
656 + $active_kit = Plugin::$instance->kits_manager->get_active_kit();
657 +
658 + foreach ( $active_kit->get_tabs() as $key => $tab ) {
659 + $summary_titles['site-settings'][ $key ] = $tab->get_title();
660 + }
661 +
721 662 return $summary_titles;
722 663 }
723 664
665 + public function should_show_revert_section( $last_imported_kit ) {
666 + if ( empty( $last_imported_kit ) ) {
667 + return false;
668 + }
669 +
670 + // TODO: BC - remove in the future
671 + // The 'templates' runner was in core and moved to the Pro plugin. (Part of it still exits in the Core for BC)
672 + // The runner that is in the core version is missing the revert functionality,
673 + // therefore we shouldn't display the revert section if the import process done with the core version.
674 + $is_import_templates_ran = isset( $last_imported_kit['runners']['templates'] );
675 + if ( $this->has_pro() && $is_import_templates_ran ) {
676 + $has_imported_templates = ! empty( $last_imported_kit['runners']['templates'] );
677 +
678 + return $has_imported_templates;
679 + }
680 +
681 + return true;
682 + }
683 +
684 + public function has_pro(): bool {
685 + return ElementorUtils::has_pro();
686 + }
687 +
724 688 private function get_elementor_editor_home_page_url() {
725 689 if ( 'page' !== get_option( 'show_on_front' ) ) {
726 690 return '';
727 691 }
@@ -783,13 +747,13 @@
783 747 return $document ? $document->get_edit_url() : '';
784 748 }
785 749
786 750 /**
787 - * @param string $class_name
751 + * @param string $class
788 752 *
789 753 * @return bool
790 754 */
791 - public function is_third_party_class( $class_name ) {
755 + public function is_third_party_class( $class ) {
792 756 $allowed_classes = [
793 757 'Elementor\\',
794 758 'ElementorPro\\',
795 759 'WP_',
@@ -796,9 +760,9 @@
796 760 'wp_',
797 761 ];
798 762
799 763 foreach ( $allowed_classes as $allowed_class ) {
800 - if ( str_starts_with( $class_name, $allowed_class ) ) {
764 + if ( str_starts_with( $class, $allowed_class ) ) {
801 765 return false;
802 766 }
803 767 }
804 768