PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta3
Elementor Website Builder – more than just a page builder v4.3.0-beta3
4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 All 452 releases
elementor / app / modules / import-export-customization / processes / import.php

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

860 lines 26.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\App\Modules\ImportExportCustomization\Processes;
4
5 use Elementor\App\Modules\ImportExportCustomization\Compatibility\Base_Adapter;
6 use Elementor\App\Modules\ImportExportCustomization\Compatibility\Envato;
7 use Elementor\App\Modules\ImportExportCustomization\Compatibility\Kit_Library;
8 use Elementor\App\Modules\ImportExportCustomization\Compatibility\Customization;
9 use Elementor\App\Modules\ImportExportCustomization\Utils;
10 use Elementor\Core\Base\Document;
11 use Elementor\Core\Kits\Documents\Kit;
12 use Elementor\Modules\AtomicWidgets\Utils\Atomic_Prop_Remap;
13 use Elementor\Modules\Components\Module as Components_Module;
14 use Elementor\Plugin;
15
16 use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Elementor_Content;
17 use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Import_Runner_Base;
18 use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Plugins;
19 use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Site_Settings;
20 use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Taxonomies;
21 use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Templates;
22 use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Wp_Content;
23 use Elementor\App\Modules\ImportExportCustomization\Module;
24 use Elementor\App\Modules\ImportExportCustomization\Runners\Import\Floating_Elements;
25
26 class Import {
27 const MANIFEST_ERROR_KEY = 'manifest-error';
28
29 const ZIP_FILE_ERROR_KEY = 'invalid-zip-file';
30
31 const ZIP_ARCHIVE_ERROR_KEY = 'zip-archive-module-missing';
32
33 /**
34 * @var Import_Runner_Base[]
35 */
36 protected $runners = [];
37
38 /**
39 * The session ID of the import process.
40 * This ID is uniquely generated for each import process (by the temp folder which contains the extracted kit files).
41 *
42 * @var string
43 */
44 private $session_id;
45
46 /**
47 * The Kit ID.
48 *
49 * @var string
50 */
51 private $kit_id;
52
53 /**
54 * Adapter for the kit compatibility.
55 *
56 * @var Base_Adapter[]
57 */
58 private $adapters;
59
60 /**
61 * Document's data (elements and settings) that was imported during the process.
62 *
63 * @var array { [document_id] => { "elements": array , "settings": array } }
64 */
65 private $documents_data = [];
66
67 /**
68 * Path to the extracted kit files.
69 *
70 * @var string
71 */
72 private $extracted_directory_path;
73
74 /**
75 * Imported kit manifest.
76 *
77 * @var array
78 */
79 private $manifest;
80
81 /**
82 * Imported kit site settings. (e.g: custom_colors, custom_typography, etc.)
83 *
84 * @var array
85 */
86 private $site_settings;
87
88 /**
89 * Selected content types to import.
90 *
91 * @var array
92 */
93 private $settings_include;
94
95 /**
96 * Referer of the import. (e.g: kit-library, local, etc.)
97 *
98 * @var string
99 */
100 private $settings_referrer;
101
102 /**
103 * All the conflict between the exited templates and the kit templates.
104 *
105 * @var array
106 */
107 private $settings_conflicts;
108
109 /**
110 * Selected elementor templates conditions to override.
111 *
112 * @var array
113 */
114 private $settings_selected_override_conditions;
115
116 /**
117 * Selected custom post types to import.
118 *
119 * @var array
120 */
121 private $settings_selected_custom_post_types;
122
123 /**
124 * Selected plugins to import.
125 *
126 * @var array
127 */
128 private $settings_selected_plugins;
129
130 /**
131 * Customization settings for selective import.
132 *
133 * @var array
134 */
135 private $settings_customization;
136
137 /**
138 * The imported data output.
139 *
140 * @var array
141 */
142 private $imported_data = [];
143
144 /**
145 * The metadata output of the import runners.
146 * Will be saved in the import_session and will be used to revert the import process.
147 *
148 * @var array
149 */
150 private $runners_import_metadata = [];
151
152 /**
153 * @param string $path session_id | zip_file_path
154 * @param array $settings Use to determine which content to import.
155 * (e.g: include, selected_plugins, selected_cpt, selected_override_conditions, etc.)
156 * @param array|null $old_instance An array of old instance parameters that will be used for creating new instance.
157 * We are using it for quick creation of the instance when the import process is being split into chunks.
158 * @throws \Exception If the import session does not exist.
159 */
160 public function __construct( string $path, array $settings = [], array $old_instance = null ) {
161 if ( ! empty( $old_instance ) ) {
162 $this->set_import_object( $old_instance );
163 } else {
164 if ( is_file( $path ) ) {
165 $this->extracted_directory_path = $this->extract_zip( $path );
166 } else {
167 $elementor_tmp_directory = Plugin::$instance->uploads_manager->get_temp_dir();
168 $path = $elementor_tmp_directory . basename( $path );
169
170 if ( ! is_dir( $path ) ) {
171 throw new \Exception( 'Couldn’t execute the import process because the import session does not exist.' );
172 }
173
174 $this->extracted_directory_path = $path . '/';
175 }
176
177 $this->session_id = basename( $this->extracted_directory_path );
178 $this->kit_id = $settings['id'] ?? '';
179 $this->settings_referrer = ! empty( $settings['referrer'] ) ? $settings['referrer'] : 'local';
180 $this->settings_include = ! empty( $settings['include'] ) ? $settings['include'] : null;
181
182 // Using isset and not empty is important since empty array is valid option.
183 $this->settings_selected_override_conditions = $settings['customization']['templates']['themeBuilder']['overrideConditions'] ?? null;
184 $this->settings_selected_custom_post_types = $settings['customization']['content']['customPostTypes'] ?? null;
185 $this->settings_selected_plugins = $settings['plugins'] ?? null;
186 $this->settings_customization = $settings['customization'] ?? null;
187
188 $this->manifest = $this->read_manifest_json();
189 $this->site_settings = $this->read_site_settings_json();
190
191 $this->set_default_settings();
192 }
193
194 add_filter( 'wp_php_error_args', function ( $args, $error ) {
195 return $this->filter_php_error_args( $args, $error );
196 }, 10, 2 );
197 }
198
199 /**
200 * Set the import object parameters.
201 *
202 * @param array $instance
203 * @return void
204 */
205 private function set_import_object( array $instance ) {
206 $this->session_id = $instance['session_id'];
207
208 $instance_data = $instance['instance_data'];
209
210 $this->extracted_directory_path = $instance_data['extracted_directory_path'];
211 $this->runners = $instance_data['runners'];
212 $this->adapters = $instance_data['adapters'];
213
214 $this->manifest = $instance_data['manifest'];
215 $this->site_settings = $instance_data['site_settings'];
216
217 $this->kit_id = $instance_data['kit_id'] ?? '';
218 $this->settings_include = $instance_data['settings_include'];
219 $this->settings_referrer = $instance_data['settings_referrer'];
220 $this->settings_conflicts = $instance_data['settings_conflicts'];
221 $this->settings_selected_override_conditions = $instance_data['settings_selected_override_conditions'];
222 $this->settings_selected_custom_post_types = $instance_data['settings_selected_custom_post_types'];
223 $this->settings_selected_plugins = $instance_data['settings_selected_plugins'];
224 $this->settings_customization = $instance_data['settings_customization'];
225
226 $this->documents_data = $instance_data['documents_data'];
227 $this->imported_data = $instance_data['imported_data'];
228 $this->runners_import_metadata = $instance_data['runners_import_metadata'];
229 }
230
231 /**
232 * Creating a new instance of the import process by the id of the old import session.
233 *
234 * @param string $session_id
235 *
236 * @return Import
237 * @throws \Exception If the import session does not exist.
238 */
239 public static function from_session( string $session_id ): Import {
240 $import_sessions = Utils::get_import_sessions();
241
242 if ( ! $import_sessions || ! isset( $import_sessions[ $session_id ] ) ) {
243 throw new \Exception( 'Couldn’t execute the import process because the import session does not exist.' );
244 }
245
246 $import_session = $import_sessions[ $session_id ];
247
248 return new self( $session_id, [], $import_session );
249 }
250
251 /**
252 * Register a runner.
253 * Be aware that the runner will be executed in the order of registration, the order is crucial for the import process.
254 *
255 * @param Import_Runner_Base $runner_instance
256 */
257 public function register( Import_Runner_Base $runner_instance ) {
258 $this->runners[ $runner_instance::get_name() ] = $runner_instance;
259 }
260
261 public function register_default_runners() {
262 $this->register( new Site_Settings() );
263 $this->register( new Plugins() );
264 $this->register( new Templates() );
265 $this->register( new Taxonomies() );
266 $this->register( new Elementor_Content() );
267 $this->register( new Wp_Content() );
268 $this->register( new Floating_Elements() );
269 }
270
271 /**
272 * Set default settings for the import.
273 */
274 private function set_default_settings() {
275 if ( ! is_array( $this->get_settings_include() ) ) {
276 $this->settings_include( $this->get_default_settings_include() );
277 }
278
279 if ( ! is_array( $this->get_settings_conflicts() ) ) {
280 $this->settings_conflicts( $this->get_default_settings_conflicts() );
281 }
282
283 if ( ! is_array( $this->get_settings_selected_override_conditions() ) ) {
284 $this->settings_selected_override_conditions( $this->get_default_settings_override_conditions() );
285 }
286
287 if ( ! is_array( $this->get_settings_selected_custom_post_types() ) ) {
288 $this->settings_selected_custom_post_types( $this->get_default_settings_custom_post_types() );
289 }
290
291 if ( ! is_array( $this->get_settings_selected_plugins() ) ) {
292 $this->settings_selected_plugins( $this->get_default_settings_plugins() );
293 }
294
295 if ( ! is_array( $this->get_settings_customization() ) ) {
296 $this->settings_customization( $this->get_default_settings_customization() );
297 }
298 }
299
300 /**
301 * Execute the import process.
302 *
303 * @return array The imported data output.
304 *
305 * @throws \Exception If no import runners have been specified.
306 */
307 public function run() {
308 if ( empty( $this->runners ) ) {
309 throw new \Exception( 'Couldn’t execute the import process because no import runners have been specified. Try again by specifying import runners.' );
310 }
311
312 $data = $this->build_runner_data();
313
314 $this->init_import_session();
315
316 remove_filter( 'elementor/document/save/data', [ Plugin::$instance->modules_manager->get_modules( 'content-sanitizer' ), 'sanitize_content' ] );
317 add_filter( 'elementor/document/save/data', [ $this, 'prevent_saving_elements_on_post_creation' ], 10, 2 );
318
319 // Set the Request's state as an Elementor upload request, in order to support unfiltered file uploads.
320 Plugin::$instance->uploads_manager->set_elementor_upload_state( true );
321
322 foreach ( $this->runners as $runner ) {
323 if ( $runner->should_import( $data ) ) {
324 $import = $runner->import( $data, $this->imported_data );
325 $this->imported_data = array_merge_recursive( $this->imported_data, $import );
326
327 $this->runners_import_metadata[ $runner::get_name() ] = $runner->get_import_session_metadata();
328 }
329 }
330
331 // After the upload complete, set the elementor upload state back to false.
332 Plugin::$instance->uploads_manager->set_elementor_upload_state( false );
333
334 remove_filter( 'elementor/document/save/data', [ $this, 'prevent_saving_elements_on_post_creation' ], 10 );
335
336 $this->finalize_import_session_option();
337
338 $this->save_elements_of_imported_posts();
339
340 Plugin::$instance->uploads_manager->remove_file_or_dir( $this->extracted_directory_path );
341 return $this->imported_data;
342 }
343
344 /**
345 * Run specific runner by runner_name
346 *
347 * @param string $runner_name
348 *
349 * @return array
350 *
351 * @throws \Exception If no export runners have been specified.
352 */
353 public function run_runner( string $runner_name ): array {
354 if ( empty( $this->runners ) ) {
355 throw new \Exception( 'Couldn’t execute the import process because no import runners have been specified. Try again by specifying import runners.' );
356 }
357
358 $data = $this->build_runner_data();
359
360 add_filter( 'elementor/document/save/data', [ $this, 'prevent_saving_elements_on_post_creation' ], 10, 2 );
361
362 // Set the Request's state as an Elementor upload request, in order to support unfiltered file uploads.
363 Plugin::$instance->uploads_manager->set_elementor_upload_state( true );
364
365 $runner = $this->runners[ $runner_name ];
366
367 if ( empty( $runner ) ) {
368 throw new \Exception( 'Couldn’t execute the import process because the import runner was not found. Try again by specifying an import runner.' );
369 }
370
371 if ( $runner->should_import( $data ) ) {
372 $import = $runner->import( $data, $this->imported_data );
373 $this->imported_data = array_merge_recursive( $this->imported_data, $import );
374
375 $this->runners_import_metadata[ $runner::get_name() ] = $runner->get_import_session_metadata();
376 }
377
378 // After the upload complete, set the elementor upload state back to false.
379 Plugin::$instance->uploads_manager->set_elementor_upload_state( false );
380
381 remove_filter( 'elementor/document/save/data', [ $this, 'prevent_saving_elements_on_post_creation' ], 10 );
382
383 $is_last_runner = key( array_slice( $this->runners, -1, 1, true ) ) === $runner_name;
384 if ( $is_last_runner ) {
385 $this->finalize_import_session_option();
386 $this->save_elements_of_imported_posts();
387 } else {
388 $this->update_instance_data_in_import_session_option();
389 }
390
391 return [
392 'status' => 'success',
393 'runner' => $runner_name,
394 'imported_data' => $this->imported_data,
395 ];
396 }
397
398 /**
399 * Create and save all the instance data to the import sessions option.
400 *
401 * @return void
402 */
403 public function init_import_session( $save_instance_data = false ) {
404 $import_sessions = Utils::get_import_sessions( true );
405 $existing_session = $import_sessions[ $this->session_id ] ?? [];
406
407 $import_sessions[ $this->session_id ] = [
408 'session_id' => $this->session_id,
409 'kit_title' => $this->manifest['title'] ?? '',
410 'kit_name' => $this->manifest['name'] ?? '',
411 'kit_thumbnail' => $existing_session['kit_thumbnail'] ?? $this->get_kit_thumbnail(),
412 'kit_source' => $existing_session['kit_source'] ?? $this->settings_referrer,
413 'user_id' => get_current_user_id(),
414 'start_timestamp' => $existing_session['start_timestamp'] ?? current_time( 'timestamp' ),
415 ];
416
417 if ( $save_instance_data ) {
418 $import_sessions[ $this->session_id ]['instance_data'] = [
419 'extracted_directory_path' => $this->extracted_directory_path,
420 'runners' => $this->runners,
421 'adapters' => $this->adapters,
422
423 'manifest' => $this->manifest,
424 'site_settings' => $this->site_settings,
425
426 'kit_id' => $this->kit_id,
427 'settings_include' => $this->settings_include,
428 'settings_referrer' => $this->settings_referrer,
429 'settings_conflicts' => $this->settings_conflicts,
430 'settings_selected_override_conditions' => $this->settings_selected_override_conditions,
431 'settings_selected_custom_post_types' => $this->settings_selected_custom_post_types,
432 'settings_selected_plugins' => $this->settings_selected_plugins,
433 'settings_customization' => $this->settings_customization,
434
435 'documents_data' => $this->documents_data,
436 'imported_data' => $this->imported_data,
437 'runners_import_metadata' => $this->runners_import_metadata,
438 ];
439 }
440
441 update_option( Module::OPTION_KEY_ELEMENTOR_IMPORT_SESSIONS, $import_sessions, false );
442 }
443
444 /**
445 * Get the Kit thumbnail, goes to the home page thumbnail if main doesn't exist
446 *
447 * @return string
448 */
449 private function get_kit_thumbnail(): string {
450 if ( ! empty( $this->manifest['thumbnail'] ) ) {
451 return $this->manifest['thumbnail'];
452 }
453
454 return apply_filters( 'elementor/import/kit_thumbnail', '', $this->kit_id, $this->settings_referrer );
455 }
456
457 public function get_runners_name(): array {
458 $data = $this->build_runner_data();
459
460 return array_keys( array_filter(
461 $this->runners,
462 fn( $runner ) => $runner->should_import( $data )
463 ) );
464 }
465
466 private function build_runner_data(): array {
467 return [
468 'session_id' => $this->session_id,
469 'include' => $this->settings_include,
470 'manifest' => $this->manifest,
471 'site_settings' => $this->site_settings,
472 'selected_plugins' => $this->settings_selected_plugins,
473 'customization' => $this->settings_customization,
474 'extracted_directory_path' => $this->extracted_directory_path,
475 'selected_custom_post_types' => $this->settings_selected_custom_post_types,
476 ];
477 }
478
479 public function get_manifest() {
480 return $this->manifest;
481 }
482
483 public function get_extracted_directory_path() {
484 return $this->extracted_directory_path;
485 }
486
487 public function get_session_id() {
488 return $this->session_id;
489 }
490
491 public function get_adapters() {
492 return $this->adapters;
493 }
494
495 public function get_imported_data() {
496 return $this->imported_data;
497 }
498
499 /**
500 * Get settings by key.
501 * Used for backward compatibility.
502 *
503 * @param string $key The key of the setting.
504 */
505 public function get_settings( $key ) {
506 switch ( $key ) {
507 case 'include':
508 return $this->get_settings_include();
509
510 case 'overrideConditions':
511 return $this->get_settings_selected_override_conditions();
512
513 case 'selectedCustomPostTypes':
514 return $this->get_settings_selected_custom_post_types();
515
516 case 'plugins':
517 return $this->get_settings_selected_plugins();
518
519 case 'customization':
520 return $this->get_settings_customization();
521
522 default:
523 return [];
524 }
525 }
526
527 public function settings_include( array $settings_include ) {
528 $this->settings_include = $settings_include;
529
530 return $this;
531 }
532
533 public function get_settings_include() {
534 return $this->settings_include;
535 }
536
537 public function settings_referrer( $settings_referrer ) {
538 $this->settings_referrer = $settings_referrer;
539
540 return $this;
541 }
542
543 public function get_settings_referrer() {
544 return $this->settings_referrer;
545 }
546
547 public function settings_conflicts( array $settings_conflicts ) {
548 $this->settings_conflicts = $settings_conflicts;
549
550 return $this;
551 }
552
553 public function get_settings_conflicts() {
554 return $this->settings_conflicts;
555 }
556
557 public function settings_selected_override_conditions( array $settings_selected_override_conditions ) {
558 $this->settings_selected_override_conditions = $settings_selected_override_conditions;
559
560 return $this;
561 }
562
563 public function get_settings_selected_override_conditions() {
564 return $this->settings_selected_override_conditions;
565 }
566
567 public function settings_selected_custom_post_types( array $settings_selected_custom_post_types ) {
568 $this->settings_selected_custom_post_types = $settings_selected_custom_post_types;
569
570 return $this;
571 }
572
573 public function get_settings_selected_custom_post_types() {
574 return $this->settings_selected_custom_post_types;
575 }
576
577 public function settings_selected_plugins( array $settings_selected_plugins ) {
578 $this->settings_selected_plugins = $settings_selected_plugins;
579
580 return $this;
581 }
582
583 public function get_settings_selected_plugins() {
584 return $this->settings_selected_plugins;
585 }
586
587 /**
588 * Prevent saving elements on elementor post creation.
589 *
590 * @param array $data
591 * @param Document $document
592 *
593 * @return array
594 */
595 public function prevent_saving_elements_on_post_creation( array $data, Document $document ) {
596 if ( isset( $data['elements'] ) ) {
597 $this->documents_data[ $document->get_main_id() ] = [ 'elements' => $data['elements'] ];
598
599 $data['elements'] = [];
600 }
601
602 if ( isset( $data['settings'] ) ) {
603 $this->documents_data[ $document->get_main_id() ]['settings'] = $data['settings'];
604
605 }
606
607 return $data;
608 }
609
610 /**
611 * Extract the zip file.
612 *
613 * @param string $zip_path The path to the zip file.
614 * @return string The extracted directory path.
615 * @throws \Error If import process fails, file validation errors occur, or data corruption is detected.
616 */
617 private function extract_zip( $zip_path ) {
618 $extraction_result = Plugin::$instance->uploads_manager->extract_and_validate_zip( $zip_path, [ 'json', 'xml' ] );
619
620 if ( is_wp_error( $extraction_result ) ) {
621 if ( isset( $extraction_result->errors['zip_error'] ) ) {
622 throw new \Error( static::ZIP_ARCHIVE_ERROR_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
623 }
624
625 throw new \Error( static::ZIP_FILE_ERROR_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
626 }
627
628 return $extraction_result['extraction_directory'];
629 }
630
631 /**
632 * Get the manifest file from the extracted directory and adapt it if needed.
633 *
634 * @return string The manifest file content.
635 * @throws \Error If import validation fails or processing errors occur.
636 */
637 private function read_manifest_json() {
638 $manifest = Utils::read_json_file( $this->extracted_directory_path . 'manifest' );
639
640 if ( ! $manifest ) {
641 Plugin::$instance->logger->get_logger()->error( static::MANIFEST_ERROR_KEY );
642 throw new \Error( static::ZIP_FILE_ERROR_KEY ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
643 }
644
645 $this->init_adapters( $manifest );
646
647 foreach ( $this->adapters as $adapter ) {
648 $manifest = $adapter->adapt_manifest( $manifest );
649 }
650
651 return $manifest;
652 }
653
654 /**
655 * Init the adapters and determine which ones to use.
656 *
657 * @param array $manifest_data The manifest file content.
658 */
659 private function init_adapters( array $manifest_data ) {
660 $this->adapters = [];
661
662 /** @var Base_Adapter[] $adapter_types */
663 $adapter_types = [ Customization::class, Envato::class, Kit_Library::class ];
664
665 foreach ( $adapter_types as $adapter_type ) {
666 if ( $adapter_type::is_compatibility_needed( $manifest_data, [ 'referrer' => $this->get_settings_referrer() ] ) ) {
667 $this->adapters[] = new $adapter_type( $this );
668 }
669 }
670 }
671
672 /**
673 * Get the site settings file from the extracted directory and adapt it if needed.
674 *
675 * @return string The site settings file content.
676 */
677 private function read_site_settings_json() {
678 $site_settings = Utils::read_json_file( $this->extracted_directory_path . 'site-settings' );
679
680 foreach ( $this->adapters as $adapter ) {
681 $site_settings = $adapter->adapt_site_settings( $site_settings, $this->manifest, $this->extracted_directory_path );
682 }
683
684 return $site_settings;
685 }
686
687 /**
688 * Get all the custom post types in the kit.
689 *
690 * @return array Custom post types names.
691 */
692 private function get_default_settings_custom_post_types() {
693 $excluded = [ 'page', 'nav_menu_item' ];
694
695 if ( empty( $this->manifest['content']['post'] ?? [] ) && empty( $this->manifest['wp-content']['post'] ?? [] ) ) {
696 $excluded[] = 'post';
697 }
698
699 $manifest_post_types = array_keys( $this->manifest['custom-post-type-title'] ?? [] );
700
701 return array_merge( $manifest_post_types, Utils::get_builtin_wp_post_types( $excluded ) );
702 }
703
704 /**
705 * Get the default settings of elementor templates conditions to override.
706 *
707 * @return array
708 */
709 private function get_default_settings_conflicts() {
710 if ( empty( $this->manifest['templates'] ) ) {
711 return [];
712 }
713
714 return apply_filters( 'elementor/import/get_default_settings_conflicts', [], $this->manifest['templates'] );
715 }
716
717 /**
718 * Get the default settings of elementor templates conditions to override.
719 *
720 * @return array
721 */
722 private function get_default_settings_override_conditions() {
723 if ( empty( $this->settings_conflicts ) ) {
724 return [];
725 }
726
727 return array_keys( $this->settings_conflicts );
728 }
729
730 /**
731 * Get the default settings of the plugins that should be imported.
732 *
733 * @return array
734 */
735 private function get_default_settings_plugins() {
736 return ! empty( $this->manifest['plugins'] ) ? $this->manifest['plugins'] : [];
737 }
738
739 /**
740 * Get the default settings of which content types should be imported.
741 *
742 * @return array
743 */
744 private function get_default_settings_include() {
745 return [ 'templates', 'plugins', 'content', 'settings' ];
746 }
747
748 public function settings_customization( $customization ) {
749 $this->settings_customization = $customization;
750 return $this;
751 }
752
753 public function get_settings_customization() {
754 return $this->settings_customization;
755 }
756
757 private function get_default_settings_customization() {
758 return [
759 'settings' => null,
760 'templates' => null,
761 'content' => null,
762 'plugins' => null,
763 ];
764 }
765
766 /**
767 * Get the data that requires updating/replacement when imported.
768 *
769 * @return array{post_ids: array, term_ids: array}
770 */
771 private function get_imported_data_replacements(): array {
772 return [
773 'post_ids' => Utils::map_old_new_post_ids( $this->imported_data ),
774 'term_ids' => Utils::map_old_new_term_ids( $this->imported_data ),
775 ];
776 }
777
778 /**
779 * Save the prevented elements on elementor post creation elements.
780 * Handle the replacement of all the dynamic content of the elements that probably have been changed during the import.
781 */
782 private function save_elements_of_imported_posts() {
783 $imported_data_replacements = $this->get_imported_data_replacements();
784
785 foreach ( $this->documents_data as $new_id => $data ) {
786 $document = Plugin::$instance->documents->get( $new_id );
787
788 if ( isset( $data['elements'] ) ) {
789 $data['elements'] = Components_Module::prepare_imported_elements( $data['elements'], $imported_data_replacements['post_ids'] ?? [] );
790 $data['elements'] = Atomic_Prop_Remap::apply( $data['elements'], $imported_data_replacements );
791 $this->merge_atomic_prop_remap_warnings( Atomic_Prop_Remap::consume_warnings() );
792 $data['elements'] = $document->on_import_update_dynamic_content( $data['elements'], $imported_data_replacements );
793 }
794
795 if ( isset( $data['settings'] ) ) {
796
797 if ( $document instanceof Kit ) {
798 // Without post_status certain tabs in the Kit will not save properly.
799 $data['settings']['post_status'] = get_post_status( $new_id );
800 }
801
802 $data['settings'] = $document->on_import_update_settings( $data['settings'], $imported_data_replacements );
803 }
804
805 $document->save( $data );
806 }
807 }
808
809 private function merge_atomic_prop_remap_warnings( array $warnings ): void {
810 if ( empty( $warnings ) ) {
811 return;
812 }
813
814 $existing = $this->runners_import_metadata['atomic_prop_remap']['warnings'] ?? [];
815 $this->runners_import_metadata['atomic_prop_remap'] = [
816 'warnings' => array_merge( $existing, $warnings ),
817 ];
818 }
819
820 private function update_instance_data_in_import_session_option() {
821 $import_sessions = Utils::get_import_sessions();
822
823 $import_sessions[ $this->session_id ]['instance_data']['documents_data'] = $this->documents_data;
824 $import_sessions[ $this->session_id ]['instance_data']['imported_data'] = $this->imported_data;
825 $import_sessions[ $this->session_id ]['instance_data']['runners_import_metadata'] = $this->runners_import_metadata;
826
827 update_option( Module::OPTION_KEY_ELEMENTOR_IMPORT_SESSIONS, $import_sessions, false );
828 }
829
830 public function finalize_import_session_option() {
831 $import_sessions = Utils::get_import_sessions();
832
833 if ( ! isset( $import_sessions[ $this->session_id ] ) ) {
834 return;
835 }
836
837 unset( $import_sessions[ $this->session_id ]['instance_data'] );
838
839 $import_sessions[ $this->session_id ]['end_timestamp'] = current_time( 'timestamp' );
840 $import_sessions[ $this->session_id ]['runners'] = $this->runners_import_metadata;
841
842 update_option( Module::OPTION_KEY_ELEMENTOR_IMPORT_SESSIONS, $import_sessions, false );
843 }
844
845 /**
846 * Filter the php error args and return 408 status code if the error is a timeout.
847 *
848 * @param array $args
849 * @param array $error
850 * @return array
851 */
852 private function filter_php_error_args( $args, $error ) {
853 if ( strpos( $error['message'], 'Maximum execution time' ) !== false ) {
854 $args['response'] = 408;
855 }
856
857 return $args;
858 }
859 }
860