PluginProbe
Elementor Website Builder – more than just a page builder / 3.32.3
Elementor Website Builder – more than just a page builder v3.32.3
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
elementor / app / modules / import-export-customization / module.php

module.php in Elementor Website Builder – more than just a page builder 3.32.3, at app/modules/import-export-customization/module.php

758 lines 24.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\App\Modules\ImportExportCustomization;
3
4 use Elementor\App\Modules\ImportExportCustomization\Processes\Export;
5 use Elementor\App\Modules\ImportExportCustomization\Processes\Import;
6 use Elementor\App\Modules\ImportExportCustomization\Processes\Revert;
7 use Elementor\Core\Base\Module as BaseModule;
8 use Elementor\Core\Files\Uploads_Manager;
9 use Elementor\Modules\CloudKitLibrary\Module as CloudKitLibrary;
10 use Elementor\Modules\System_Info\Reporters\Server;
11 use Elementor\Plugin;
12 use Elementor\Tools;
13 use Elementor\Utils as ElementorUtils;
14 use Elementor\App\Modules\ImportExportCustomization\Utils as ImportExportUtils;
15 use Elementor\App\Modules\ImportExportCustomization\Data\Controller;
16 use Elementor\Core\Settings\Manager as SettingsManager;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit; // Exit if accessed directly.
20 }
21
22 /**
23 * Import Export Module
24 *
25 * Responsible for initializing Elementor App functionality
26 */
27 class Module extends BaseModule {
28 const FORMAT_VERSION = '3.0';
29
30 const REFERRER_KIT_LIBRARY = 'kit-library';
31
32 const REFERRER_LOCAL = 'local';
33
34 const REFERRER_CLOUD = 'cloud';
35
36 const PLUGIN_PERMISSIONS_ERROR_KEY = 'plugin-installation-permissions-error';
37
38 const KIT_LIBRARY_ERROR_KEY = 'invalid-kit-library-zip-error';
39
40 const NO_WRITE_PERMISSIONS_KEY = 'no-write-permissions';
41
42 const THIRD_PARTY_ERROR = 'third-party-error';
43
44 const DOMDOCUMENT_MISSING = 'domdocument-missing';
45
46 const OPTION_KEY_ELEMENTOR_IMPORT_SESSIONS = 'elementor_import_sessions';
47
48 const OPTION_KEY_ELEMENTOR_REVERT_SESSIONS = 'elementor_revert_sessions';
49
50 const META_KEY_ELEMENTOR_IMPORT_SESSION_ID = '_elementor_import_session_id';
51
52 const META_KEY_ELEMENTOR_EDIT_MODE = '_elementor_edit_mode';
53 const IMPORT_PLUGINS_ACTION = 'import-plugins';
54 const EXPORT_SOURCE_CLOUD = 'cloud';
55 const EXPORT_SOURCE_FILE = 'file';
56
57 /**
58 * Assigning the export process to a property, so we can use the process from outside the class.
59 *
60 * @var Export
61 */
62 public $export;
63
64 /**
65 * Assigning the import process to a property, so we can use the process from outside the class.
66 *
67 * @var Import
68 */
69 public $import;
70
71 /**
72 * Assigning the revert process to a property, so we can use the process from outside the class.
73 *
74 * @var Revert
75 */
76 public $revert;
77
78 /**
79 * Get name.
80 *
81 * @access public
82 *
83 * @return string
84 */
85 public function get_name() {
86 return 'import-export-customization';
87 }
88
89 public function __construct() {
90 $this->register_actions();
91
92 Controller::register_hooks();
93
94 if ( ElementorUtils::is_wp_cli() ) {
95 \WP_CLI::add_command( 'elementor kit', WP_CLI::class );
96 }
97
98 ( new Usage() )->register();
99
100 $this->revert = new Revert();
101 }
102
103 public function get_init_settings() {
104 if ( ! Plugin::$instance->app->is_current() ) {
105 return [];
106 }
107
108 return $this->get_config_data();
109 }
110
111 /**
112 * Register the import/export tab in elementor tools.
113 */
114 public function register_settings_tab( Tools $tools ) {
115 $tools->add_tab( 'import-export-kit', [
116 'label' => esc_html__( 'Website Templates', 'elementor' ),
117 'sections' => [
118 'intro' => [
119 'label' => esc_html__( 'Website Templates', 'elementor' ),
120 'callback' => function() {
121 $this->render_import_export_tab_content();
122 },
123 'fields' => [],
124 ],
125 ],
126 ] );
127 }
128
129 /**
130 * Render the import/export tab content.
131 */
132 private function render_import_export_tab_content() {
133 $is_cloud_kits_available = CloudKitLibrary::get_app()->check_eligibility()['is_eligible'];
134
135 $content_data = [
136 'export' => [
137 'title' => esc_html__( 'Export this website', 'elementor' ),
138 'button' => [
139 'url' => Plugin::$instance->app->get_base_url() . '#/export-customization',
140 'text' => esc_html__( 'Export', 'elementor' ),
141 'id' => 'elementor-import-export__export',
142 ],
143 'description' => esc_html__( 'You can download this website as a .zip file, or upload it to the library.', 'elementor' ),
144 ],
145 'import' => [
146 'title' => esc_html__( 'Apply a Website Template', 'elementor' ),
147 'button' => [
148 'url' => Plugin::$instance->app->get_base_url() . '#/import-customization',
149 'text' => $is_cloud_kits_available ? esc_html__( 'Upload .zip file', 'elementor' ) : esc_html__( 'Import', 'elementor' ),
150 'id' => 'elementor-import-export__import',
151 ],
152 'description' => esc_html__( 'You can import design and settings from a .zip file or choose from the library.', 'elementor' ),
153 ],
154 ];
155
156 if ( $is_cloud_kits_available ) {
157 $content_data['import']['button_secondary'] = [
158 'url' => Plugin::$instance->app->get_base_url() . '#/kit-library/cloud',
159 'text' => esc_html__( 'Import from library', 'elementor' ),
160 'id' => 'elementor-import-export__import_from_library',
161 ];
162 }
163
164 $last_imported_kit = $this->revert->get_last_import_session();
165 $penultimate_imported_kit = $this->revert->get_penultimate_import_session();
166
167 $user_date_format = get_option( 'date_format' );
168 $user_time_format = get_option( 'time_format' );
169 $date_format = $user_date_format . ' ' . $user_time_format;
170
171 $should_show_revert_section = ! empty( $last_imported_kit );
172
173 if ( $should_show_revert_section ) {
174 if ( ! empty( $penultimate_imported_kit ) ) {
175 $revert_text = sprintf(
176 /* translators: 1: kit title, 2: date, 3: line break, 4: kit title, 5: date. */
177 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' ),
178 ! empty( $last_imported_kit['kit_title'] ) ? $last_imported_kit['kit_title'] : esc_html__( 'imported kit', 'elementor' ),
179 gmdate( $date_format, $last_imported_kit['start_timestamp'] ),
180 '<br>',
181 ! empty( $penultimate_imported_kit['kit_title'] ) ? $penultimate_imported_kit['kit_title'] : esc_html__( 'imported kit', 'elementor' ),
182 gmdate( $date_format, $penultimate_imported_kit['start_timestamp'] )
183 );
184 } else {
185 $revert_text = sprintf(
186 /* translators: 1: kit title, 2: date, 3: line break */
187 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' ),
188 ! empty( $last_imported_kit['kit_title'] ) ? $last_imported_kit['kit_title'] : esc_html__( 'imported kit', 'elementor' ),
189 gmdate( $date_format, $last_imported_kit['start_timestamp'] ),
190 '<br>'
191 );
192 }
193 }
194 ?>
195
196 <div class="tab-import-export-kit__content">
197 <p class="tab-import-export-kit__info">
198 <?php
199 printf(
200 '%1$s <a href="https://go.elementor.com/wp-dash-import-export-general/" target="_blank">%2$s</a>',
201 esc_html__( 'Here’s where you can export this website as a .zip file, upload it to the cloud, or start the process of applying an existing template to your site.', 'elementor' ),
202 esc_html__( 'Learn more', 'elementor' ),
203 );
204 ?>
205 </p>
206
207 <div class="tab-import-export-kit__wrapper">
208 <?php foreach ( $content_data as $data ) {
209 $this->print_item_content( $data );
210 } ?>
211 </div>
212
213 <?php
214 if ( $should_show_revert_section ) {
215
216 $link_attributes = [
217 'href' => $this->get_revert_href(),
218 'id' => 'elementor-import-export__revert_kit',
219 'class' => 'button',
220 ];
221 ?>
222 <div class="tab-import-export-kit__revert">
223 <h2>
224 <?php echo esc_html__( 'Remove the most recent Website Template', 'elementor' ); ?>
225 </h2>
226 <p class="tab-import-export-kit__info">
227 <?php ElementorUtils::print_unescaped_internal_string( $revert_text ); ?>
228 </p>
229 <?php $this->render_last_kit_thumbnail( $last_imported_kit ); ?>
230 <a <?php ElementorUtils::print_html_attributes( $link_attributes ); ?> >
231 <?php echo esc_html__( 'Remove Website Template', 'elementor' ); ?>
232 </a>
233 </div>
234 <?php } ?>
235 </div>
236 <?php
237 }
238
239 private function print_item_content( $data ) {
240 ?>
241 <div class="tab-import-export-kit__container">
242 <div class="tab-import-export-kit__box">
243 <h2><?php ElementorUtils::print_unescaped_internal_string( $data['title'] ); ?></h2>
244 </div>
245 <p class="description"><?php ElementorUtils::print_unescaped_internal_string( $data['description'] ); ?></p>
246
247 <?php if ( ! empty( $data['link'] ) ) : ?>
248 <a href="<?php ElementorUtils::print_unescaped_internal_string( $data['link']['url'] ); ?>" target="_blank"><?php ElementorUtils::print_unescaped_internal_string( $data['link']['text'] ); ?></a>
249 <?php endif; ?>
250 <div class="tab-import-export-kit__box action-buttons">
251 <?php if ( ! empty( $data['button_secondary'] ) ) : ?>
252 <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">
253 <?php ElementorUtils::print_unescaped_internal_string( $data['button_secondary']['text'] ); ?>
254 </a>
255 <?php endif; ?>
256 <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">
257 <?php ElementorUtils::print_unescaped_internal_string( $data['button']['text'] ); ?>
258 </a>
259 </div>
260 </div>
261 <?php
262 }
263
264 private function get_revert_href(): string {
265 $admin_post_url = admin_url( 'admin-post.php?action=elementor_revert_kit' );
266 $nonced_admin_post_url = wp_nonce_url( $admin_post_url, 'elementor_revert_kit' );
267 return $this->maybe_add_referrer_param( $nonced_admin_post_url );
268 }
269
270 /**
271 * Checks if referred by a kit and adds the referrer ID to the href
272 *
273 * @param string $href
274 *
275 * @return string
276 */
277 private function maybe_add_referrer_param( string $href ): string {
278 $param_name = 'referrer_kit';
279
280 if ( empty( $_GET[ $param_name ] ) ) {
281 return $href;
282 }
283
284 return add_query_arg( $param_name, sanitize_key( $_GET[ $param_name ] ), $href );
285 }
286
287 /**
288 * Render the last kit thumbnail if exists
289 *
290 * @param $last_imported_kit
291 *
292 * @return void
293 */
294 private function render_last_kit_thumbnail( $last_imported_kit ) {
295 if ( empty( $last_imported_kit['kit_thumbnail'] ) ) {
296 return;
297 }
298
299 ?>
300 <div class="tab-import-export-kit__kit-item-row">
301 <article class="tab-import-export-kit__kit-item">
302 <header>
303 <h3>
304 <?php echo esc_html( $last_imported_kit['kit_title'] ); ?>
305 </h3>
306 </header>
307 <img
308 src="<?php echo esc_url( $last_imported_kit['kit_thumbnail'] ); ?>"
309 alt="<?php echo esc_attr( $last_imported_kit['kit_title'] ); ?>"
310 loading="lazy"
311 >
312 </article>
313 </div>
314 <?php
315 }
316
317 /**
318 * Upload a kit zip file and get the kit data.
319 *
320 * Assigning the Import process to the 'import' property,
321 * so it will be available to use in different places such as: WP_Cli, Pro, etc.
322 *
323 * @param string $file Path to the file.
324 * @param string $referrer Referrer of the file 'local' or 'kit-library'.
325 * @param string $kit_id
326 * @return array
327 * @throws \Exception
328 */
329 public function upload_kit( $file, $referrer, $kit_id = null ) {
330 $this->ensure_writing_permissions();
331
332 $this->import = new Import( $file, [
333 'referrer' => $referrer,
334 'id' => $kit_id,
335 ] );
336
337 return [
338 'session' => $this->import->get_session_id(),
339 'manifest' => $this->import->get_manifest(),
340 'conflicts' => $this->import->get_settings_conflicts(),
341 ];
342 }
343
344 /**
345 * Import a kit by session_id.
346 * Upload and import a kit by kit zip file.
347 *
348 * If the split_to_chunks flag is true, the process won't start
349 * It will initialize the import process and return the session_id and the runners.
350 *
351 * Assigning the Import process to the 'import' property,
352 * so it will be available to use in different places such as: WP_Cli, Pro, etc.
353 *
354 * @param string $path Path to the file or session_id.
355 * @param array $settings Settings the import use to determine which content to import.
356 * (e.g: include, selected_plugins, selected_cpt, selected_override_conditions, etc.)
357 * @param bool $split_to_chunks Determine if the import process should be split into chunks.
358 * @return array
359 * @throws \Exception
360 */
361 public function import_kit( string $path, array $settings, bool $split_to_chunks = false ): array {
362 $this->ensure_writing_permissions();
363 $this->ensure_DOMDocument_exists();
364
365 $this->import = new Import( $path, $settings );
366 $this->import->register_default_runners();
367
368 remove_filter( 'elementor/document/save/data', [ Plugin::$instance->modules_manager->get_modules( 'content-sanitizer' ), 'sanitize_content' ] );
369 do_action( 'elementor/import-export-customization/import-kit', $this->import );
370
371 if ( $split_to_chunks ) {
372 $this->import->init_import_session( true );
373
374 return [
375 'session' => $this->import->get_session_id(),
376 'runners' => $this->import->get_runners_name(),
377 ];
378 }
379
380 return $this->import->run();
381 }
382
383 /**
384 * Resuming import process by re-creating the import instance and running the specific runner.
385 *
386 * @param string $session_id The id off the import session.
387 * @param string $runner_name The specific runner that we want to run.
388 *
389 * @return array Two types of response.
390 * 1. The status and the runner name.
391 * 2. The imported data. (Only if the runner is the last one in the import process)
392 * @throws \Exception
393 */
394 public function import_kit_by_runner( string $session_id, string $runner_name ): array {
395 // Check session_id
396 $this->import = Import::from_session( $session_id );
397 $runners = $this->import->get_runners_name();
398
399 $run = $this->import->run_runner( $runner_name );
400
401 if ( end( $runners ) === $run['runner'] ) {
402 return $this->import->get_imported_data();
403 }
404
405 return $run;
406 }
407
408 /**
409 * Export a kit.
410 *
411 * Assigning the Export process to the 'export' property,
412 * so it will be available to use in different places such as: WP_Cli, Pro, etc.
413 *
414 * @param array $settings Settings the export use to determine which content to export.
415 * (e.g: include, kit_info, selected_plugins, selected_cpt, etc.)
416 * @return array
417 * @throws \Exception
418 */
419 public function export_kit( array $settings ) {
420 $this->ensure_writing_permissions();
421
422 $this->export = new Export( $settings );
423 $this->export->register_default_runners();
424
425 do_action( 'elementor/import-export-customization/export-kit', $this->export );
426
427 return $this->export->run();
428 }
429
430 /**
431 * Handle revert kit ajax request.
432 */
433 public function revert_last_imported_kit() {
434 $this->revert = new Revert();
435 $this->revert->register_default_runners();
436
437 do_action( 'elementor/import-export-customization/revert-kit', $this->revert );
438
439 $this->revert->run();
440 }
441
442
443 /**
444 * Handle revert last imported kit ajax request.
445 */
446 public function handle_revert_last_imported_kit() {
447 check_admin_referer( 'elementor_revert_kit' );
448
449 $this->revert_last_imported_kit();
450
451 wp_safe_redirect( admin_url( 'admin.php?page=' . Tools::PAGE_ID . '#tab-import-export-kit' ) );
452 die;
453 }
454
455 /**
456 * Register appropriate actions.
457 */
458 private function register_actions() {
459 add_action( 'admin_post_elementor_revert_kit', [ $this, 'handle_revert_last_imported_kit' ] );
460
461 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
462
463 $page_id = Tools::PAGE_ID;
464
465 add_action( "elementor/admin/after_create_settings/{$page_id}", [ $this, 'register_settings_tab' ] );
466
467 // TODO 18/04/2023 : This needs to be moved to the runner itself after https://elementor.atlassian.net/browse/HTS-434 is done.
468 if ( self::IMPORT_PLUGINS_ACTION === ElementorUtils::get_super_global_value( $_SERVER, 'HTTP_X_ELEMENTOR_ACTION' ) ) {
469 add_filter( 'woocommerce_create_pages', [ $this, 'empty_pages' ], 10, 0 );
470 }
471 // TODO ^^^
472
473 add_filter( 'elementor/import/kit/result', function( $result ) {
474 if ( ! empty( $result['file_url'] ) ) {
475 return [
476 'file_name' => $this->get_remote_kit_zip( $result['file_url'] ),
477 'referrer' => static::REFERRER_KIT_LIBRARY,
478 'file_url' => $result['file_url'],
479 ];
480 }
481
482 return $result;
483 } );
484 }
485
486 /**
487 * Prevent the creation of the default WooCommerce pages (Cart, Checkout, etc.)
488 *
489 * TODO 18/04/2023 : This needs to be moved to the runner itself after https://elementor.atlassian.net/browse/HTS-434 is done.
490 *
491 * @return array
492 */
493 public function empty_pages(): array {
494 return [];
495 }
496
497 private function ensure_writing_permissions() {
498 $server = new Server();
499
500 $paths_to_check = [
501 Server::KEY_PATH_WP_CONTENT_DIR => $server->get_system_path( Server::KEY_PATH_WP_CONTENT_DIR ),
502 Server::KEY_PATH_UPLOADS_DIR => $server->get_system_path( Server::KEY_PATH_UPLOADS_DIR ),
503 Server::KEY_PATH_ELEMENTOR_UPLOADS_DIR => $server->get_system_path( Server::KEY_PATH_ELEMENTOR_UPLOADS_DIR ),
504 ];
505
506 $permissions = $server->get_paths_permissions( $paths_to_check );
507
508 // WP Content dir has to be exists and writable.
509 if ( ! $permissions[ Server::KEY_PATH_WP_CONTENT_DIR ]['write'] ) {
510 throw new \Error( self::NO_WRITE_PERMISSIONS_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
511 }
512
513 // WP Uploads dir has to be exists and writable.
514 if ( ! $permissions[ Server::KEY_PATH_UPLOADS_DIR ]['write'] ) {
515 throw new \Error( self::NO_WRITE_PERMISSIONS_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
516 }
517
518 // Elementor uploads dir permissions is divided to 2 cases:
519 // 1. If the dir exists, it has to be writable.
520 // 2. If the dir doesn't exist, the parent dir has to be writable (wp uploads dir), so we can create it.
521 if ( $permissions[ Server::KEY_PATH_ELEMENTOR_UPLOADS_DIR ]['exists'] && ! $permissions[ Server::KEY_PATH_ELEMENTOR_UPLOADS_DIR ]['write'] ) {
522 throw new \Error( self::NO_WRITE_PERMISSIONS_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
523 }
524 }
525
526 private function ensure_DOMDocument_exists() {
527 if ( ! class_exists( 'DOMDocument' ) ) {
528 throw new \Error( self::DOMDOCUMENT_MISSING ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
529 }
530 }
531
532 /**
533 * Enqueue admin scripts
534 */
535 public function enqueue_scripts() {
536 wp_enqueue_script(
537 'elementor-import-export-admin',
538 $this->get_js_assets_url( 'import-export-admin' ),
539 [ 'elementor-common' ],
540 ELEMENTOR_VERSION,
541 true
542 );
543
544 wp_localize_script(
545 'elementor-import-export-admin',
546 'elementorImportExport',
547 [
548 'lastImportedSession' => $this->revert->get_last_import_session(),
549 'appUrl' => Plugin::$instance->app->get_base_url() . '#/kit-library',
550 ]
551 );
552
553 wp_enqueue_script(
554 'import-export-customization-admin',
555 $this->get_js_assets_url( 'import-export-customization-admin' ),
556 [ 'elementor-common' ],
557 ELEMENTOR_VERSION,
558 true
559 );
560 }
561
562 protected function get_remote_kit_zip( $url ) {
563 $remote_zip_request = wp_safe_remote_get( $url );
564
565 if ( is_wp_error( $remote_zip_request ) ) {
566 Plugin::$instance->logger->get_logger()->error( $remote_zip_request->get_error_message() );
567 throw new \Error( static::KIT_LIBRARY_ERROR_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
568 }
569
570 if ( 200 !== $remote_zip_request['response']['code'] ) {
571 Plugin::$instance->logger->get_logger()->error( $remote_zip_request['response']['message'] );
572 throw new \Error( static::KIT_LIBRARY_ERROR_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
573 }
574
575 return Plugin::$instance->uploads_manager->create_temp_file( $remote_zip_request['body'], 'kit.zip' );
576 }
577
578 /**
579 * Get config data that will be exposed to the frontend.
580 */
581 private function get_config_data() {
582 $export_nonce = wp_create_nonce( 'elementor_export' );
583 $export_url = add_query_arg( [ '_nonce' => $export_nonce ], Plugin::$instance->app->get_base_url() );
584
585 return [
586 'exportURL' => $export_url,
587 'summaryTitles' => $this->get_summary_titles(),
588 'builtinWpPostTypes' => ImportExportUtils::get_builtin_wp_post_types(),
589 'elementorPostTypes' => ImportExportUtils::get_elementor_post_types(),
590 'isUnfilteredFilesEnabled' => Uploads_Manager::are_unfiltered_uploads_enabled(),
591 'elementorHomePageUrl' => $this->get_elementor_home_page_url(),
592 'recentlyEditedElementorPageUrl' => $this->get_recently_edited_elementor_page_url(),
593 'tools_url' => Tools::get_url(),
594 'importSessions' => Revert::get_import_sessions(),
595 'lastImportedSession' => $this->revert->get_last_import_session(),
596 'kitPreviewNonce' => wp_create_nonce( 'kit_thumbnail' ),
597 'restApiBaseUrl' => Controller::get_base_url(),
598 'uiTheme' => $this->get_elementor_ui_theme_preference(),
599 'exportGroups' => $this->get_export_groups(),
600 'manifestVersion' => self::FORMAT_VERSION,
601 'elementorVersion' => ELEMENTOR_VERSION,
602 'upgradeVersionUrl' => admin_url( 'plugins.php' ),
603 ];
604 }
605
606 private function get_elementor_ui_theme_preference() {
607 $editor_preferences = SettingsManager::get_settings_managers( 'editorPreferences' );
608
609 return $editor_preferences->get_model()->get_settings( 'ui_theme' );
610 }
611
612 private function get_export_groups() {
613 $export_groups = [];
614 $document_types = Plugin::$instance->documents->get_document_types();
615
616 foreach ( $document_types as $name => $document_type ) {
617 $export_groups[ $name ] = defined( $document_type . '::EXPORT_GROUP' ) ? $document_type::EXPORT_GROUP : '';
618 }
619
620 return $export_groups;
621 }
622
623 /**
624 * Get labels of Elementor document types, Elementor Post types, WordPress Post types and Custom Post types.
625 */
626 private function get_summary_titles() {
627 $summary_titles = [];
628
629 $document_types = Plugin::$instance->documents->get_document_types();
630
631 foreach ( $document_types as $name => $document_type ) {
632 $summary_titles['templates'][ $name ] = [
633 'single' => $document_type::get_title(),
634 'plural' => $document_type::get_plural_title(),
635 ];
636 }
637
638 $elementor_post_types = ImportExportUtils::get_elementor_post_types();
639 $wp_builtin_post_types = ImportExportUtils::get_builtin_wp_post_types();
640 $post_types = array_merge( $elementor_post_types, $wp_builtin_post_types );
641
642 foreach ( $post_types as $post_type ) {
643 $post_type_object = get_post_type_object( $post_type );
644
645 $summary_titles['content'][ $post_type ] = [
646 'single' => $post_type_object->labels->singular_name ?? '',
647 'plural' => $post_type_object->label ?? '',
648 ];
649 }
650
651 $custom_post_types = ImportExportUtils::get_registered_cpt_names();
652 if ( ! empty( $custom_post_types ) ) {
653 foreach ( $custom_post_types as $custom_post_type ) {
654
655 $custom_post_types_object = get_post_type_object( $custom_post_type );
656 // CPT data appears in two arrays:
657 // 1. content object: in order to show the export summary when completed in getLabel function
658 $summary_titles['content'][ $custom_post_type ] = [
659 'single' => $custom_post_types_object->labels->singular_name ?? '',
660 'plural' => $custom_post_types_object->label ?? '',
661 ];
662
663 // 2. customPostTypes object: in order to actually export the data
664 $summary_titles['content']['customPostTypes'][ $custom_post_type ] = [
665 'single' => $custom_post_types_object->labels->singular_name ?? '',
666 'plural' => $custom_post_types_object->label ?? '',
667 ];
668 }
669 }
670
671 return $summary_titles;
672 }
673
674 private function get_elementor_editor_home_page_url() {
675 if ( 'page' !== get_option( 'show_on_front' ) ) {
676 return '';
677 }
678
679 $frontpage_id = get_option( 'page_on_front' );
680
681 return $this->get_elementor_editor_page_url( $frontpage_id );
682 }
683
684 private function get_elementor_home_page_url() {
685 if ( 'page' !== get_option( 'show_on_front' ) ) {
686 return '';
687 }
688
689 $frontpage_id = get_option( 'page_on_front' );
690
691 return $this->get_elementor_page_url( $frontpage_id );
692 }
693
694 private function get_recently_edited_elementor_page_url() {
695 $query = ElementorUtils::get_recently_edited_posts_query( [ 'posts_per_page' => 1 ] );
696
697 if ( ! isset( $query->post ) ) {
698 return '';
699 }
700
701 return $this->get_elementor_page_url( $query->post->ID );
702 }
703
704 private function get_recently_edited_elementor_editor_page_url() {
705 $query = ElementorUtils::get_recently_edited_posts_query( [ 'posts_per_page' => 1 ] );
706
707 if ( ! isset( $query->post ) ) {
708 return '';
709 }
710
711 return $this->get_elementor_editor_page_url( $query->post->ID );
712 }
713
714 private function get_elementor_document( $page_id ) {
715 $document = Plugin::$instance->documents->get( $page_id );
716
717 if ( ! $document || ! $document->is_built_with_elementor() ) {
718 return false;
719 }
720
721 return $document;
722 }
723
724 private function get_elementor_page_url( $page_id ) {
725 $document = $this->get_elementor_document( $page_id );
726
727 return $document ? $document->get_preview_url() : '';
728 }
729
730 private function get_elementor_editor_page_url( $page_id ) {
731 $document = $this->get_elementor_document( $page_id );
732
733 return $document ? $document->get_edit_url() : '';
734 }
735
736 /**
737 * @param string $class
738 *
739 * @return bool
740 */
741 public function is_third_party_class( $class ) {
742 $allowed_classes = [
743 'Elementor\\',
744 'ElementorPro\\',
745 'WP_',
746 'wp_',
747 ];
748
749 foreach ( $allowed_classes as $allowed_class ) {
750 if ( str_starts_with( $class, $allowed_class ) ) {
751 return false;
752 }
753 }
754
755 return true;
756 }
757 }
758