PluginProbe
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets / 4.5.4
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets v4.5.4
4.5.4 4.2.1 4.2.2 4.2.3 4.5.0 4.5.2 4.5.3 4.2.0 4.1.18 4.1.17 4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 All 146 releases
ultimate-post-kit / includes / setup-wizard / init.php

init.php in Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets 4.5.4, at includes/setup-wizard/init.php

680 lines 22.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace UltimatePostKit\Includes;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 // Load the Remote Data Handler
10 require_once __DIR__ . '/class-remote-data-handler.php';
11
12 use UltimatePostKit\Admin\ModuleService;
13 use Elementor\Plugin;
14 /**
15 * Overwrite the feedback method in the WP_Upgrader_Skin
16 * to suppress the normal feedback.
17 */
18
19 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
20
21 class Quiet_Upgrader_Skin extends \WP_Upgrader_Skin {
22 /*
23 * Suppress normal upgrader feedback / output
24 */
25 public function feedback( $string, ...$args ) {
26 /* no output */
27 }
28 }
29
30
31 class Setup_Wizard {
32
33 // Singleton instance
34 private static $instance = null;
35
36 // Constructor
37 private function __construct() {
38 $this->init_hooks();
39 }
40
41 // Get instance
42 public static function get_instance() {
43 if ( self::$instance == null ) {
44 self::$instance = new self();
45 }
46 return self::$instance;
47 }
48
49 // Initialize hooks
50 private function init_hooks() {
51 add_action( 'wp_ajax_ultimate_post_kit_setup_wizard_install_plugins', array( $this, 'install_plugins' ) );
52 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
53 add_action( 'admin_init', array( $this, 'activate_default_widgets' ) );
54 add_action( 'admin_init', array( $this, 'maybe_display_setup_wizard' ) );
55 add_action( 'admin_init', array( $this, 'check_manual_wizard_request' ) );
56
57 // NOTE: WordPress manages plugin/translation updates. Do not add filters
58 // that interfere with the built-in update pipeline (wp.org Guideline).
59 }
60
61 // Check for manual wizard requests
62 public function check_manual_wizard_request() {
63 // This runs on admin_init, which also fires on admin-ajax.php before any
64 // authentication, and on every admin screen for every logged-in role. The setup
65 // wizard is an administrator-only flow, so gate it explicitly.
66 if ( wp_doing_ajax() || ! current_user_can( 'manage_options' ) ) {
67 return;
68 }
69
70 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check of a GET flag to decide whether to render the setup wizard screen, no form data processed.
71 $is_setup_wizard_request = isset($_GET['upk_setup_wizard']) && $_GET['upk_setup_wizard'] === 'show';
72
73 if ( $is_setup_wizard_request ) {
74 // Use the same approach as first activation - completely override the page
75 add_action('admin_head', function() {
76 ?>
77 <style>
78 html, body {
79 height: 100%;
80 margin: 0;
81 padding: 0;
82 overflow: hidden;
83 }
84 #wpwrap, #wpcontent, #wpbody, #wpbody-content {
85 height: 100%;
86 padding: 0;
87 margin: 0;
88 }
89 #adminmenumain, #wpadminbar {
90 display: none;
91 }
92 </style>
93 <script>
94 jQuery(document).ready(function($) {
95 $('body').addClass('bdt-setup-wizard-active');
96 });
97 </script>
98 <?php
99
100 // Display setup wizard using the same method as first activation
101 $this->display_page();
102 });
103 }
104 }
105
106 // Display wizard in fullscreen mode
107 public function display_wizard_fullscreen() {
108 ?>
109 <style>
110 html, body {
111 height: 100%;
112 margin: 0;
113 padding: 0;
114 overflow: hidden;
115 }
116 #wpwrap, #wpcontent, #wpbody, #wpbody-content {
117 height: 100%;
118 padding: 0;
119 margin: 0;
120 }
121 #adminmenumain, #wpadminbar {
122 display: none;
123 }
124 </style>
125 <?php
126 // Directly output the wizard content
127 add_action('admin_footer', function() {
128 echo '<div id="upk-setup-wizard-container">';
129 $this->display_page();
130 echo '</div>';
131 ?>
132 <script>
133 jQuery(document).ready(function($) {
134 $('body').addClass('bdt-setup-wizard-active');
135 // Hide all other content and show only our wizard
136 $('#wpbody-content').html($('#upk-setup-wizard-container').html());
137 $('#upk-setup-wizard-container').remove();
138 });
139 </script>
140 <?php
141 }, 999);
142 }
143
144 // Get wizard HTML content
145 public function get_wizard_html() {
146 ob_start();
147 ?>
148 <div class="bdt-setup-wizard-overlay upk-setup-wizard ">
149 <div class="bdt-setup-wizard content-loaded">
150 <?php
151 require_once plugin_dir_path( BDTUPK__FILE__ ) . 'includes/setup-wizard/views/render.php';
152 ?>
153 </div>
154 </div>
155 <?php
156 return ob_get_clean();
157 }
158
159 // Check if this is first activation and display setup wizard if needed
160 public function maybe_display_setup_wizard() {
161 // This runs on admin_init, which also fires on admin-ajax.php before any
162 // authentication, and on every admin screen for every logged-in role. The setup
163 // wizard is an administrator-only flow, so gate it explicitly.
164 if ( wp_doing_ajax() || ! current_user_can( 'manage_options' ) ) {
165 return;
166 }
167
168 // Only check for first activation here
169 if ( get_option( 'bdtupk_setup_wizard_completed' ) === false ) {
170 // Set the flag so it doesn't run again
171 update_option( 'bdtupk_setup_wizard_completed', true );
172
173 // Add a header to ensure proper full-page display
174 add_action('admin_head', function() {
175 ?>
176 <style>
177 html, body {
178 height: 100%;
179 margin: 0;
180 padding: 0;
181 overflow: hidden;
182 }
183 #wpwrap, #wpcontent, #wpbody, #wpbody-content {
184 height: 100%;
185 padding: 0;
186 margin: 0;
187 }
188 #adminmenumain, #wpadminbar {
189 display: none;
190 }
191 </style>
192 <script>
193 jQuery(document).ready(function($) {
194 $('body').addClass('bdt-setup-wizard-active');
195 });
196 </script>
197 <?php
198
199 // Display setup wizard
200 $this->display_page();
201 });
202 }
203 }
204
205 // Keep the admin_menu method for reference but not hooked
206 public function admin_menu() {
207 add_submenu_page(
208 'ultimate_post_kit_options',
209 esc_html__( 'Setup Wizard', 'ultimate-post-kit' ),
210 esc_html__( 'Setup Wizard', 'ultimate-post-kit' ),
211 'manage_options',
212 'ultimate-post-kit-setup-wizard',
213 array( $this, 'display_page' )
214 );
215 }
216
217 public function display_page() {
218 ?>
219 <div class="bdt-setup-wizard-overlay upk-setup-wizard">
220 <div class="bdt-setup-wizard content-loaded">
221 <?php
222 require_once plugin_dir_path( BDTUPK__FILE__ ) . 'includes/setup-wizard/views/render.php';
223 ?>
224 </div>
225 </div>
226 <?php
227 }
228
229 // Enqueue necessary scripts
230 public function enqueue_scripts() {
231
232 // Loaded on admin_enqueue_scripts for every admin screen and every role. The
233 // wizard's assets and its nonce have no business outside an administrator's
234 // wizard/settings screen.
235 if ( ! current_user_can( 'manage_options' ) ) {
236 return;
237 }
238
239
240 $direction_suffix = is_rtl() ? '.rtl' : '';
241
242 wp_enqueue_style('bdt-uikit', BDTUPK_ADMIN_ASSETS_URL . 'css/bdt-uikit' . $direction_suffix . '.css', [], '3.17.0');
243 wp_enqueue_script('bdt-uikit', BDTUPK_ADMIN_ASSETS_URL . 'js/bdt-uikit.min.js', ['jquery'], '3.17.0', true);
244
245 wp_register_script( 'upk-setup-wizard', plugins_url( 'assets/js/setup-wizard.js', __FILE__ ), array( 'jquery' ), '1.0.0', true );
246 wp_register_style( 'upk-setup-wizard', plugins_url( 'assets/css/setup-wizard.css', __FILE__ ), array(), '1.0.0' );
247
248 wp_enqueue_script( 'upk-setup-wizard' );
249 wp_enqueue_style( 'upk-setup-wizard' );
250
251 wp_localize_script(
252 'upk-setup-wizard',
253 'UPK_SetupWizard',
254 array(
255 'ajax_url' => admin_url( 'admin-ajax.php' ),
256 'nonce' => wp_create_nonce( 'ultimate_post_kit_setup_wizard_nonce' ),
257 'is_fullscreen' => true
258 )
259 );
260 }
261
262 public static function get_widget_map() {
263 $arr_obj = ModuleService::get_widget_settings(
264 function ( $settings ) {
265 $core_widgets = $settings['settings_fields']['ultimate_post_kit_active_modules'];
266 return $core_widgets;
267 }
268 );
269 return $arr_obj;
270 }
271
272 // Install plugins
273 public function install_plugins() {
274 check_ajax_referer( 'ultimate_post_kit_setup_wizard_nonce', 'nonce' );
275
276 $plugin_slugs = isset( $_POST['plugins'] ) ? map_deep( wp_unslash( $_POST['plugins'] ), 'sanitize_text_field' ) : array();
277
278 if ( empty( $plugin_slugs ) || ! is_array( $plugin_slugs ) ) {
279 wp_send_json_error( array( 'message' => 'Invalid plugins array' ) );
280 }
281
282 if ( ! current_user_can( 'install_plugins' ) ) {
283 wp_send_json_error( array( 'message' => 'Unauthorized' ) );
284 }
285
286 include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
287 include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
288 include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';
289 include_once ABSPATH . 'wp-admin/includes/plugin.php';
290
291 // Replace new \Plugin_Installer_Skin with new Quiet_Upgrader_Skin when output needs to be suppressed.
292 $skin = new Quiet_Upgrader_Skin();
293 // $skin = new \Plugin_Installer_Skin( array( 'api' => $api ) );
294 $upgrader = new \Plugin_Upgrader( $skin );
295
296 // $upgrader = new \Plugin_Upgrader();
297
298 $installedPlugins = get_plugins();
299 $results = array();
300
301 foreach ( $plugin_slugs as $plugin_slug ) {
302 // skip when the plugin is already active
303 if (is_plugin_active($plugin_slug)) {
304 $results[] = array(
305 'slug' => $plugin_slug,
306 'success' => true,
307 'message' => 'Installed and activated successfully',
308 );
309 continue;
310 }
311
312 // Download the plugin if the plugin is not installed
313 if (!isset($installedPlugins[$plugin_slug])) {
314 $slug = explode('/', $plugin_slug)[0];
315 $api = plugins_api( 'plugin_information', array( 'slug' => $slug ) );
316
317 if ( is_wp_error( $api ) ) {
318 $results[] = array(
319 'slug' => $plugin_slug,
320 'success' => false,
321 'message' => $api->get_error_message(),
322 );
323 continue;
324 }
325
326 $result = $upgrader->install( $api->download_link );
327 if ( is_wp_error( $result ) ) {
328 $results[] = array(
329 'slug' => $plugin_slug,
330 'success' => false,
331 'message' => $result->get_error_message(),
332 );
333 continue;
334 }
335 }
336
337 // Activating a plugin is a separate capability from installing one, so it is
338 // checked on its own rather than being implied by 'install_plugins' above.
339 if ( ! current_user_can( 'activate_plugins' ) ) {
340 $results[] = array(
341 'slug' => $plugin_slug,
342 'success' => false,
343 'message' => esc_html__( 'You do not have permission to activate plugins on this site.', 'ultimate-post-kit' ),
344 );
345 continue;
346 }
347
348 // active the plugin
349 if ( is_plugin_inactive( $plugin_slug ) ) {
350 $activation_result = activate_plugin( $plugin_slug );
351 if ( is_wp_error( $activation_result ) ) {
352 $results[] = array(
353 'slug' => $plugin_slug,
354 'success' => false,
355 'message' => $activation_result->get_error_message(),
356 );
357 continue;
358 }
359
360 $results[] = array(
361 'slug' => $plugin_slug,
362 'success' => true,
363 'message' => 'Installed and activated successfully',
364 );
365 }
366 }
367
368 ob_clean();
369 wp_send_json_success( array( 'results' => $results ) );
370 wp_die();
371 }
372
373 /**
374 * Get the main plugin file path for a given slug.
375 *
376 * @param string $slug Plugin slug.
377 * @return string|false Plugin file path or false if not found.
378 */
379 private function get_plugin_file( $slug ) {
380 $plugins = get_plugins();
381
382 foreach ( $plugins as $file => $plugin ) {
383 if ( strpos( $file, $slug ) !== false ) {
384 return $file;
385 }
386 }
387
388 return false;
389 }
390
391 /**
392 * Activate default widgets in setup wizard
393 */
394 public function activate_default_widgets() {
395
396 // Also reached anonymously via admin-ajax.php, which fires admin_init before
397 // authentication. Enabling widget modules is an administrator action.
398 if ( wp_doing_ajax() || ! current_user_can( 'manage_options' ) ) {
399 return;
400 }
401
402 // List of widgets to activate by default
403 $default_active_widgets = array(
404 'alex-grid',
405 'alice-grid',
406 'alter-carousel',
407 'banner',
408 'buzz-list',
409 'carbon-slider',
410 'featured-list',
411 'news-ticker',
412 'pholox-slider',
413 'timeline',
414 'category',
415 'social-count',
416 'tag-cloud'
417 );
418
419 // Get current active modules
420 $active_modules = get_option('ultimate_post_kit_active_modules', array());
421
422 // Make sure $active_modules is an array
423 if (!is_array($active_modules)) {
424 $active_modules = array();
425 }
426
427 // Check if active_modules option exists and is not empty
428 // If it's a new installation or option doesn't exist, we'll set our defaults
429 $modified = false;
430
431 foreach ($default_active_widgets as $widget) {
432 // Only set if not already defined (prevents overriding user settings on existing installations)
433 if (!isset($active_modules[$widget])) {
434 $active_modules[$widget] = 'on';
435 $modified = true;
436 }
437 }
438
439 // Update the option if changes were made
440 if ($modified) {
441 update_option('ultimate_post_kit_active_modules', $active_modules);
442 }
443 }
444 }
445
446 // Initialize the Setup Wizard
447 Setup_Wizard::get_instance();
448
449 use Elementor\TemplateLibrary\Source_Local;
450
451 add_action('wp_ajax_ultimate_post_kit_import_elementor_template', function () {
452 check_ajax_referer( 'ultimate_post_kit_setup_wizard_nonce', 'nonce' );
453
454 if ( ! current_user_can( 'manage_options' ) ) {
455 wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'ultimate-post-kit' ) ) );
456 wp_die();
457 }
458
459 $json_url = isset( $_POST['import_url'] ) ? esc_url_raw( wp_unslash( $_POST['import_url'] ) ) : '';
460
461 $response = wp_safe_remote_get($json_url, array(
462 'timeout' => 60,
463 ));
464
465 if (is_wp_error($response)) {
466 wp_send_json_error(['message' => esc_html__('Failed to fetch template from URL.', 'ultimate-post-kit')]);
467 wp_die();
468 }
469
470 $sourceData = wp_remote_retrieve_body($response);
471 $sourceData2 = json_decode($sourceData, true);
472
473 if (!$sourceData2 || !is_array($sourceData2)) {
474 wp_send_json_error(['message' => esc_html__('Failed to fetch template from URL.', 'ultimate-post-kit')]);
475 wp_die();
476 }
477
478 $temp_file = wp_upload_dir()['path'] . '/elementor_import_' . time() . '.json';
479 file_put_contents($temp_file, $sourceData);
480
481 // Initialize Elementor's Template Importer
482 if (!class_exists('\Elementor\TemplateLibrary\Source_Local')) {
483 wp_delete_file($temp_file);
484 wp_send_json_error(['message' => esc_html__('Elementor is not installed or activated!', 'ultimate-post-kit')]);
485 wp_die();
486 }
487
488 $manager = new Source_Local();
489 $templateData = $manager->import_template('elementor_template', $temp_file);
490 wp_delete_file($temp_file); // Delete temp file after import
491
492 if (is_wp_error($templateData) || !is_array($templateData) || empty($templateData[0]['template_id'])) {
493 wp_send_json_error(['message' => esc_html__('Failed to import template!', 'ultimate-post-kit')]);
494 wp_die();
495 }
496
497 $template_id = $templateData[0]['template_id'];
498 $metaData = get_post_meta($template_id);
499
500 $page_title = isset($_POST['title']) ? sanitize_text_field(wp_unslash($_POST['title'])) : esc_html__("No Title", 'ultimate-post-kit');
501
502 // Validate Elementor Data
503 if (!isset($metaData['_elementor_data'][0])) {
504 wp_send_json_error(['message' => esc_html__('Elementor data not found in template.', 'ultimate-post-kit')]);
505 wp_die();
506 }
507
508 $_elementor_data = wp_slash($metaData['_elementor_data'][0]);
509
510 // Create New Page
511 $new_post_id = wp_insert_post([
512 'post_type' => 'page',
513 'post_status' => empty($page_title) ? 'draft' : 'publish',
514 'post_title' => $page_title,
515 'post_content' => '',
516 ]);
517
518 if (is_wp_error($new_post_id)) {
519 wp_send_json_error(['message' => esc_html__('Failed to create page!', 'ultimate-post-kit')]);
520 wp_die();
521 }
522
523 // Assign Elementor Template Data
524 update_post_meta($new_post_id, '_elementor_data', $_elementor_data);
525
526 // Import Page Settings if available
527 if (isset($metaData['_elementor_page_settings'][0])) {
528 $_elementor_page_settings = is_serialized($metaData['_elementor_page_settings'][0])
529 ? unserialize($metaData['_elementor_page_settings'][0], ['allowed_classes' => false])
530 : $metaData['_elementor_page_settings'][0];
531 update_post_meta($new_post_id, '_elementor_page_settings', $_elementor_page_settings);
532 }
533
534 update_post_meta($new_post_id, '_elementor_template_type', $sourceData2['type'] ?? '');
535 update_post_meta($new_post_id, '_elementor_edit_mode', 'builder');
536 // update_post_meta($new_post_id, '_wp_page_template', !empty($pageTemplate) ? $pageTemplate : 'elementor_header_footer');
537
538 wp_send_json_success([
539 'message' => esc_html__('The template was imported successfully.', 'ultimate-post-kit'),
540 'ids' => $new_post_id,
541 'edit_link' => admin_url('post.php?post=' . $new_post_id . '&action=elementor'),
542 ]);
543 }
544 );
545
546
547 add_action('wp_ajax_ultimate_post_kit_import_elementor_bundle_template', function () {
548 check_ajax_referer('ultimate_post_kit_setup_wizard_nonce', 'nonce');
549
550 if ( ! current_user_can( 'manage_options' ) ) {
551 wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'ultimate-post-kit' ) ) );
552 wp_die();
553 }
554
555 $file_url = isset($_POST['import_url']) ? esc_url_raw(wp_unslash($_POST['import_url'])) : '';
556
557 if (!filter_var($file_url, FILTER_VALIDATE_URL) || 0 !== strpos($file_url, 'http')) {
558 wp_send_json_error(['message' => esc_html__('Invalid import URL', 'ultimate-post-kit')]);
559 }
560
561 $remote_zip_request = wp_safe_remote_get($file_url, array(
562 'timeout' => 60,
563 ));
564
565 if (is_wp_error($remote_zip_request)) {
566 wp_send_json_error(['message' => esc_html__('Failed to fetch template from URL.', 'ultimate-post-kit')]);
567 }
568
569
570 if (200 !== $remote_zip_request['response']['code']) {
571 wp_send_json_error(['message' => esc_html__('Failed to fetch template from URL.', 'ultimate-post-kit')]);
572 }
573
574 $kit_zip_path = Plugin::$instance->uploads_manager->create_temp_file($remote_zip_request['body'], 'kit.zip');
575
576 $app = Plugin::$instance->app;
577 if (!$app) {
578 wp_send_json_error(['message' => esc_html__('Elementor app not available', 'ultimate-post-kit')]);
579 }
580
581 $import_export_module = $app->get_component('import-export');
582
583 try {
584 $result = $import_export_module->upload_kit($kit_zip_path, 'local');
585 $manifest = $result['manifest'] ?? [];
586 $plugins = $manifest['plugins'];
587
588 $missingPlugins = [];
589 foreach ($plugins as $plugin) {
590 $pluginSlug = $plugin['plugin'].".php";
591 if (is_plugin_inactive($pluginSlug)) {
592 $missingPlugins[] = $plugin;
593 }
594 }
595
596 if (count($missingPlugins)) {
597 wp_send_json_error([
598 'plugins' => $missingPlugins,
599 'message' => esc_html__('Missing plugins', 'ultimate-post-kit'),
600 ]);
601 }
602
603 $tmp_folder_id = $result['session'];
604 $includes = [];
605 $selectedCustomPostTypes = [];
606
607 if (isset($manifest['templates'])) {
608 $includes[] = 'templates';
609 }
610
611 if (isset($manifest['content'])) {
612 $includes[] = 'content';
613 }
614
615 if (isset($manifest['site-settings'])) {
616 $includes[] = 'settings';
617 }
618
619 if (isset($manifest['custom-post-type-title'])) {
620 $selectedCustomPostTypes = array_keys($manifest['custom-post-type-title']);
621 }
622
623 $settings = [
624 'id' => '',
625 'session' => $tmp_folder_id,
626 'include' => $includes,
627 'overrideConditions' => [],
628 'selectedCustomPostTypes' => $selectedCustomPostTypes,
629 ];
630
631 $import = $import_export_module->import_kit($tmp_folder_id, $settings, true);
632
633 // Deliberately NOT calling
634 // Plugin::$instance->uploads_manager->enable_unfiltered_files_upload() here.
635 // That permanently sets Elementor's `elementor_unfiltered_files_upload` option,
636 // which Elementor itself surfaces behind an explicit security warning and an
637 // opt-in confirmation. Importing a template must not silently relax another
638 // plugin's upload filtering for the whole site.
639
640 wp_send_json_success($import);
641 } catch (\Throwable $e) {
642 wp_send_json_error(['message' => esc_html__('Import failed: ', 'ultimate-post-kit') . esc_html($e->getMessage())]);
643 }
644 });
645
646 add_action('wp_ajax_ultimate_post_kit_import_elementor_bundle_runner_template', function () {
647 check_ajax_referer('ultimate_post_kit_setup_wizard_nonce', 'nonce');
648
649 if ( ! current_user_can( 'manage_options' ) ) {
650 wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'ultimate-post-kit' ) ) );
651 wp_die();
652 }
653
654 $runner = isset($_POST['runner']) ? sanitize_text_field(wp_unslash($_POST['runner'])) : '';
655 $sessionId = isset($_POST['sessionId']) ? sanitize_text_field(wp_unslash($_POST['sessionId'])) : '';
656
657 if (!$runner || !$sessionId) {
658 wp_send_json_error(['message' => esc_html__('Required Param Is Missing.', 'ultimate-post-kit')]);
659 }
660
661 $app = Plugin::$instance->app;
662 if (!$app) {
663 wp_send_json_error(['message' => esc_html__('Elementor app not available.', 'ultimate-post-kit')]);
664 }
665
666 try {
667 // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged, WordPress.PHP.IniSet.max_execution_time_Disallowed -- raise the limit only for this admin-triggered template import, which can exceed the default.
668 @ini_set('max_execution_time', 60 * 5);
669
670 $import_export_module = $app->get_component('import-export');
671 $import = $import_export_module->import_kit_by_runner($sessionId, $runner);
672
673 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- hooking into Elementor's own action, not a plugin-defined hook.
674 do_action('elementor/import-export/import-kit/runner/after-run', $import);
675 wp_send_json_success($import);
676 } catch (\Throwable $throwable) {
677 wp_send_json_error(['message' => $throwable->getMessage()]);
678 }
679 });
680