PluginProbe
WDesignKit – AI Templates, Widget Builder & MCP Workflow / 2.6.2
WDesignKit – AI Templates, Widget Builder & MCP Workflow v2.6.2
2.6.6 2.6.5 2.6.4 2.6.3 2.6.2 2.6.1 2.6.0 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5.0 2.4.0 2.3.3 2.3.2 2.3.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 All 128 releases
wdesignkit / includes / admin / class-api.php

class-api.php in WDesignKit – AI Templates, Widget Builder & MCP Workflow 2.6.2, at includes/admin/class-api.php

5,894 lines 184.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The file that defines the core plugin class
4 *
5 * @link https://posimyth.com/
6 * @since 1.0.0
7 *
8 * @package Wdesignkit
9 * @subpackage Wdesignkit/includes
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 use wdkit\Wdkit_Wdesignkit;
17 use wdkit\WdKit_enqueue\Wdkit_Enqueue;
18 use wdkit\wdkit_datahooks\Wdkit_Data_Hooks;
19
20 if ( ! class_exists( 'Wdkit_Api_Call' ) ) {
21
22 /**
23 * Main classs call for all api
24 *
25 * @link https://posimyth.com/
26 * @since 1.0.0
27 */
28 class Wdkit_Api_Call {
29
30 /**
31 * Member Variable
32 *
33 * @var instance
34 */
35 private static $instance;
36
37 /**
38 * Member Variable
39 *
40 * @var staring widgets_with_post_category
41 */
42 public $widgets_with_post_category = array(
43 'post_category', 'include_products',
44 );
45
46 /**
47 * Member Variable
48 *
49 * @var staring $wdkit_api
50 */
51 public $wdkit_api = WDKIT_SERVER_API_URL . 'api/wp/';
52
53 /**
54 * Member Variable
55 *
56 * @var staring $wdkit_api_v2
57 */
58 public $wdkit_api_v2 = WDKIT_SERVER_API_URL . 'api/v2/wp/';
59
60 /**
61 * Member Variable
62 *
63 * @var staring $widget_folder_u_r_l
64 */
65 public $widget_folder_u_r_l = '';
66
67 /**
68 * Member Variable
69 *
70 * @var staring $e_msg_login
71 */
72 public $e_msg_login = 'Login Error: Check your details and try again.';
73
74 /**
75 * Member Variable
76 *
77 * @var staring $e_desc_login
78 */
79 public $e_desc_login = 'Invalid Login Details';
80
81 /**
82 * Member Variable
83 *
84 * @var staring wdkit_onbording_api
85 */
86 public $wdkit_onbording_api = 'https://api.posimyth.com/wp-json/wdkit/v2/wdkit_store_user_data';
87
88 /**
89 * Member Variable
90 *
91 * @var staring wdkit_onbording_end
92 */
93 public $wdkit_onbording_end = 'wkit_onbording_end';
94
95 /**
96 * Initiator
97 */
98 public static function get_instance() {
99 if ( ! isset( self::$instance ) ) {
100 self::$instance = new self();
101 }
102
103 return self::$instance;
104 }
105
106 /**
107 * Define the core functionality of the plugin.
108 */
109 public function __construct() {
110 add_action( 'wp_ajax_get_wdesignkit', array( $this, 'wdkit_api_call' ) );
111 }
112
113 /**
114 * Error JSON message
115 *
116 * @param array $data give array.
117 * @param string $status api code number.
118 *
119 * @since 1.0.0
120 * */
121 public function wdkit_error_msg( $data = null, $status = null ) {
122 wp_send_json_error( $data );
123 wp_die();
124 }
125
126 /**
127 * Success JSON message
128 *
129 * @param array $data give array.
130 * @param string $status api code number.
131 *
132 * @since 1.0.0
133 * */
134 public function wdkit_success_msg( $data = null, $status = null ) {
135 wp_send_json_success( $data, $status );
136 wp_die();
137 }
138
139
140 /**
141 * Memory headroom left for image work, in bytes. 0 means unlimited.
142 */
143 private static function wdkit_available_image_memory() {
144 $limit = wp_convert_hr_to_bytes( ini_get( 'memory_limit' ) );
145
146 if ( $limit <= 0 ) {
147 return 0;
148 }
149
150 return max( 0, $limit - memory_get_usage( true ) );
151 }
152
153 /**
154 * Stop WordPress decoding images that cannot fit in the memory available.
155 *
156 * Both filters are consulted by wp_create_image_subsizes() *before* it loads an image
157 * editor, so refusing here means the oversized image is never decoded:
158 *
159 * big_image_size_threshold -> falsy skips the "-scaled" copy (needs a full decode)
160 * intermediate_image_sizes_advanced -> empty makes _wp_make_subsizes() return early,
161 * ahead of its wp_get_image_editor() call
162 *
163 * The original file is still attached and usable; only the derived sizes are skipped.
164 * That trades ideal thumbnails for an import that completes, instead of a fatal that
165 * takes the whole page down and repeats on every retry.
166 *
167 * @since 2.6.2
168 */
169 private static function wdkit_guard_oversized_images() {
170 static $registered = false;
171
172 // Registering twice would stack duplicate closures on both filters.
173 if ( $registered ) {
174 return;
175 }
176
177 $registered = true;
178
179 if ( ! class_exists( 'Wdkit_Image_Guard' ) ) {
180 require_once WDKIT_INCLUDES . 'admin/class-wdkit-image-guard.php';
181 }
182
183 add_filter(
184 'big_image_size_threshold',
185 function ( $threshold, $imagesize = array(), $file = '', $attachment_id = 0 ) {
186 if ( ! empty( $imagesize[0] ) && ! empty( $imagesize[1] )
187 && ! Wdkit_Image_Guard::decode_fits( $imagesize[0], $imagesize[1], self::wdkit_available_image_memory() )
188 ) {
189 return false;
190 }
191
192 return $threshold;
193 },
194 99,
195 4
196 );
197
198 add_filter(
199 'intermediate_image_sizes_advanced',
200 function ( $sizes, $image_meta = array(), $attachment_id = 0 ) {
201 if ( ! empty( $image_meta['width'] ) && ! empty( $image_meta['height'] )
202 && ! Wdkit_Image_Guard::decode_fits( $image_meta['width'], $image_meta['height'], self::wdkit_available_image_memory() )
203 ) {
204 return array();
205 }
206
207 return $sizes;
208 },
209 99,
210 3
211 );
212 }
213
214 /**
215 * Get Wdkit Api Call Ajax.
216 */
217 public function wdkit_api_call() {
218
219 check_ajax_referer( 'wdkit_nonce', 'kit_nonce' );
220
221 if ( ! is_user_logged_in() || ! current_user_can( 'manage_options' ) ) {
222 wp_send_json_error( array( 'content' => __( 'Insufficient permissions.', 'wdesignkit' ) ) );
223 }
224
225 $type = isset( $_POST['type'] ) ? strtolower( sanitize_text_field( wp_unslash( $_POST['type'] ) ) ) : false;
226 if ( ! $type ) {
227 $this->wdkit_error_msg( __( 'Something went wrong.', 'wdesignkit' ) );
228 }
229
230 switch ( $type ) {
231 case 'onboarding_handler':
232 $data = $this->wdkit_onboarding_handler();
233 break;
234 case 'wkit_login':
235 $data = apply_filters( 'wp_wdkit_login_ajax', 'wkit_login' );
236 break;
237 case 'api_login':
238 $data = apply_filters( 'wp_wdkit_login_ajax', 'api_login' );
239 break;
240 case 'social_login':
241 $data = apply_filters( 'wp_wdkit_login_ajax', 'social_login' );
242 break;
243 case 'forgot_password':
244 $data = apply_filters( 'wp_wdkit_login_ajax', 'forgot_password' );
245 break;
246 case 'wdkit_user_signup':
247 $data = apply_filters( 'wp_wdkit_login_ajax', 'wdkit_user_signup' );
248 break;
249 case 'wkit_meta_data':
250 $data = $this->wdkit_meta_data();
251 break;
252 case 'get_user_info':
253 $data = $this->wdkit_get_user_info();
254 break;
255 case 'browse_page':
256 $data = $this->wdkit_browse_page();
257 break;
258 case 'kit_template':
259 $data = $this->wdkit_template();
260 break;
261 case 'wkit_preset_template':
262 $data = apply_filters( 'wp_wdkit_preset_ajax', 'wdkit_preset_template' );
263 break;
264 case 'wdkit_preset_dwnld_template':
265 $data = apply_filters( 'wp_wdkit_preset_ajax', 'wdkit_preset_dwnld_template' );
266 break;
267 case 'template_remove':
268 $data = $this->wdkit_template_remove();
269 break;
270 case 'save_template':
271 $data = $this->wdkit_put_save_template();
272 break;
273 case 'update_save_temp_image':
274 $data = $this->wdkit_update_save_temp_image();
275 break;
276 case 'save_wp_images':
277 $data = $this->wdkit_save_wp_images();
278 break;
279 case 'get_global_val':
280 $data = $this->wdkit_get_global_val();
281 break;
282 case 'update_global_val':
283 $data = $this->wdkit_update_global_val();
284 break;
285 case 'wdkit_get_site_setting':
286 $data = $this->wdkit_get_site_setting();
287 break;
288 case 'wdkit_update_site_setting':
289 $data = $this->wdkit_update_site_setting();
290 break;
291 case 'update_preset_setting':
292 $data = $this->wdkit_update_preset();
293 break;
294 case 'find_template':
295 $data = $this->wdkit_find_existing_template();
296 break;
297 case 'update_template':
298 $data = $this->wdkit_update_template();
299 break;
300 case 'manage_favorite':
301 $data = $this->wdkit_manage_favorite();
302 break;
303 case 'check_plugins_depends':
304 $data = $this->wdkit_check_plugins_depends();
305 break;
306 case 'install_plugins_depends':
307 $data = $this->wdkit_install_plugins_depends();
308 break;
309 case 'generate_site_logo':
310 $data = $this->wkit_generate_site_logo();
311 break;
312 case 'generate_ai_content':
313 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'generate_ai_content' );
314 break;
315 case 'generate_ai_content_batch':
316 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'generate_ai_content_batch' );
317 break;
318 case 'reset_site':
319 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'reset_site' );
320 break;
321 case 'wdkit_nxt_thembuilder_reset':
322 $data = $this->wdkit_nxt_thembuilder_reset();
323 break;
324 case 'wdkit_check_user_credit':
325 $data = $this->wdkit_check_user_credit();
326 break;
327 case 'wdkit_remove_header_footer':
328 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'wdkit_remove_header_footer' );
329 break;
330 case 'check_post_count':
331 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'check_post_count' );
332 break;
333 case 'wkit_check_product_count':
334 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'wkit_check_product_count' );
335 break;
336 case 'select_team_img':
337 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'select_team_img' );
338 break;
339 case 'wkit_ai_desc_keyword':
340 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'wkit_ai_desc_keyword' );
341 break;
342 case 'wkit_ai_credit_update':
343 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'wkit_ai_credit_update' );
344 break;
345 case 'wkit_generate_post_data':
346 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'wkit_generate_post_data' );
347 break;
348 case 'wkit_generate_product_data':
349 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'wkit_generate_product_data' );
350 break;
351 case 'wkit_cteate_product':
352 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'wkit_cteate_product' );
353 break;
354 case 'wkit_remove_dummy_post':
355 $data = apply_filters( 'wp_wdkit_import_temp_ajax', 'wkit_remove_dummy_post' );
356 break;
357 case 'update_latest_plugin':
358 $data = $this->wdkit_update_latest_plugin();
359 break;
360 case 'activate_container':
361 $data = $this->wdkit_activate_container();
362 break;
363 case 'import_taxonomy':
364 $data = $this->wdkit_import_taxonomy();
365 break;
366 case 'import_template':
367 $data = $this->wdkit_import_template();
368 break;
369 case 'import_multi_template':
370 $data = $this->wdkit_import_multi_template();
371 break;
372 case 'import_page_section':
373 $data = $this->import_page_section_content();
374 break;
375 case 'wkit_update_elementor_template':
376 $data = $this->wkit_update_elementor_template();
377 break;
378 case 'wdkit_update_page_content':
379 $data = $this->wdkit_update_page_content();
380 break;
381 case 'update_plugin_setting':
382 $data = $this->update_plugin_setting();
383 break;
384 case 'update_theme_setting':
385 $data = $this->update_theme_setting();
386 break;
387 case 'update_site_setting':
388 $data = $this->update_site_setting();
389 break;
390 case 'import_kit_template':
391 $data = $this->wdkit_import_kit_template();
392 break;
393 case 'enable_template_widgets':
394 $data = $this->wdkit_enable_template_widgets();
395 break;
396 case 'scan_nexter_widgets':
397 if ( ! empty( $_POST['blockNames'] ) && has_filter( 'nexter_block_list_merge' ) ) {
398
399 $posted_blocks = json_decode( stripslashes( $_POST['blockNames'] ), true );
400
401 if ( is_array( $posted_blocks ) ) {
402 $blockList = array_map( 'sanitize_text_field', $posted_blocks );
403
404 // �
405 filter call करो
406 $result = apply_filters( 'nexter_block_list_merge', $blockList );
407
408 wp_send_json( $result );
409 wp_die();
410 }
411 }
412
413 wp_send_json(
414 array(
415 'success' => false,
416 'message' => __( 'No block names received or filter not found.', 'wdesignkit' ),
417 'description' => 'Ensure blockNames are posted and the filter is attached.',
418 )
419 );
420 wp_die();
421 $data = '';
422 break;
423 case 'shared_with_me':
424 $data = $this->wdkit_shared_with_me();
425 break;
426 case 'manage_workspace':
427 $data = $this->wdkit_manage_workspace();
428 break;
429 case 'widget_browse_page':
430 $data = apply_filters( 'wp_wdkit_widget_ajax', 'widget_browse_page' );
431 break;
432 case 'wkit_create_widget':
433 $data = apply_filters( 'wp_wdkit_widget_ajax', 'wkit_create_widget' );
434 break;
435 case 'wkit_import_widget':
436 $data = apply_filters( 'wp_wdkit_widget_ajax', 'wkit_import_widget' );
437 break;
438 case 'wkit_export_widget':
439 $data = apply_filters( 'wp_wdkit_widget_ajax', 'wkit_export_widget' );
440 break;
441 case 'wkit_delete_widget':
442 $data = apply_filters( 'wp_wdkit_widget_ajax', 'wkit_delete_widget' );
443 break;
444 case 'wkit_widget_preview':
445 $data = apply_filters( 'wp_wdkit_widget_ajax', 'wkit_widget_preview' );
446 break;
447 case 'wkit_check_widget_versions':
448 $data = apply_filters( 'wp_wdkit_widget_ajax', 'wkit_check_widget_versions' );
449 break;
450 case 'wkit_plugin_download_get':
451 $data = apply_filters( 'wp_wdkit_widget_ajax', 'wkit_plugin_download_get' );
452 break;
453 case 'wkit_manage_widget_workspace':
454 $data = $this->wdkit_manage_widget_workspace();
455 break;
456 case 'wkit_activate_key':
457 $data = $this->wdkit_activate_key();
458 break;
459 case 'wkit_manage_widget_category':
460 $data = $this->wdkit_manage_widget_category();
461 break;
462 case 'wkit_widget_json':
463 $data = $this->wkit_widget_json();
464 break;
465 case 'wkit_download_widget':
466 $data = $this->wdkit_download_widget();
467 break;
468 case 'wkit_public_download_widget':
469 $data = apply_filters( 'wp_wdkit_widget_ajax', 'wkit_public_download_widget' );
470 break;
471 case 'wkit_add_widget':
472 $data = $this->wdkit_add_widget();
473 break;
474 case 'wkit_favourite_widget':
475 $data = $this->wdkit_favourite_widget();
476 break;
477 case 'wkit_setting_panel':
478 $data = $this->wdkit_setting_panel();
479 break;
480 case 'media_import':
481 $data = $this->wdkit_media_import();
482 break;
483 case 'active_licence':
484 $data = $this->wdkit_activate_licence();
485 break;
486 case 'delete_licence':
487 $data = $this->wdkit_delete_licence_key();
488 break;
489 case 'sync_licence':
490 $data = $this->wdkit_sync_licence_key();
491 break;
492 case 'get_wkit_version':
493 $data = $this->wdkit_prev_version();
494 break;
495 case 'rollback_wdkit':
496 $data = $this->wdkit_rollback_check();
497 break;
498 case 'wkit_logout':
499 $data = $this->wdkit_logout();
500 break;
501 case 'wkit_white_label':
502 $this->wkit_white_label();
503 break;
504 case 'wkit_reset_wl':
505 $data = $this->wkit_reset_wl();
506 break;
507 case 'wdkit_dark_mode':
508 $data = $this->wdkit_dark_mode();
509 break;
510 case 'wdkit_get_workspace_data':
511 $data = $this->wdkit_get_workspace_data();
512 break;
513 default:
514 $this->wdkit_error_msg( __( 'Unknown request type.', 'wdesignkit' ) );
515 return;
516 }
517
518 $this->wdkit_success_msg( $data );
519 // wp_die();
520 }
521
522 /**
523 *
524 * This Function is used for API call
525 *
526 * @since 1.0.0
527 *
528 * @param array $data give array.
529 * @param array $name store data.
530 * @param int $timeout optional HTTP timeout in seconds. Default 100.
531 */
532 protected function wkit_api_call( $data, $name, $timeout = 100 ) {
533 $u_r_l = $this->wdkit_api;
534
535 if ( empty( $u_r_l ) ) {
536 return array(
537 'massage' => esc_html__( 'API Not Found', 'wdesignkit' ),
538 'success' => false,
539 );
540 }
541
542 $args = array(
543 'method' => 'POST',
544 'body' => $data,
545 'timeout' => $timeout,
546 );
547 $response = wp_remote_post( $u_r_l . $name, $args );
548
549 if ( is_wp_error( $response ) ) {
550 $error_message = $response->get_error_message();
551
552 /* Translators: %s is a placeholder for the error message */
553 $error_message = sprintf( esc_html__( 'API request error: %s', 'wdesignkit' ), esc_html( $error_message ) );
554
555 return array(
556 'massage' => $error_message,
557 'success' => false,
558 );
559 }
560
561 $status_code = wp_remote_retrieve_response_code( $response );
562 if ( 200 === $status_code ) {
563
564 return array(
565 'data' => json_decode( wp_remote_retrieve_body( $response ) ),
566 'massage' => esc_html__( 'Success', 'wdesignkit' ),
567 'status' => $status_code,
568 'success' => true,
569 );
570 }
571
572 $error_message = sprintf( 'Server error: %d', esc_html( $status_code ) );
573
574 if ( isset( $error_data->message ) ) {
575 $error_message .= ' (' . $error_data->message . ')';
576 }
577
578 return array(
579 'massage' => $error_message,
580 'status' => $status_code,
581 'success' => false,
582 );
583 }
584
585 /**
586 *
587 * It is Use for handle onboarding data.
588 *
589 * @since 1.0.9
590 */
591 public function wdkit_onboarding_handler() {
592 $page_template = isset( $_POST['page_template'] ) ? json_decode( wp_unslash( $_POST['page_template'] ), true ) : '';
593 $page_builder = isset( $_POST['page_builder'] ) ? json_decode( wp_unslash( $_POST['page_builder'] ), true ) : '';
594
595 $elementor_plugin = isset( $_POST['elementor_plugin'] ) ? (int) sanitize_text_field( wp_unslash( $_POST['elementor_plugin'] ) ) : 0;
596 $tpag_plugin = isset( $_POST['tpag_plugin'] ) ? (int) sanitize_text_field( wp_unslash( $_POST['tpag_plugin'] ) ) : 0;
597 $bricks_theme = isset( $_POST['bricks_theme'] ) ? (int) sanitize_text_field( wp_unslash( $_POST['bricks_theme'] ) ) : 0;
598 $site_info = isset( $_POST['info'] ) ? sanitize_text_field( wp_unslash( $_POST['info'] ) ) : false;
599
600 $server_software = ! empty( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : '';
601
602 $web_server = $server_software;
603 $memory_limit = ini_get( 'memory_limit' );
604 $max_execution_time = ini_get( 'max_execution_time' );
605 $php_version = phpversion();
606 $wp_version = get_bloginfo( 'version' );
607 $email = get_option( 'admin_email' );
608 $siteurl = get_option( 'siteurl' );
609 $language = get_bloginfo( 'language' );
610
611 // Active Plugin Name.
612 $act_plugin = array();
613 $actplu = get_option( 'active_plugins' );
614 if ( ! function_exists( 'get_plugins' ) ) {
615 require_once ABSPATH . 'wp-admin/includes/plugin.php';
616 }
617
618 $plugins = get_plugins();
619 foreach ( $actplu as $p ) {
620 if ( isset( $plugins[ $p ] ) ) {
621 $act_plugin[] = $plugins[ $p ]['Name'];
622 }
623 }
624
625 $plugin = wp_json_encode( $act_plugin );
626
627 $theme = '';
628 $acthemeobj = wp_get_theme();
629 if ( $acthemeobj->get( 'Name' ) !== null && ! empty( $acthemeobj->get( 'Name' ) ) ) {
630 $theme = $acthemeobj->get( 'Name' );
631 }
632
633 $basic_requirements = array(
634 'elementor_install' => $elementor_plugin,
635 'tpag_install' => $tpag_plugin,
636 'bricks_install' => $bricks_theme,
637 );
638
639 if ( ! empty( $site_info ) ) {
640 $final = array(
641 'web_server' => $web_server,
642 'memory_limit' => $memory_limit,
643 'max_execution_time' => $max_execution_time,
644 'php_version' => $php_version,
645 'wp_version' => $wp_version,
646 'email' => $email,
647 'site_url' => $siteurl,
648 'site_language' => $language,
649 'theme' => $theme,
650 'plugins' => $act_plugin,
651 'basic_requirements' => $basic_requirements,
652 'page_template' => $page_template,
653 'page_builder' => $page_builder,
654 );
655 } else {
656 $final = array();
657 }
658
659 $response = wp_remote_post(
660 $this->wdkit_onbording_api,
661 array(
662 'method' => 'POST',
663 'body' => wp_json_encode( $final ),
664 )
665 );
666
667 $existing_value = get_option( $this->wdkit_onbording_end );
668 if ( false === $existing_value ) {
669 add_option( $this->wdkit_onbording_end, true );
670 }
671
672 if ( is_wp_error( $response ) ) {
673 $result = array(
674 'success' => false,
675 'messages' => 'Oops',
676 'description' => 'Description',
677 );
678
679 wp_send_json( $result );
680 } else {
681 $status_one = wp_remote_retrieve_response_code( $response );
682
683 if ( 200 === $status_one ) {
684 $get_data_one = wp_remote_retrieve_body( $response );
685
686 $get_res = json_decode( json_decode( $get_data_one, true ), true );
687
688 $result = array(
689 'success' => ! empty( $get_res['success'] ) ? $get_res['success'] : false,
690 'messages' => ! empty( $get_res['messages'] ) ? $get_res['messages'] : 'success',
691 'description' => ! empty( $get_res['description'] ) ? $get_res['description'] : 'Description',
692 );
693
694 wp_send_json( $result );
695 } else {
696
697 $result = array(
698 'success' => false,
699 'messages' => 'Oops',
700 'description' => 'description',
701 );
702
703 wp_send_json( $result );
704 }
705 }
706
707 wp_die();
708 }
709
710 /**
711 *
712 * It is Use for get meta data for non login user
713 *
714 * @since 1.0.0
715 */
716 protected function wdkit_meta_data() {
717 $type = isset( $_POST['meta_type'] ) ? sanitize_text_field( wp_unslash( $_POST['meta_type'] ) ) : '';
718 $data = array( 'type' => $type );
719
720 $response = $this->wkit_api_call( $data, 'meta' );
721 $success = ! empty( $response['success'] ) ? $response['success'] : false;
722 $status = ! empty( $response['status'] ) ? (int) $response['status'] : 400;
723
724 if ( empty( $success ) ) {
725 $result = array(
726 'plugin' => array(),
727 'builder' => array(),
728 'category' => array(),
729 'widgetscategory' => array(),
730 'tags' => array(),
731 'widgetbuilder' => array(),
732
733 'message' => esc_html__( 'Server Error', 'wdesignkit' ),
734 'description' => esc_html__( 'Server Error, Data Not Found', 'wdesignkit' ),
735 'success' => false,
736 );
737
738 wp_send_json( $result );
739 wp_die();
740 }
741
742 $get_data_one = ! empty( $response['data'] ) ? $response['data'] : array();
743 $statuscode = array( 'HTTP_CODE' => $status );
744
745 $final = json_decode( wp_json_encode( $get_data_one ), true );
746
747 $final['Setting'] = self::wkit_get_settings_panel();
748 $final['widget_list'] = $this->wkit_manage_widget_sequence( array() );
749
750 $final = array(
751 'data' => $final,
752 );
753
754 wp_send_json( $final );
755 wp_die();
756 }
757
758 /**
759 *
760 * It is Use for get activate license key data from tpae and nexter blocks.
761 *
762 * @since 1.1.6
763 */
764 protected function wkit_manage_license_data() {
765 $manage_licence = array();
766 $theplus_active_check = is_plugin_active( 'the-plus-addons-for-elementor-page-builder/theplus_elementor_addon.php' );
767 $nexter_active_check = is_plugin_active( 'the-plus-addons-for-block-editor/the-plus-addons-for-block-editor.php' );
768
769 $theplus_licence = get_option( 'tpaep_licence_data', array() );
770
771 // Also require the TPAE Pro plugin to be active (Pro defines THEPLUS_VERSION;
772 // the free plugin defines L_THEPLUS_VERSION). This hides the "found active
773 // key" notice when the Pro plugin is removed even though its licence option
774 // still lingers in the database.
775 if ( ! empty( $theplus_active_check ) && defined( 'THEPLUS_VERSION' ) && ! empty( $theplus_licence ) ) {
776 $manage_licence['tpae'] = $theplus_licence;
777 }
778
779 $nexter_licence = get_option( 'tpgb_activate', array() );
780
781 // Also require the Nexter Blocks Pro plugin to be active (Pro defines
782 // TPGBP_VERSION; the free plugin defines TPGB_VERSION), so the notice hides
783 // when the Pro plugin is removed but its licence option persists.
784 if ( ! empty( $nexter_active_check ) && defined( 'TPGBP_VERSION' ) && ! empty( $nexter_licence ) && ! empty( $nexter_licence['tpgb_activate_key'] ) ) {
785 $tpgb_license_status = get_option( 'tpgbp_license_status', array() );
786 $tpgb_license_status['license_key'] = $nexter_licence['tpgb_activate_key'];
787 $manage_licence['tpag'] = $tpgb_license_status;
788 }
789
790 return $manage_licence;
791 }
792
793 /**
794 *
795 * It is Use for get all info of user.
796 *
797 * @since 1.0.0
798 */
799 protected function wdkit_get_user_info() {
800 $token = isset( $_POST['token'] ) ? wp_unslash( $_POST['token'] ) : false;
801 $email = isset( $_POST['email'] ) ? strtolower( sanitize_email( wp_unslash( $_POST['email'] ) ) ) : false;
802 $builder = isset( $_POST['builder'] ) ? strtolower( sanitize_text_field( wp_unslash( $_POST['builder'] ) ) ) : '';
803
804 $site_url = isset( $_POST['site_url'] ) ? esc_url_raw( wp_unslash( $_POST['site_url'] ) ) : '';
805
806 $response = array();
807
808 if ( empty( $token ) ) {
809 $response = array(
810 'success' => false,
811 'message' => $this->e_msg_login,
812 'description' => $this->e_desc_login,
813 );
814
815 wp_send_json( $response );
816 wp_die();
817 }
818
819 // $token = $this->wdkit_login_user_token( $email );
820 $args = array(
821 'token' => $token,
822 'builder' => $builder,
823 'site_url' => $site_url,
824 );
825
826 $response = WDesignKit_Data_Query::get_data( 'get_user_info', $args );
827
828 if ( is_wp_error( $response ) ) {
829 wp_send_json( array(
830 'success' => false,
831 'message' => $response->get_error_message(),
832 'description' => $response->get_error_message(),
833 ) );
834 wp_die();
835 }
836
837 $status = ( ! empty( $response['status'] ) ) ? sanitize_text_field( $response['status'] ) : 'error';
838 $email = isset( $_POST['email'] ) ? strtolower( sanitize_email( wp_unslash( $_POST['email'] ) ) ) : false;
839
840 /**Condtion user for user logout & expire token*/
841 if ( 'Token is Expired' === $status || 'Authorization Token not found' === $status ) {
842 delete_transient( 'wdkit_auth_' . $email );
843 // Clear stored license data when token expires so banner shows again
844 delete_option( 'wdkit_licence_data' );
845 }
846
847 if ( empty( $response ) ) {
848 $response['login_reset'] = 'yes';
849 }
850
851 // Store WDesignKit license data locally if present in response
852 if ( ! empty( $response['credits']['wdkit_licence'] ) && is_array( $response['credits']['wdkit_licence'] ) ) {
853 $wdkit_licence = $response['credits']['wdkit_licence'];
854 // Handle serialized data
855 if ( is_string( $wdkit_licence ) && is_serialized( $wdkit_licence ) ) {
856 $wdkit_licence = unserialize( $wdkit_licence );
857 }
858 if ( ! empty( $wdkit_licence ) && is_array( $wdkit_licence ) ) {
859 update_option( 'wdkit_licence_data', $wdkit_licence );
860 }
861 }
862
863 $response['Setting'] = $this->wkit_get_settings_panel();
864 $response['widget_list'] = $this->wkit_manage_widget_sequence( $response );
865 $response['manage_licence'] = $this->wkit_manage_license_data();
866
867 $response = array(
868 'data' => $response,
869 'success' => true,
870 );
871
872 wp_send_json( $response );
873 wp_die();
874 }
875
876 /**
877 *
878 * It is Use for get all widgets local and server.
879 *
880 * @since 1.0.19
881 * @param string $response userinfo store.
882 */
883 protected function wkit_manage_widget_sequence( $response = array() ) {
884
885 $credits = ! empty( $response['credits']['widget_limit']['meta_value'] ) ? $response['credits']['widget_limit']['meta_value'] : 10;
886 $server_list = ! empty( $response['widgettemplate'] ) ? $response['widgettemplate'] : array();
887 $db_builder_list = ! empty( $response['widgetbuilder'] ) ? $response['widgetbuilder'] : array();
888
889 $placeholderimg = WDKIT_URL . 'assets/images/placeholder.jpg';
890
891 $local_list = $this->wdkit_get_local_widgets();
892
893 $server_w_unique = array_column( $server_list, 'w_unique' );
894
895 $idx_builder = array();
896 foreach ( $db_builder_list as $index => $value ) {
897 $builder_name = ! empty( $value['builder_slug'] ) ? $value['builder_slug'] : '';
898 $w_id = ! empty( $value['w_id'] ) ? $value['w_id'] : '';
899
900 if ( ! empty( $builder_name ) ) {
901 $idx_builder[ $w_id ] = strtolower( str_replace( ' ', '_', trim( $builder_name ) ) );
902 }
903 }
904
905 foreach ( $server_list as $index => $value ) {
906 $get_id = $server_list[ $index ]['builder'] ? $server_list[ $index ]['builder'] : '';
907
908 $server_list[ $index ]['type'] = 'server';
909 $server_list[ $index ]['builder'] = ! empty( $idx_builder[ $get_id ] ) ? $idx_builder[ $get_id ] : '';
910 }
911
912 $count = 0;
913
914 foreach ( $local_list as $key => $value ) {
915 $widget_id = ! empty( $value['widgetdata']['widget_id'] ) ? $value['widgetdata']['widget_id'] : '';
916 $allow_push = isset( $value['widgetdata']['allow_push'] ) ? $value['widgetdata']['allow_push'] : true;
917
918 if ( in_array( $widget_id, $server_w_unique ) ) {
919
920 $index = array_search( $widget_id, $server_w_unique );
921
922 $server_list[ $index ]['title'] = $local_list[ $key ]['widgetdata']['name'];
923 $server_list[ $index ]['w_version'] = $local_list[ $key ]['widgetdata']['widget_version'];
924 $server_list[ $index ]['allow_push'] = $allow_push;
925 $server_list[ $index ]['builder'] = $local_list[ $key ]['widgetdata']['type'];
926 $server_list[ $index ]['w_unique'] = $local_list[ $key ]['widgetdata']['widget_id'];
927 $server_list[ $index ]['image'] = ! empty( $local_list[ $key ]['widgetdata']['w_image'] ) ? $local_list[ $key ]['widgetdata']['w_image'] : $placeholderimg;
928
929 $local_list[ $key ] = $server_list[ $index ];
930
931 $local_list[ $key ]['type'] = 'done';
932
933 unset( $server_list[ $index ] );
934 } else {
935 $local_list[ $key ]['widgetdata']['builder'] = $local_list[ $key ]['widgetdata']['type'];
936 $local_list[ $key ]['widgetdata']['w_unique'] = $local_list[ $key ]['widgetdata']['widget_id'];
937 $local_list[ $key ]['widgetdata']['allow_push'] = $allow_push;
938 $local_list[ $key ]['widgetdata']['image'] = ! empty( $local_list[ $key ]['widgetdata']['w_image'] ) ? $local_list[ $key ]['widgetdata']['w_image'] : $placeholderimg;
939 $local_list[ $key ]['widgetdata']['is_activated'] = 'active';
940
941 $local_list[ $key ]['widgetdata']['type'] = 'plugin';
942
943 $local_list[ $key ]['widgetdata']['title'] = $local_list[ $key ]['widgetdata']['name'];
944 unset( $local_list[ $key ]['widgetdata']['name'] );
945 unset( $local_list[ $key ]['widgetdata']['widget_id'] );
946
947 $local_list[ $key ] = $local_list[ $key ]['widgetdata'];
948 }
949 }
950
951 $final = array_merge( $local_list, $server_list );
952
953 $db_widget = array();
954
955 foreach ( $final as $key => $self ) {
956 $is_activated = ! empty( $final[ $key ]['is_activated'] ) ? $final[ $key ]['is_activated'] : 'active';
957
958 if ( 'active' === $is_activated ) {
959 ++$count;
960 }
961
962 if ( ( $count > $credits ) && ( 'unlimited' !== $credits ) ) {
963 $final[ $key ]['is_activated'] = 'deactive';
964 }
965
966 if ( ! empty( $self['is_activated'] ) && 'active' !== $self['is_activated'] ) {
967 $db_widget[] = array(
968 'w_unique' => $self['w_unique'],
969 'builder' => $self['builder'],
970 'title' => $self['title'],
971 'is_activated' => $self['is_activated'],
972 );
973 }
974 }
975
976 $get_db_widget = get_option( 'wkit_deactivate_widgets', array() );
977 if ( empty( $get_db_widget ) ) {
978 add_option( 'wkit_deactivate_widgets', $db_widget, '', 'yes' );
979 } else {
980 update_option( 'wkit_deactivate_widgets', $db_widget );
981 }
982
983 return $final;
984 }
985
986 /**
987 * Browse Page Filter
988 *
989 * @since 1.0.0
990 */
991 protected function wdkit_browse_page() {
992 $args = $this->wdkit_parse_args( $_POST );
993
994 $response = WDesignKit_Data_Query::get_data( 'browse_page', $args );
995
996 if ( is_wp_error( $response ) ) {
997 wp_send_json( array(
998 'success' => false,
999 'message' => $response->get_error_message(),
1000 ) );
1001 wp_die();
1002 }
1003
1004 $manage_licence = array();
1005 $manage_licence['theplus_elementor_addon'] = ! empty( defined( 'THEPLUS_VERSION' ) ) ? true : false;
1006 $manage_licence['tpag'] = ! empty( defined( 'TPGBP_VERSION' ) ) ? true : false;
1007 $manage_licence['elementor-pro'] = ! empty( defined( 'ELEMENTOR_PRO_VERSION' ) ) ? true : false;
1008 $response['manage_licence'] = $manage_licence;
1009
1010 wp_send_json( $response );
1011 wp_die();
1012 }
1013
1014 /**
1015 *
1016 * It is Use for get template from kit.
1017 *
1018 * @since 1.0.0
1019 */
1020 protected function wdkit_template() {
1021 $args = $this->wdkit_parse_args( $_POST );
1022
1023 $response = WDesignKit_Data_Query::get_data( 'kit_template', $args );
1024
1025 wp_send_json( $response );
1026 wp_die();
1027 }
1028
1029 /**
1030 *
1031 * It is Use for remove or delete template.
1032 *
1033 * @since 1.0.0
1034 */
1035 protected function wdkit_template_remove() {
1036 $args = $this->wdkit_parse_args( $_POST );
1037
1038 $user_email = strtolower( sanitize_email( $args['email'] ) );
1039 $response = '';
1040
1041 // Bug D fix: response()->json() is Laravel syntax — causes PHP fatal. Use plain array.
1042 if ( empty( $user_email ) || empty( $args['template_id'] ) ) {
1043 $response = array(
1044 'message' => $this->e_msg_login,
1045 'description' => $this->e_desc_login,
1046 'success' => false,
1047 );
1048
1049 wp_send_json( $response );
1050 wp_die();
1051 }
1052
1053 $args['token'] = $this->wdkit_login_user_token( $user_email );
1054
1055 unset( $user_email );
1056 $response = WDesignKit_Data_Query::get_data( 'template_remove', $args );
1057
1058 wp_send_json( $response );
1059 wp_die();
1060 }
1061
1062 /**
1063 *
1064 * It is Use for save template from page builder.
1065 *
1066 * @since 1.0.0
1067 */
1068 protected function wdkit_put_save_template() {
1069 $email = isset( $_POST['email'] ) ? strtolower( sanitize_email( wp_unslash( $_POST['email'] ) ) ) : false;
1070 $post_id = isset( $_POST['post_id'] ) ? sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) : '';
1071 $builder = isset( $_POST['builder'] ) ? sanitize_text_field( wp_unslash( $_POST['builder'] ) ) : '';
1072
1073 $response = '';
1074
1075 if ( empty( $email ) ) {
1076 $response = array(
1077 'id' => 0,
1078 'editpage' => '',
1079 'message' => $this->e_msg_login,
1080 'description' => $this->e_desc_login,
1081 'success' => false,
1082 );
1083
1084 wp_send_json( $response );
1085 wp_die();
1086 }
1087
1088 $args = $this->wdkit_parse_args( $_POST );
1089 $args['token'] = $this->wdkit_login_user_token( $email );
1090 unset( $args['email'] );
1091
1092 if( 'elementor' === $builder ){
1093 $args['data'] = base64_decode( $args['data'] );
1094 } else if ( 'gutenberg' === $builder ) {
1095 $args['data'] = base64_decode( $args['data'] );
1096 }
1097
1098 global $post;
1099
1100 $custom_fields = array();
1101 if ( ! empty( $post_id ) ) {
1102 $meta_fields = get_post_custom( $post_id );
1103
1104 foreach ( $meta_fields as $key => $value ) {
1105 if ( str_contains( $key, 'nxt-' ) ) {
1106 $custom_fields[ $key ] = $value;
1107 }
1108 }
1109
1110 if ( ! empty( $custom_fields ) ) {
1111 $data = json_decode( $args['data'], true );
1112 $data['custom_meta'] = $custom_fields;
1113 $args['data'] = wp_json_encode( $data );
1114 }
1115 }
1116
1117 $response = WDesignKit_Data_Query::get_data( 'save_template', $args );
1118
1119 wp_send_json( $response );
1120 wp_die();
1121 }
1122
1123 /**
1124 *
1125 * It is Use for update save template image.
1126 *
1127 * @since 2.0.6
1128 */
1129 protected function wdkit_update_save_temp_image() {
1130 $temp_content = isset( $_POST['temp_content'] ) ? esc_url_raw( $_POST['temp_content'] ) : '';
1131 $content_name = isset( $_POST['content_name'] ) ? sanitize_text_field( $_POST['content_name'] ) : '';
1132 $token = isset( $_POST['token'] ) ? sanitize_text_field( $_POST['token'] ) : '';
1133 $user_type = isset( $_POST['user_type'] ) ? sanitize_text_field( $_POST['user_type'] ) : '';
1134 $type = isset( $_POST['content_type'] ) ? sanitize_text_field( $_POST['content_type'] ) : '';
1135 $id = isset( $_POST['id'] ) ? sanitize_text_field( $_POST['id'] ) : '';
1136 if ( empty( $temp_content ) || empty( $user_type ) || empty( $id ) || empty( $token ) ) {
1137 $response = array(
1138 'message' => __( 'Data not found', 'wdesignkit' ),
1139 'description' => __( 'Data not found', 'wdesignkit' ),
1140 'success' => false,
1141 );
1142 } else {
1143 $temp_content = str_replace( '\\', '', $temp_content );
1144 $temp_content = wp_remote_get( $temp_content )['body'];
1145 $temp_content = base64_encode( $temp_content );
1146
1147 $args = array(
1148 'token' => $token,
1149 'template_id' => $id,
1150 'name' => $content_name,
1151 'content' => $temp_content,
1152 'type' => $type,
1153 );
1154
1155 $response = $this->wkit_api_call( $args, 'save_images' );
1156 $success = ! empty( $response['success'] ) ? $response['success'] : false;
1157
1158 if ( $success ) {
1159 $response = array(
1160 'data' => $response['data'],
1161 'success' => true,
1162 );
1163 } else {
1164 $response = array(
1165 'message' => __( 'API Error', 'wdesignkit' ),
1166 'description' => __( 'API Error', 'wdesignkit' ),
1167 'data' => $response['data'],
1168 'success' => false,
1169 );
1170 }
1171 }
1172
1173 wp_send_json( $response );
1174 wp_die();
1175 }
1176
1177 /**
1178 *
1179 * It is Use for save image to WordPress Media Library.
1180 *
1181 * @since 2.3.3
1182 */
1183 protected function wdkit_save_wp_images() {
1184
1185 // media_sideload_image() generates every registered thumbnail size, which decodes
1186 // the full source bitmap. Same guard as the page import.
1187 $this->wdkit_guard_oversized_images();
1188
1189 $image_url = isset( $_POST['image'] ) ? sanitize_text_field( $_POST['image'] ) : '';
1190
1191 if ( empty( $image_url ) ) {
1192 $response = array(
1193 'message' => __( 'No Image Provided', 'wdesignkit' ),
1194 'description' => __( 'No Image URL provided for save.', 'wdesignkit' ),
1195 'success' => false,
1196 );
1197 } else {
1198
1199 $attachment_id = media_sideload_image( $image_url, 0, null, 'id' );
1200
1201 if ( is_wp_error( $attachment_id ) ) {
1202 $response = array(
1203 'message' => __( 'Upload Failed', 'wdesignkit' ),
1204 'description' => $attachment_id->get_error_message(),
1205 'success' => false,
1206 );
1207 } else {
1208 $saved_url = wp_get_attachment_url( $attachment_id );
1209
1210 // Elementor's importer skips an image only when it finds
1211 // _elementor_source_image_hash matching sha1 of the URL it is given. The
1212 // content we hand it now carries this local URL, so stamp the hash of that
1213 // URL too - without it Elementor re-downloads a file already on disk and
1214 // leaves a "-1" duplicate behind for every image on every page that uses it.
1215 if ( $saved_url ) {
1216 update_post_meta( $attachment_id, '_elementor_source_image_hash', sha1( $saved_url ) );
1217
1218 // Same purpose for the block importer, which keys off its own meta.
1219 update_post_meta( $attachment_id, 'tpgb_source_image_key', sha1( $saved_url ) );
1220 }
1221
1222 $response = array(
1223 'message' => __( 'Image Saved', 'wdesignkit' ),
1224 'description' => __( 'Image successfully saved to Media Library.', 'wdesignkit' ),
1225 'success' => true,
1226 'url' => $saved_url,
1227 );
1228 }
1229
1230 }
1231
1232 wp_send_json( $response );
1233 wp_die();
1234 }
1235
1236 /**
1237 *
1238 * Get Elementor Global color and Typography.
1239 *
1240 * @since 1.1.16
1241 */
1242 protected function wdkit_get_global_val() {
1243
1244 $builder = isset( $_POST['builder'] ) ? strtolower( sanitize_text_field( $_POST['builder'] ) ) : '';
1245
1246 if ( 'elementor' === $builder ) {
1247 $kit_id = get_option( 'elementor_active_kit' );
1248 if ( empty( $kit_id ) ) {
1249 $response = array(
1250 'message' => __( 'Elementor kit not found', 'wdesignkit' ),
1251 'description' => __( 'No active Elementor kit found', 'wdesignkit' ),
1252 'success' => false,
1253 );
1254
1255 wp_send_json( $response );
1256 wp_die();
1257 }
1258
1259 $kit_meta = get_post_meta( $kit_id, '_elementor_page_settings', true );
1260 if ( empty( $kit_meta['system_colors'] ) ) {
1261 $static_meta = array(
1262 'system_colors' => array(
1263 0 => array(
1264 '_id' => 'primary',
1265 'title' => 'Primary',
1266 'color' => '#6EC1E4',
1267 ),
1268 1 => array(
1269 '_id' => 'secondary',
1270 'title' => 'Secondary',
1271 'color' => '#54595F',
1272 ),
1273 2 => array(
1274 '_id' => 'text',
1275 'title' => 'Text',
1276 'color' => '#7A7A7A',
1277 ),
1278 3 => array(
1279 '_id' => 'accent',
1280 'title' => 'Accent',
1281 'color' => '#61CE70',
1282 ),
1283 ),
1284 'custom_colors' => array(),
1285 'system_typography' => array(
1286 0 => array(
1287 '_id' => 'primary',
1288 'title' => 'Primary',
1289 'typography_typography' => 'custom',
1290 'typography_font_family' => 'Roboto',
1291 'typography_font_weight' => '600',
1292 ),
1293 1 => array(
1294 '_id' => 'secondary',
1295 'title' => 'Secondary',
1296 'typography_typography' => 'custom',
1297 'typography_font_family' => 'Roboto Slab',
1298 'typography_font_weight' => '400',
1299 ),
1300 2 => array(
1301 '_id' => 'text',
1302 'title' => 'Text',
1303 'typography_typography' => 'custom',
1304 'typography_font_family' => 'Roboto',
1305 'typography_font_weight' => '400',
1306 ),
1307 3 => array(
1308 '_id' => 'accent',
1309 'title' => 'Accent',
1310 'typography_typography' => 'custom',
1311 'typography_font_family' => 'Roboto',
1312 'typography_font_weight' => '500',
1313 ),
1314 ),
1315 'custom_typography' => array(),
1316 'default_generic_fonts' => 'Sans-serif',
1317 'site_name' => ! empty( get_bloginfo( 'name' ) ) ? get_bloginfo( 'name' ) : '',
1318 'page_title_selector' => 'h1.entry-title',
1319 'activeItemIndex' => 1,
1320 'viewport_md' => 768,
1321 'viewport_lg' => 1025,
1322 );
1323
1324 $kit_meta = $static_meta;
1325 update_post_meta( $kit_id, '_elementor_page_settings', $kit_meta );
1326 }
1327
1328 $system_colors = ! empty( $kit_meta['system_colors'] ) ? $kit_meta['system_colors'] : array();
1329 $custom_colors = ! empty( $kit_meta['custom_colors'] ) ? $kit_meta['custom_colors'] : array();
1330 $system_typography = ! empty( $kit_meta['system_typography'] ) ? $kit_meta['system_typography'] : array();
1331 $custom_typography = ! empty( $kit_meta['custom_typography'] ) ? $kit_meta['custom_typography'] : array();
1332
1333 $color_array = array_merge( $system_colors, $custom_colors );
1334 $typo_array = array_merge( $system_typography, $custom_typography );
1335
1336 $global_data = array(
1337 'color' => $color_array,
1338 'typography' => $typo_array,
1339 );
1340
1341 $response = array(
1342 'message' => __( 'Global data Found', 'wdesignkit' ),
1343 'description' => __( 'Global Color and Typography found', 'wdesignkit' ),
1344 'data' => $global_data,
1345 'success' => true,
1346 );
1347
1348 } elseif ( 'gutenberg' === $builder ) {
1349
1350 $plus_settings = get_option( 'tpgb_global_options', false );
1351 $plus_settings = ! empty( $plus_settings ) ? json_decode( $plus_settings, true ) : json_decode( '[]' );
1352
1353 if ( empty( $plus_settings ) ) {
1354
1355 $static_meta = array(
1356 'active' => 'preset1',
1357 'darkMode' => 'none',
1358 'presets' => array(
1359 'preset1' => array(
1360 'name' => 'Preset 1',
1361 'key' => 'preset1',
1362 'colors' => array(
1363 array(
1364 'label' => 'Primary',
1365 'value' => '#8072FC',
1366 ),
1367 array(
1368 'label' => 'Secondary',
1369 'value' => '#6FC784',
1370 ),
1371 array(
1372 'label' => 'Tertiary',
1373 'value' => '#FF5A6E',
1374 ),
1375 array(
1376 'label' => 'Accent',
1377 'value' => '#F3F3F3',
1378 ),
1379 array(
1380 'label' => 'Background',
1381 'value' => '#888888',
1382 ),
1383 ),
1384 'gradient' => array(
1385 array(
1386 'label' => 'Primary',
1387 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1388 ),
1389
1390 array(
1391 'label' => 'Secondary',
1392 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1393 ),
1394
1395 array(
1396 'label' => 'Tertiary',
1397 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1398 ),
1399
1400 array(
1401 'label' => 'Accent',
1402 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1403 ),
1404
1405 array(
1406 'label' => 'Background',
1407 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1408 ),
1409 ),
1410 'spacing' => array(
1411 array(
1412 'label' => 'Large',
1413 'value' => array(
1414 'md' => 70,
1415 'unit' => 'px',
1416 ),
1417 ),
1418 array(
1419 'label' => 'Medium',
1420 'value' => array(
1421 'md' => 40,
1422 'unit' => 'px',
1423 ),
1424 ),
1425 array(
1426 'label' => 'Small',
1427 'value' => array(
1428 'md' => 20,
1429 'unit' => 'px',
1430 ),
1431
1432 ),
1433 ),
1434 'typography' => array(
1435 array(
1436 'label' => 'Display Text',
1437 'value' => array(
1438 'openTypography' => 1,
1439 'size' => array(
1440 'md' => 65,
1441 'unit' => 'px',
1442 ),
1443 'height' => array(
1444 'md' => 75,
1445 'unit' => 'px',
1446 ),
1447 'fontFamily' => array(
1448 'family' => 'Roboto',
1449 'type' => 'sans-serif',
1450 'fontWeight' => 700,
1451 ),
1452 'spacing' => array(
1453 'md' => 0,
1454 'unit' => 'px',
1455 ),
1456 ),
1457 ),
1458 array(
1459 'label' => 'Headline',
1460 'value' => array(
1461 'openTypography' => 1,
1462 'size' => array(
1463 'md' => 45,
1464 'unit' => 'px',
1465 ),
1466 'height' => array(
1467 'md' => 60,
1468 'unit' => 'px',
1469 ),
1470 'fontFamily' => array(
1471 'family' => 'Roboto',
1472 'type' => 'sans-serif',
1473 'fontWeight' => 700,
1474 ),
1475 'spacing' => array(
1476 'md' => 0,
1477 'unit' => 'px',
1478 ),
1479 ),
1480 ),
1481 array(
1482 'label' => 'Sub Headline',
1483 'value' => array(
1484 'openTypography' => 1,
1485 'size' => array(
1486 'md' => 38,
1487 'unit' => 'px',
1488 ),
1489 'height' => array(
1490 'md' => 45,
1491 'unit' => 'px',
1492 ),
1493 'fontFamily' => array(
1494 'family' => 'Roboto',
1495 'type' => 'sans-serif',
1496 'fontWeight' => 500,
1497 ),
1498 'spacing' => array(
1499 'md' => 0,
1500 'unit' => 'px',
1501 ),
1502 ),
1503 ),
1504 array(
1505 'label' => 'Title 1',
1506 'value' => array(
1507 'openTypography' => 1,
1508 'size' => array(
1509 'md' => 30,
1510 'unit' => 'px',
1511 ),
1512 'height' => array(
1513 'md' => 40,
1514 'unit' => 'px',
1515 ),
1516 'fontFamily' => array(
1517 'family' => 'Roboto',
1518 'type' => 'sans-serif',
1519 'fontWeight' => 500,
1520 ),
1521 'spacing' => array(
1522 'md' => 0,
1523 'unit' => 'px',
1524 ),
1525 ),
1526 ),
1527 array(
1528 'label' => 'Title 2',
1529 'value' => array(
1530 'openTypography' => 1,
1531 'size' => array(
1532 'md' => 25,
1533 'unit' => 'px',
1534 ),
1535 'height' => array(
1536 'md' => 30,
1537 'unit' => 'px',
1538 ),
1539 'fontFamily' => array(
1540 'family' => 'Roboto',
1541 'type' => 'sans-serif',
1542 'fontWeight' => 400,
1543 ),
1544 'spacing' => array(
1545 'md' => 0,
1546 'unit' => 'px',
1547 ),
1548 ),
1549 ),
1550 array(
1551 'label' => 'Body',
1552 'value' => array(
1553 'openTypography' => 1,
1554 'size' => array(
1555 'md' => 17,
1556 'unit' => 'px',
1557 ),
1558 'height' => array(
1559 'md' => 22,
1560 'unit' => 'px',
1561 ),
1562 'fontFamily' => array(
1563 'family' => 'Roboto',
1564 'type' => 'sans-serif',
1565 'fontWeight' => 400,
1566 ),
1567 'spacing' => array(
1568 'md' => 0,
1569 'unit' => 'px',
1570 ),
1571 ),
1572 ),
1573 array(
1574 'label' => 'Captions',
1575 'value' => array(
1576 'openTypography' => 1,
1577 'size' => array(
1578 'md' => 13,
1579 'unit' => 'px',
1580 ),
1581 'height' => array(
1582 'md' => 16,
1583 'unit' => 'px',
1584 ),
1585 'fontFamily' => array(
1586 'family' => 'Roboto',
1587 'type' => 'sans-serif',
1588 'fontWeight' => 400,
1589 ),
1590 'spacing' => array(
1591 'md' => 0,
1592 'unit' => 'px',
1593 ),
1594 ),
1595 ),
1596 ),
1597 'boxshadow' => array(
1598 array(
1599 'label' => 'Normal Shadow',
1600 'value' => array(
1601 'openShadow' => 1,
1602 'inset' => 0,
1603 'horizontal' => 2,
1604 'vertical' => 6,
1605 'blur' => 10,
1606 'spread' => 0,
1607 'color' => 'rgba(0,0,0,0.15)',
1608 ),
1609 ),
1610 array(
1611 'label' => 'Hover Shadow',
1612 'value' => array(
1613 'openShadow' => 1,
1614 'inset' => 0,
1615 'horizontal' => 2,
1616 'vertical' => 5,
1617 'blur' => 14,
1618 'spread' => 3,
1619 'color' => 'rgba(0,0,0,0.2)',
1620 ),
1621 ),
1622 ),
1623 ),
1624 'preset2' => array(
1625 'name' => 'Preset 2',
1626 'key' => 'preset2',
1627 'colors' => array(
1628 array(
1629 'label' => 'Primary',
1630 'value' => '#8072FC',
1631 ),
1632 array(
1633 'label' => 'Secondary',
1634 'value' => '#6FC784',
1635 ),
1636 array(
1637 'label' => 'Tertiary',
1638 'value' => '#FF5A6E',
1639 ),
1640 array(
1641 'label' => 'Accent',
1642 'value' => '#F3F3F3',
1643 ),
1644 array(
1645 'label' => 'Background',
1646 'value' => '#888888',
1647 ),
1648 ),
1649 'gradient' => array(
1650 array(
1651 'label' => 'Primary',
1652 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1653 ),
1654
1655 array(
1656 'label' => 'Secondary',
1657 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1658 ),
1659
1660 array(
1661 'label' => 'Tertiary',
1662 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1663 ),
1664
1665 array(
1666 'label' => 'Accent',
1667 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1668 ),
1669
1670 array(
1671 'label' => 'Background',
1672 'value' => 'linear-gradient(135deg,rgb(8,148,229) 0%,rgb(155,81,224) 100%)',
1673 ),
1674 ),
1675 'spacing' => array(
1676 array(
1677 'label' => 'Large',
1678 'value' => array(
1679 'md' => 70,
1680 'unit' => 'px',
1681 ),
1682 ),
1683 array(
1684 'label' => 'Medium',
1685 'value' => array(
1686 'md' => 40,
1687 'unit' => 'px',
1688 ),
1689 ),
1690 array(
1691 'label' => 'Small',
1692 'value' => array(
1693 'md' => 20,
1694 'unit' => 'px',
1695 ),
1696
1697 ),
1698 ),
1699 'typography' => array(
1700 array(
1701 'label' => 'Display Text',
1702 'value' => array(
1703 'openTypography' => 1,
1704 'size' => array(
1705 'md' => 65,
1706 'unit' => 'px',
1707 ),
1708 'height' => array(
1709 'md' => 75,
1710 'unit' => 'px',
1711 ),
1712 'fontFamily' => array(
1713 'family' => 'Roboto',
1714 'type' => 'sans-serif',
1715 'fontWeight' => 700,
1716 ),
1717 'spacing' => array(
1718 'md' => 0,
1719 'unit' => 'px',
1720 ),
1721 ),
1722 ),
1723 array(
1724 'label' => 'Headline',
1725 'value' => array(
1726 'openTypography' => 1,
1727 'size' => array(
1728 'md' => 45,
1729 'unit' => 'px',
1730 ),
1731 'height' => array(
1732 'md' => 60,
1733 'unit' => 'px',
1734 ),
1735 'fontFamily' => array(
1736 'family' => 'Roboto',
1737 'type' => 'sans-serif',
1738 'fontWeight' => 700,
1739 ),
1740 'spacing' => array(
1741 'md' => 0,
1742 'unit' => 'px',
1743 ),
1744 ),
1745 ),
1746 array(
1747 'label' => 'Sub Headline',
1748 'value' => array(
1749 'openTypography' => 1,
1750 'size' => array(
1751 'md' => 38,
1752 'unit' => 'px',
1753 ),
1754 'height' => array(
1755 'md' => 45,
1756 'unit' => 'px',
1757 ),
1758 'fontFamily' => array(
1759 'family' => 'Roboto',
1760 'type' => 'sans-serif',
1761 'fontWeight' => 500,
1762 ),
1763 'spacing' => array(
1764 'md' => 0,
1765 'unit' => 'px',
1766 ),
1767 ),
1768 ),
1769 array(
1770 'label' => 'Title 1',
1771 'value' => array(
1772 'openTypography' => 1,
1773 'size' => array(
1774 'md' => 30,
1775 'unit' => 'px',
1776 ),
1777 'height' => array(
1778 'md' => 40,
1779 'unit' => 'px',
1780 ),
1781 'fontFamily' => array(
1782 'family' => 'Roboto',
1783 'type' => 'sans-serif',
1784 'fontWeight' => 500,
1785 ),
1786 'spacing' => array(
1787 'md' => 0,
1788 'unit' => 'px',
1789 ),
1790 ),
1791 ),
1792 array(
1793 'label' => 'Title 2',
1794 'value' => array(
1795 'openTypography' => 1,
1796 'size' => array(
1797 'md' => 25,
1798 'unit' => 'px',
1799 ),
1800 'height' => array(
1801 'md' => 30,
1802 'unit' => 'px',
1803 ),
1804 'fontFamily' => array(
1805 'family' => 'Roboto',
1806 'type' => 'sans-serif',
1807 'fontWeight' => 400,
1808 ),
1809 'spacing' => array(
1810 'md' => 0,
1811 'unit' => 'px',
1812 ),
1813 ),
1814 ),
1815 array(
1816 'label' => 'Body',
1817 'value' => array(
1818 'openTypography' => 1,
1819 'size' => array(
1820 'md' => 17,
1821 'unit' => 'px',
1822 ),
1823 'height' => array(
1824 'md' => 22,
1825 'unit' => 'px',
1826 ),
1827 'fontFamily' => array(
1828 'family' => 'Roboto',
1829 'type' => 'sans-serif',
1830 'fontWeight' => 400,
1831 ),
1832 'spacing' => array(
1833 'md' => 0,
1834 'unit' => 'px',
1835 ),
1836 ),
1837 ),
1838 array(
1839 'label' => 'Captions',
1840 'value' => array(
1841 'openTypography' => 1,
1842 'size' => array(
1843 'md' => 13,
1844 'unit' => 'px',
1845 ),
1846 'height' => array(
1847 'md' => 16,
1848 'unit' => 'px',
1849 ),
1850 'fontFamily' => array(
1851 'family' => 'Roboto',
1852 'type' => 'sans-serif',
1853 'fontWeight' => 400,
1854 ),
1855 'spacing' => array(
1856 'md' => 0,
1857 'unit' => 'px',
1858 ),
1859 ),
1860 ),
1861 ),
1862 'boxshadow' => array(
1863 array(
1864 'label' => 'Normal Shadow',
1865 'value' => array(
1866 'openShadow' => 1,
1867 'inset' => 0,
1868 'horizontal' => 2,
1869 'vertical' => 6,
1870 'blur' => 10,
1871 'spread' => 0,
1872 'color' => 'rgba(0,0,0,0.15)',
1873 ),
1874 ),
1875 array(
1876 'label' => 'Hover Shadow',
1877 'value' => array(
1878 'openShadow' => 1,
1879 'inset' => 0,
1880 'horizontal' => 2,
1881 'vertical' => 5,
1882 'blur' => 14,
1883 'spread' => 3,
1884 'color' => 'rgba(0,0,0,0.2)',
1885 ),
1886 ),
1887 ),
1888 ),
1889 ),
1890 'globalContainer' => array(
1891 'md' => '',
1892 'unit' => 'px',
1893 ),
1894 );
1895
1896 update_option( 'tpgb_global_options', json_encode( $static_meta ) );
1897 $plus_settings = $static_meta;
1898 }
1899
1900 $active_id = ! empty( $plus_settings['active'] ) ? $plus_settings['active'] : '';
1901 $preset_array = ! empty( $plus_settings['presets'] ) ? $plus_settings['presets'] : array();
1902 $act_preset = ! empty( $plus_settings['presets'][ $active_id ] ) ? $plus_settings['presets'][ $active_id ] : array();
1903
1904 foreach ( $act_preset['colors'] as $index => &$item ) {
1905 $item['id'] = $index + 1;
1906 }
1907 unset( $item );
1908
1909 foreach ( $act_preset['typography'] as $index => &$item ) {
1910 $item['id'] = $index + 1;
1911 }
1912 unset( $item );
1913
1914 $act_preset['color'] = $act_preset['colors'];
1915 unset( $act_preset['colors'] );
1916
1917 $response = array(
1918 'message' => __( 'Global data Found', 'wdesignkit' ),
1919 'description' => __( 'Global Color and Typography found', 'wdesignkit' ),
1920 'data' => $act_preset,
1921 'success' => true,
1922 );
1923 }
1924
1925 wp_send_json( $response );
1926 wp_die();
1927 }
1928
1929 /**
1930 *
1931 * Get site settings.
1932 *
1933 * @since 2.1.3
1934 */
1935 protected function wdkit_get_site_setting() {
1936
1937 $kit_id = get_option( 'elementor_active_kit' );
1938 if ( empty( $kit_id ) ) {
1939 $response = array(
1940 'message' => __( 'Elementor kit not found', 'wdesignkit' ),
1941 'description' => __( 'No active Elementor kit found', 'wdesignkit' ),
1942 'success' => false,
1943 );
1944
1945 wp_send_json( $response );
1946 wp_die();
1947 }
1948
1949 $kit_meta = get_post_meta( $kit_id, '_elementor_page_settings', true );
1950
1951 $container_width = ! empty( $kit_meta['container_width'] ) ? $kit_meta['container_width'] : array();
1952 $globals = ! empty( $kit_meta['__globals__'] ) ? $kit_meta['__globals__'] : array();
1953 $body_background_color = ! empty( $kit_meta['body_background_color'] ) ? $kit_meta['body_background_color'] : array();
1954
1955 $site_globals = array(
1956 'body_background_color' => $body_background_color,
1957 'container_width' => $container_width,
1958 'globals' => $globals,
1959 );
1960
1961 $response = array(
1962 'message' => __( 'Global data Found', 'wdesignkit' ),
1963 'description' => __( 'Global Color and Typography found', 'wdesignkit' ),
1964 'data' => $site_globals,
1965 'success' => true,
1966 );
1967
1968 wp_send_json( $response );
1969 wp_die();
1970 }
1971
1972 /**
1973 *
1974 * update site settings.
1975 *
1976 * @since 2.1.3
1977 */
1978 protected function wdkit_update_site_setting() {
1979
1980 $builder = ! empty( $_POST['builder'] ) ? sanitize_text_field( $_POST['builder'] ) : '';
1981 $site_data = ! empty( $_POST['site_data'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['site_data'] ) ), true ) : array();
1982
1983 if ( 'elementor' == $builder ) {
1984 $kit_id = get_option( 'elementor_active_kit' );
1985 if ( ! $kit_id && did_action( 'elementor/loaded' ) && class_exists( '\Elementor\Core\Kits\Manager' ) ) {
1986 \Elementor\Core\Kits\Manager::create_default_kit();
1987 $kit_id = get_option( 'elementor_active_kit' );
1988 }
1989
1990 if ( ! $kit_id ) {
1991 $response = array(
1992 'message' => __( 'Elementor kit not found', 'wdesignkit' ),
1993 'description' => __( 'No active Elementor kit found', 'wdesignkit' ),
1994 'success' => false,
1995 );
1996
1997 wp_send_json( $response );
1998 wp_die();
1999 }
2000
2001 // A freshly created kit has no `_elementor_page_settings` meta yet,
2002 // so an empty result here is a valid starting point, not an error.
2003 $kit_meta = get_post_meta( $kit_id, '_elementor_page_settings', true );
2004 if ( ! is_array( $kit_meta ) ) {
2005 $kit_meta = array();
2006 }
2007
2008 $kit_meta['container_width'] = ! empty( $site_data['container_width'] ) ? $site_data['container_width'] : array();
2009 $kit_meta['__globals__'] = ! empty( $site_data['globals'] ) ? $site_data['globals'] : array();
2010 $kit_meta['body_background_color'] = ! empty( $site_data['body_background_color'] ) ? $site_data['body_background_color'] : array();
2011
2012 update_post_meta( $kit_id, '_elementor_page_settings', $kit_meta );
2013
2014 // Regenerate Elementor's cached CSS. Writing the kit meta directly does
2015 // not rebuild the kit stylesheet, so the imported body background colour
2016 // and container width would otherwise never render on the frontend.
2017 $this->wdkit_regenerate_elementor_kit_css();
2018
2019 $response = array(
2020 'message' => __( 'Site data Updated', 'wdesignkit' ),
2021 'description' => __( 'Site Globals Updated', 'wdesignkit' ),
2022 'success' => true,
2023 );
2024
2025 } elseif ( 'gutenberg' == $builder ) {
2026 $plus_settings = get_option( 'tpgb_global_options' );
2027
2028 $site_preset = json_decode( $plus_settings, true );
2029 $site_preset['globalContainer'] = $site_data;
2030
2031 update_option( 'tpgb_global_options', json_encode( $site_preset ) );
2032
2033 $response = array(
2034 'message' => __( 'Site data Updated', 'wdesignkit' ),
2035 'description' => __( 'Site Globals Updated', 'wdesignkit' ),
2036 'success' => true,
2037 );
2038
2039 } else {
2040 $response = array(
2041 'message' => __( 'Builder Not Found !', 'wdesignkit' ),
2042 'description' => __( 'Template Builder not Found', 'wdesignkit' ),
2043 'success' => true,
2044 );
2045 }
2046
2047 wp_send_json( $response );
2048 wp_die();
2049 }
2050
2051 /**
2052 *
2053 * Update Elementor Global color and Typography.
2054 *
2055 * @since 1.1.20
2056 */
2057 protected function wdkit_update_global_val() {
2058
2059 $builder = ! empty( $_POST['builder'] ) ? sanitize_text_field( $_POST['builder'] ) : '';
2060
2061 if ( 'elementor' == $builder ) {
2062
2063 $g_color = ! empty( $_POST['g_color'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['g_color'] ) ), true ) : array();
2064 $g_typo = ! empty( $_POST['g_typography'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['g_typography'] ) ), true ) : array();
2065
2066 // Get colors from Elementor Site Kit
2067 $kit_id = get_option( 'elementor_active_kit' );
2068 if ( ! $kit_id && did_action( 'elementor/loaded' ) && class_exists( '\Elementor\Core\Kits\Manager' ) ) {
2069 // No kit has ever been created on this site (the option is only
2070 // ever populated by Elementor's own activation hook). Create one
2071 // via Elementor's own helper so the import has somewhere to write.
2072 \Elementor\Core\Kits\Manager::create_default_kit();
2073 $kit_id = get_option( 'elementor_active_kit' );
2074 }
2075
2076 if ( ! $kit_id ) {
2077 $response = array(
2078 'message' => __( 'Elementor kit not found', 'wdesignkit' ),
2079 'description' => __( 'No active Elementor kit found', 'wdesignkit' ),
2080 'success' => false,
2081 );
2082
2083 wp_send_json( $response );
2084 wp_die();
2085 }
2086
2087 // A freshly created kit has no `_elementor_page_settings` meta yet,
2088 // so an empty result here is a valid starting point, not an error.
2089 $kit_meta = get_post_meta( $kit_id, '_elementor_page_settings', true );
2090 if ( ! is_array( $kit_meta ) ) {
2091 $kit_meta = array();
2092 }
2093
2094 $kit_meta['custom_colors'] = array_merge( $g_color, $kit_meta['custom_colors'] ?? array() );
2095 $kit_meta['custom_typography'] = array_merge( $g_typo, $kit_meta['custom_typography'] ?? array() );
2096
2097 update_post_meta( $kit_id, '_elementor_page_settings', $kit_meta );
2098
2099 // Regenerate Elementor's cached CSS. Writing the kit meta directly does
2100 // not rebuild the kit stylesheet, so the imported global colours and
2101 // fonts would otherwise never render on the frontend.
2102 $this->wdkit_regenerate_elementor_kit_css();
2103
2104 $response = array(
2105 'message' => __( 'Global data Updated', 'wdesignkit' ),
2106 'description' => __( 'Global Color and Typography Updated', 'wdesignkit' ),
2107 'success' => true,
2108 );
2109
2110 } elseif ( 'gutenberg' == $builder ) {
2111 $new_preset = ! empty( $_POST['new_preset'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['new_preset'] ) ), true ) : array();
2112 $new_preset_id = ! empty( $new_preset['key'] ) ? $new_preset['key'] : '';
2113 $plus_settings = get_option( 'tpgb_global_options' );
2114 $site_preset = json_decode( $plus_settings, true );
2115
2116 $site_preset['presets'][ $new_preset_id ] = $new_preset;
2117 $site_preset['active'] = $new_preset_id;
2118
2119 update_option( 'tpgb_global_options', json_encode( $site_preset ) );
2120
2121 $response = array(
2122 'message' => __( 'Global data Updated', 'wdesignkit' ),
2123 'description' => __( 'Global Color and Typography Updated', 'wdesignkit' ),
2124 'success' => true,
2125 );
2126
2127 } else {
2128 $response = array(
2129 'message' => __( 'Builder Not Found !', 'wdesignkit' ),
2130 'description' => __( 'Template Builder not Found', 'wdesignkit' ),
2131 'success' => true,
2132 );
2133 }
2134
2135 wp_send_json( $response );
2136 wp_die();
2137 }
2138
2139 /**
2140 * Regenerate Elementor's cached CSS files after the active kit's
2141 * `_elementor_page_settings` meta has been changed directly.
2142 *
2143 * Elementor renders global colours, global fonts and the body background
2144 * colour into a cached kit stylesheet. Updating the meta via
2145 * update_post_meta() does not rebuild that stylesheet, so imported site
2146 * settings never reach the frontend until the cache is cleared. This
2147 * mirrors the clear_cache() call already used by the page/section import.
2148 *
2149 * @since 2.3.2
2150 *
2151 * @return void
2152 */
2153 protected function wdkit_regenerate_elementor_kit_css() {
2154 if ( did_action( 'elementor/loaded' ) && class_exists( '\Elementor\Plugin' ) ) {
2155 \Elementor\Plugin::$instance->files_manager->clear_cache();
2156 }
2157 }
2158
2159 /**
2160 *
2161 * Create Gutenberg page and save for re-generate css file.
2162 *
2163 * @since 1.2.3
2164 */
2165 protected function wdkit_update_preset() {
2166
2167 $act_type = ! empty( $_POST['act_type'] ) ? sanitize_text_field( $_POST['act_type'] ) : '';
2168 $post_id = ! empty( $_POST['post_id'] ) ? sanitize_text_field( $_POST['post_id'] ) : '';
2169
2170 if ( 'create' == $act_type ) {
2171
2172 $page_id = wp_insert_post(
2173 array(
2174 'post_title' => 'WDesignKit Gutenberg',
2175 'post_status' => 'publish',
2176 'post_type' => 'post',
2177 'post_name' => sanitize_title( 'wdesignkit' ),
2178 'post_content' => '<!-- wp:heading --><h2 class="wp-block-heading">Add Your Heading Text Here<h2><!-- /wp:heading -->',
2179 'meta_input' => array(
2180 'gutenberg_preview' => true,
2181 '_wp_page_template' => 'default',
2182 ),
2183 )
2184 );
2185
2186 if ( is_wp_error( $page_id ) || ! $page_id ) {
2187 $response = array(
2188 'success' => true,
2189 'message' => esc_html__( 'Page Not Found!', 'wdesignkit' ),
2190 'description' => esc_html__( 'Page Not Found!', 'wdesignkit' ),
2191 );
2192
2193 wp_send_json( $response );
2194 wp_die();
2195 }
2196
2197 update_post_meta( $page_id, '_edit_lock', time() . ':1' );
2198 update_post_meta( $page_id, '_edit_last', get_current_user_id() );
2199
2200 $preview_url = admin_url( 'post.php?post=' . $page_id . '&action=edit' );
2201
2202 $response = array(
2203 'success' => true,
2204 'post_id' => $page_id,
2205 'preview_url' => $preview_url,
2206 'message' => esc_html__( 'Page Created', 'wdesignkit' ),
2207 'description' => esc_html__( 'Page Created', 'wdesignkit' ),
2208 );
2209
2210 wp_send_json( $response );
2211 wp_die();
2212
2213 }
2214
2215 if ( ! empty( $post_id ) && ( $act_type == 'remove' ) ) {
2216
2217 wp_delete_post( $post_id, true );
2218
2219 $response = array(
2220 'success' => true,
2221 'message' => esc_html__( 'post deleted', 'wdesignkit' ),
2222 'description' => esc_html__( 'post deleted', 'wdesignkit' ),
2223 );
2224
2225 wp_send_json( $response );
2226 wp_die();
2227 }
2228 }
2229
2230 /**
2231 *
2232 * It is For Find User Existing template List.
2233 *
2234 * @since 1.0.6
2235 */
2236 protected function wdkit_find_existing_template() {
2237 $array_data = array(
2238 'search' => isset( $_POST['search'] ) ? sanitize_text_field( wp_unslash( $_POST['search'] ) ) : '',
2239 'token' => isset( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : '',
2240 'type' => isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '',
2241 'u_id' => isset( $_POST['u_id'] ) ? sanitize_text_field( wp_unslash( $_POST['u_id'] ) ) : '',
2242 'builder' => isset( $_POST['builder'] ) ? sanitize_text_field( wp_unslash( $_POST['builder'] ) ) : '',
2243 'parpage' => isset( $_POST['parpage'] ) ? sanitize_text_field( wp_unslash( $_POST['parpage'] ) ) : 12,
2244 );
2245
2246 $response = $this->wkit_api_call( $array_data, 'existing_template' );
2247
2248 wp_send_json( $response );
2249 wp_die();
2250 }
2251
2252 /**
2253 *
2254 * It is For Update User Existing template List.
2255 *
2256 * @since 1.0.6
2257 */
2258 protected function wdkit_update_template() {
2259 $array_data = array(
2260 'data' => isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : '',
2261 'post_id' => isset( $_POST['post_id'] ) ? sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) : '',
2262 'token' => isset( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : '',
2263 'type' => isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '',
2264 'id' => isset( $_POST['id'] ) ? sanitize_text_field( wp_unslash( $_POST['id'] ) ) : '',
2265 'global_data' => isset( $_POST['global_data'] ) ? wp_unslash( $_POST['global_data'] ) : array(),
2266 // 'global_font_family' => isset( $_POST['global_font_family'] ) ? wp_unslash( $_POST['global_font_family'] ) : array(),
2267 // 'global_color' => isset( $_POST['global_color'] ) ? wp_unslash( $_POST['global_color'] ) : array(),
2268 );
2269
2270 if ( ! empty( $array_data['post_id'] ) ) {
2271 $custom_fields = array();
2272 $post_id = $array_data['post_id'];
2273
2274 $meta_fields = get_post_custom( $post_id );
2275
2276 foreach ( $meta_fields as $key => $value ) {
2277 if ( str_contains( $key, 'nxt-' ) ) {
2278 $custom_fields[ $key ] = $value;
2279 }
2280 }
2281
2282 if ( ! empty( $custom_fields ) ) {
2283 $data = json_decode( $array_data['data'], true );
2284 $data['custom_meta'] = $custom_fields;
2285 $array_data['data'] = wp_json_encode( $data );
2286 }
2287 }
2288
2289 $array_data['remove'] = 'yes';
2290 $response = $this->wkit_api_call( $array_data, 'existing_template' );
2291 wp_send_json( $response );
2292 wp_die();
2293 }
2294
2295 /**
2296 *
2297 * It is Use for manage favourite template.
2298 *
2299 * @since 1.0.0
2300 */
2301 protected function wdkit_manage_favorite() {
2302 $template_id = isset( $_POST['template_id'] ) ? strtolower( sanitize_text_field( wp_unslash( $_POST['template_id'] ) ) ) : 0;
2303 $email = isset( $_POST['email'] ) ? strtolower( sanitize_email( wp_unslash( $_POST['email'] ) ) ) : false;
2304
2305 if ( empty( $email ) || empty( $template_id ) ) {
2306 $response = array(
2307 'message' => $this->e_msg_login,
2308 'description' => $this->e_desc_login,
2309 'success' => false,
2310 );
2311
2312 wp_send_json( $response );
2313 wp_die();
2314 }
2315
2316 $args = $this->wdkit_parse_args( $_POST );
2317 $args['token'] = $this->wdkit_login_user_token( $email );
2318
2319 unset( $args['email'] );
2320 $response = WDesignKit_Data_Query::get_data( 'manage_favorite', $args );
2321
2322 wp_send_json( $response );
2323 wp_die();
2324 }
2325
2326 /**
2327 *
2328 * It is Use for Check Plugin Dependency of template.
2329 *
2330 * @since 1.0.0
2331 * @version 1.0.9
2332 */
2333 protected function wdkit_check_plugins_depends() {
2334 $plugins = isset( $_POST['plugins'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['plugins'] ) ) ) : array();
2335 $update_plugin = array();
2336 $update_theme = array();
2337
2338 if ( empty( $plugins ) || ! is_array( $plugins ) ) {
2339 $this->wdkit_error_msg( array( 'plugins' => 'No Plugins' ) );
2340 }
2341
2342 $all_plugins = $this->get_plugins();
2343 foreach ( $plugins as $plugin ) {
2344 $pluginslug = ! empty( $plugin->plugin_slug ) ? sanitize_text_field( wp_unslash( $plugin->plugin_slug ) ) : '';
2345 $free_pro = ! empty( $plugin->freepro ) ? sanitize_text_field( wp_unslash( $plugin->freepro ) ) : '0';
2346 $type = ! empty( $plugin->type ) ? sanitize_text_field( wp_unslash( $plugin->type ) ) : 'plugin';
2347
2348 if ( is_null( $pluginslug ) ) {
2349 $plugin->status = 'warning';
2350 $update_plugin[] = $plugin;
2351 $update_theme[] = $plugin;
2352
2353 continue;
2354 }
2355
2356 if ( 'plugin' === $type ) {
2357 if ( ! is_plugin_active( $pluginslug ) ) {
2358 if ( ! isset( $all_plugins[ $pluginslug ] ) ) {
2359 if ( isset( $free_pro ) && '1' === $free_pro ) {
2360 $plugin->status = 'manually';
2361 } else {
2362 $plugin->status = 'unavailable';
2363 }
2364 } else {
2365 $plugin->status = 'inactive';
2366 }
2367
2368 $update_plugin[] = $plugin;
2369 } elseif ( is_plugin_active( $pluginslug ) ) {
2370 $plugin->status = 'active';
2371 $update_plugin[] = $plugin;
2372 }
2373 } elseif ( 'theme' === $type ) {
2374 $theme_array = array_keys( wp_get_themes() );
2375 $theme_slug = get_stylesheet();
2376 $parent_theme_slug = get_template();
2377
2378 if ( $theme_slug === $plugin->original_slug || $parent_theme_slug === $plugin->original_slug ) {
2379
2380 $plugin->status = 'active';
2381 } else {
2382 $theme_name = $plugin->original_slug;
2383 if ( ! in_array( $theme_name, $theme_array ) ) {
2384 if ( isset( $free_pro ) && '1' === $free_pro ) {
2385 $plugin->status = 'manually';
2386 } else {
2387 $plugin->status = 'unavailable';
2388 }
2389 } else {
2390 $plugin->status = 'inactive';
2391 }
2392 }
2393
2394 $update_theme[] = $plugin;
2395 }
2396 }
2397
2398 $response = array(
2399 'plugins' => $update_plugin,
2400 'theme' => $update_theme,
2401 'ele_container' => get_option( 'elementor_experiment-container', false ),
2402 );
2403
2404 $this->wdkit_success_msg( $response );
2405 }
2406
2407 /**
2408 *
2409 * It is Use for Install dependent plugin.
2410 *
2411 * @since 1.0.0
2412 * @version 1.0.9
2413 */
2414 protected function wdkit_install_plugins_depends() {
2415 $plugins = isset( $_POST['plugins'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['plugins'] ) ), true ) : array();
2416 $type = ! empty( $plugins['type'] ) ? $plugins['type'] : 'plugin';
2417 $p_id = ! empty( $plugins['p_id'] ) ? $plugins['p_id'] : 'plugin';
2418
2419 $responce = '';
2420 if ( 'plugin' === $type ) {
2421 $responce = Wdkit_Depends_Installer::get_instance()->wdkit_install_plugin( $plugins );
2422 } elseif ( 'theme' === $type ) {
2423 $theme_name = ! empty( $plugins['original_slug'] ) ? $plugins['original_slug'] : '';
2424 if ( ! empty( $theme_name ) ) {
2425
2426 $theme_array = array_keys( wp_get_themes() );
2427 $theme_slug = get_stylesheet();
2428
2429 if ( in_array( $theme_name, $theme_array ) ) {
2430 $activate_result = switch_theme( $theme_name );
2431
2432 if ( ! is_wp_error( $activate_result ) ) {
2433 $responce = array(
2434 'message' => esc_html__( 'Theme activated successfully', 'wdesignkit' ),
2435 'description' => esc_html__( 'Theme successfully activated', 'wdesignkit' ),
2436 'slug' => 'nexter',
2437 'p_id' => $p_id,
2438 'status' => 'active',
2439 'success' => true,
2440 );
2441 } else {
2442 $responce = array(
2443 'message' => esc_html__( 'Theme Not Activated !', 'wdesignkit' ),
2444 'description' => $activate_result->get_error_message(),
2445 'status' => 'inactive',
2446 'p_id' => $p_id,
2447 'success' => false,
2448 );
2449 }
2450 } else {
2451 $result = $this->wdkit_install_theme_depends( $theme_name );
2452
2453 $message = ! empty( $result['message'] ) ? $result['message'] : esc_html__( 'Somthing Wrong', 'wdesignkit' );
2454 $description = ! empty( $result['description'] ) ? $result['description'] : esc_html__( 'Error Somthing Wrong', 'wdesignkit' );
2455 $status = ! empty( $result['status'] ) ? $result['status'] : esc_html__( 'inactive', 'wdesignkit' );
2456 $success = ! empty( $result['success'] ) ? $result['success'] : false;
2457
2458 $responce = array(
2459 'message' => $message,
2460 'description' => $description,
2461 'p_id' => $p_id,
2462 'status' => $status,
2463 'success' => $success,
2464 );
2465 }
2466 } else {
2467 $responce = array(
2468 'message' => esc_html__( 'Theme Name not Found', 'wdesignkit' ),
2469 'description' => esc_html__( 'Can Not Found Theme Name you Enterd.', 'wdesignkit' ),
2470 'success' => false,
2471 );
2472 }
2473 }
2474
2475 wp_send_json( $responce );
2476 wp_die();
2477 }
2478
2479 protected function wdkit_install_theme_depends( $name = 'nexter' ) {
2480
2481 if ( ! current_user_can( 'install_themes' ) ) {
2482 $response = $this->tpae_set_response( false, 'Invalid nonce.', 'The security check failed. Please refresh the page and try again.' );
2483 return $response;
2484 }
2485
2486 $theme_slug = $name;
2487 $theme_api_url = 'https://api.wordpress.org/themes/info/1.0/';
2488
2489 // Parameters for the request
2490 $args = array(
2491 'body' => array(
2492 'action' => 'theme_information',
2493 'request' => serialize(
2494 (object) array(
2495 'slug' => $name,
2496 'fields' => array(
2497 'description' => false,
2498 'sections' => false,
2499 'rating' => true,
2500 'ratings' => false,
2501 'downloaded' => true,
2502 'download_link' => true,
2503 'last_updated' => true,
2504 'homepage' => true,
2505 'tags' => true,
2506 'template' => true,
2507 'active_installs' => false,
2508 'parent' => false,
2509 'versions' => false,
2510 'screenshot_url' => true,
2511 'active_installs' => false,
2512 ),
2513 )
2514 ),
2515 ),
2516 );
2517
2518 // Make the request
2519 $response = wp_remote_post( $theme_api_url, $args );
2520 // Check for errors
2521 if ( is_wp_error( $response ) ) {
2522 $error_message = $response->get_error_message();
2523
2524 $result = $this->tpae_set_response( false, 'oops', 'oops', '' );
2525 } else {
2526 $theme_info = unserialize( $response['body'] );
2527 $theme_name = $theme_info->name;
2528 $theme_zip_url = $theme_info->download_link;
2529
2530 global $wp_filesystem;
2531 // Install the theme
2532 $theme = wp_remote_get( $theme_zip_url, array( 'timeout' => 30 ) );
2533
2534 if ( ! function_exists( 'WP_Filesystem' ) ) {
2535 require_once wp_normalize_path( ABSPATH . '/wp-admin/includes/file.php' );
2536 }
2537
2538 WP_Filesystem();
2539
2540 $active_theme = wp_get_theme();
2541 $theme_name = $active_theme->get( 'Name' );
2542
2543 $wp_filesystem->put_contents( WP_CONTENT_DIR . '/themes/' . $theme_slug . '.zip', $theme['body'] );
2544 $zip = new ZipArchive();
2545 if ( $zip->open( WP_CONTENT_DIR . '/themes/' . $theme_slug . '.zip' ) === true ) {
2546 $zip->extractTo( WP_CONTENT_DIR . '/themes/' );
2547 $zip->close();
2548 }
2549
2550 $wp_filesystem->delete( WP_CONTENT_DIR . '/themes/' . $theme_slug . '.zip' );
2551
2552 $activate_result = switch_theme( $name );
2553
2554 if ( ! is_wp_error( $activate_result ) ) {
2555 $response = array(
2556 'message' => esc_html__( 'Theme activated successfully', 'wdesignkit' ),
2557 'description' => esc_html__( 'Theme successfully activated', 'wdesignkit' ),
2558 'status' => 'active',
2559 'success' => true,
2560 );
2561 } else {
2562 $response = array(
2563 'message' => esc_html__( 'Theme Not Activated !', 'wdesignkit' ),
2564 'description' => $activate_result->get_error_message(),
2565 'status' => 'inactive',
2566 'success' => false,
2567 );
2568 }
2569 }
2570
2571 return $response;
2572 }
2573
2574 /**
2575 *
2576 * It is Use Update WDesignKit plugin latest version.
2577 *
2578 * @since 1.0.17
2579 */
2580 protected function wdkit_update_latest_plugin() {
2581
2582 return Wdkit_Depends_Installer::get_instance()->wdkit_update_plugin();
2583 }
2584
2585 /**
2586 *
2587 * It is Use for get plugin list.
2588 *
2589 * @since 1.0.0
2590 */
2591 private function get_plugins() {
2592 if ( ! function_exists( 'get_plugins' ) ) {
2593 require_once \ABSPATH . 'wp-admin/includes/plugin.php';
2594 }
2595
2596 return get_plugins();
2597 }
2598
2599 /**
2600 * Get Download Template Content
2601 *
2602 * @since 1.0.0
2603 */
2604 protected function wdkit_activate_container() {
2605
2606 $option_value = get_option( 'elementor_experiment-container', false );
2607
2608 if ( $option_value === false ) {
2609 add_option( 'elementor_experiment-container', 'active' );
2610 } else {
2611 update_option( 'elementor_experiment-container', 'active' );
2612 }
2613
2614 $result = array(
2615 'message' => esc_html__( 'Container Activated Successfully', 'wdesignkit' ),
2616 'description' => esc_html__( 'Elementor Container Activated Successfully.', 'wdesignkit' ),
2617 'success' => true,
2618 );
2619
2620 wp_send_json( $response );
2621 wp_die();
2622 }
2623
2624 /**
2625 * import category and tags for post
2626 *
2627 * @since 2.0.0
2628 */
2629 protected function wdkit_import_taxonomy() {
2630 $category = isset( $_POST['category'] ) ? json_decode( wp_unslash( $_POST['category'] ) ) : array();
2631 $tags = isset( $_POST['tags'] ) ? json_decode( wp_unslash( $_POST['tags'] ) ) : array();
2632
2633 $response = array(
2634 'success' => false,
2635 'categories' => array(),
2636 'tags' => array(),
2637 );
2638
2639 if ( ! empty( $category ) && count( $category ) > 0 ) {
2640 foreach ( $category as $category_name ) {
2641 $category_name = sanitize_text_field( $category_name );
2642
2643 $term_exists = term_exists( $category_name, 'category' );
2644 if ( ! $term_exists ) {
2645 $result = wp_insert_term( $category_name, 'category' );
2646 if ( ! is_wp_error( $result ) ) {
2647 $response['categories'][] = array(
2648 'name' => $category_name,
2649 'term_id' => $result['term_id'],
2650 );
2651 } else {
2652 $response['categories'][] = array(
2653 'name' => $category_name,
2654 'error' => $result->get_error_message(),
2655 );
2656 }
2657 } else {
2658 $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : $term_exists;
2659 $response['categories'][] = array(
2660 'name' => $category_name,
2661 'term_id' => $term_id,
2662 );
2663 }
2664 }
2665
2666 $response['success'] = true;
2667 }
2668
2669 if ( ! empty( $tags ) && count( $tags ) > 0 ) {
2670 foreach ( $tags as $tags_name ) {
2671 $tags_name = sanitize_text_field( $tags_name );
2672
2673 $term_exists = term_exists( $tags_name, 'post_tag' );
2674 if ( ! $term_exists ) {
2675 $result = wp_insert_term( $tags_name, 'post_tag' );
2676 if ( ! is_wp_error( $result ) ) {
2677 $response['tags'][] = array(
2678 'name' => $tags_name,
2679 'term_id' => $result['term_id'],
2680 );
2681 } else {
2682 $response['tags'][] = array(
2683 'name' => $tags_name,
2684 'error' => $result->get_error_message(),
2685 );
2686 }
2687 } else {
2688 $term_id = is_array( $term_exists ) ? $term_exists['term_id'] : $term_exists;
2689 $response['tags'][] = array(
2690 'name' => $tags_name,
2691 'term_id' => $term_id,
2692 );
2693 }
2694 }
2695
2696 $response['success'] = true;
2697 }
2698
2699 wp_send_json( $response );
2700 wp_die();
2701 }
2702
2703 /**
2704 * Get Download Template Content
2705 *
2706 * @since 1.0.0
2707 */
2708 protected function wdkit_import_template() {
2709 $args = $this->wdkit_parse_args( $_POST );
2710 $api_type = isset( $_POST['api_type'] ) ? sanitize_text_field( wp_unslash( $_POST['api_type'] ) ) : 'import_template';
2711
2712 $response = '';
2713 if ( empty( $args['template_id'] ) ) {
2714 $result = array(
2715 'content' => '',
2716 'message' => esc_html__( 'Invalid import', 'wdesignkit' ),
2717 'description' => esc_html__( 'Invalid import: Check your details and try again.', 'wdesignkit' ),
2718 'success' => false,
2719 );
2720
2721 wp_send_json( $response );
2722 wp_die();
2723 }
2724
2725 $args['token'] = $this->wdkit_login_user_token( $args['email'] );
2726
2727 unset( $args['email'] );
2728 $args['unique_id'] = get_option( 'wdkit_unique_id' ) ?? '';
2729 $response = WDesignKit_Data_Query::get_data( $api_type, $args );
2730
2731 if ( is_wp_error( $response ) ) {
2732 wp_send_json( array(
2733 'success' => false,
2734 'message' => $response->get_error_message(),
2735 ) );
2736 wp_die();
2737 }
2738
2739 $custom_meta = isset( $_POST['custom_meta'] ) ? sanitize_text_field( wp_unslash( $_POST['custom_meta'] ) ) : false;
2740
2741 /** Custom meta Field */
2742 if ( ! empty( $custom_meta ) && 'true' === $custom_meta && ! empty( $response ) && ! empty( $response['content'] ) ) {
2743
2744 $res_content = json_decode( $response['content'], true );
2745 if ( isset( $res_content['custom_meta'] ) && ! empty( $res_content['custom_meta'] ) ) {
2746 $meta_data = $res_content['custom_meta'];
2747
2748 if ( ! empty( $meta_data ) ) {
2749 foreach ( $meta_data as $meta_key => $meta_val ) {
2750 if ( ! empty( $meta_val[0] ) && is_serialized( $meta_val[0] ) ) {
2751 $meta_val[0] = maybe_unserialize( $meta_val[0] );
2752 }
2753
2754 if ( get_post_meta( get_the_ID(), $meta_key, true ) === '' ) {
2755 add_post_meta( get_the_ID(), $meta_key, $meta_val[0] );
2756 } else {
2757 update_post_meta( get_the_ID(), $meta_key, $meta_val[0] );
2758 }
2759 }
2760 }
2761 }
2762 }
2763
2764 wp_send_json( $response );
2765 wp_die();
2766 }
2767
2768 /**
2769 * This Function is Use For Media Import
2770 *
2771 * @since 1.0.0
2772 *
2773 * @param array $content store media content.
2774 * @param string $editor it is check editor.
2775 */
2776 /**
2777 * Resolve a local upload URL back to its attachment ID.
2778 *
2779 * Handles the "-scaled" copy WordPress makes for large originals and any
2780 * "-1920x1280" size suffix, both of which attachment_url_to_postid() misses because
2781 * they are not the value stored in _wp_attached_file.
2782 *
2783 * @since 2.6.2
2784 *
2785 * @param string $url Local upload URL.
2786 * @return int Attachment ID, or 0.
2787 */
2788 private static function wdkit_attachment_id_from_url( $url ) {
2789 static $cache = array();
2790
2791 if ( isset( $cache[ $url ] ) ) {
2792 return $cache[ $url ];
2793 }
2794
2795 $id = (int) attachment_url_to_postid( $url );
2796
2797 if ( ! $id ) {
2798 // Try the original file behind a -scaled or -WxH derivative.
2799 $stripped = preg_replace( '/-scaled(\.[a-z0-9]+)$/i', '$1', $url );
2800 $stripped = preg_replace( '/-\d+x\d+(\.[a-z0-9]+)$/i', '$1', (string) $stripped );
2801
2802 if ( $stripped && $stripped !== $url ) {
2803 $id = (int) attachment_url_to_postid( $stripped );
2804 }
2805 }
2806
2807 // Only remember hits. Page imports run concurrently, so an attachment created by a
2808 // sibling request may not exist yet when this is first asked — caching that miss
2809 // would keep every later control in this request pointing at nothing.
2810 if ( $id ) {
2811 $cache[ $url ] = $id;
2812 }
2813
2814 return $id;
2815 }
2816
2817 /**
2818 * Is this media reference still pointing off-site?
2819 *
2820 * Template content arrives holding the URLs of wherever the media lived before. Those
2821 * carry that site's attachment IDs, which have no meaning here - and can collide with
2822 * unrelated local posts.
2823 *
2824 * @since 2.6.2
2825 *
2826 * @param string $url URL from a media control.
2827 * @return bool True when the URL points at another site's uploads.
2828 */
2829 private static function wdkit_is_foreign_media_url( $url ) {
2830
2831 if ( ! class_exists( 'Wdkit_Image_Guard' ) ) {
2832 require_once WDKIT_INCLUDES . 'admin/class-wdkit-image-guard.php';
2833 }
2834
2835 $uploads = wp_get_upload_dir();
2836
2837 return Wdkit_Image_Guard::is_foreign_media( $url, isset( $uploads['baseurl'] ) ? $uploads['baseurl'] : '' );
2838 }
2839
2840 /**
2841 * Find - or make - the local attachment behind a source-site media URL.
2842 *
2843 * Elementor stamps every image it imports with `_elementor_source_image_hash`
2844 * (sha1 of the URL it came from), and its importer consults that before doing any
2845 * network work. Delegating here means a URL already imported at create time resolves
2846 * from the database, and one that never made it is fetched exactly once.
2847 *
2848 * Only ever called for foreign URLs. Handing it a local URL would re-download the
2849 * file and leave a duplicate, because the stored hash is of the *remote* URL and so
2850 * would never match.
2851 *
2852 * @since 2.6.2
2853 *
2854 * @param string $url Source-site media URL.
2855 * @param int $source_id The source site's attachment ID, used as Elementor's cache key.
2856 * @return array Local `id` and `url`, or an empty array when it cannot be resolved.
2857 */
2858 private static function wdkit_localise_media_url( $url, $source_id = 0 ) {
2859 static $cache = array();
2860
2861 if ( isset( $cache[ $url ] ) ) {
2862 return $cache[ $url ];
2863 }
2864
2865 if ( ! did_action( 'elementor/loaded' ) || ! class_exists( '\\Elementor\\Plugin' ) ) {
2866 return array();
2867 }
2868
2869 $images = \Elementor\Plugin::$instance->templates_manager->get_import_images_instance();
2870
2871 if ( ! $images ) {
2872 return array();
2873 }
2874
2875 // A download may happen, so keep the oversized-image guard in force.
2876 self::wdkit_guard_oversized_images();
2877
2878 $imported = $images->import(
2879 array(
2880 // Elementor only checks its hash table when an id is present.
2881 'id' => $source_id ? $source_id : 1,
2882 'url' => $url,
2883 )
2884 );
2885
2886 $local = ( ! empty( $imported['id'] ) && ! empty( $imported['url'] ) )
2887 ? array(
2888 'id' => (int) $imported['id'],
2889 'url' => $imported['url'],
2890 )
2891 : array();
2892
2893 // Remember hits only: a sibling request importing concurrently may simply not have
2894 // finished yet, and caching that miss would strand every later control on this page.
2895 if ( $local ) {
2896 $cache[ $url ] = $local;
2897 }
2898
2899 return $local;
2900 }
2901
2902 /**
2903 * Repair dangling attachment IDs across every page of a finished import.
2904 *
2905 * The create-time repair in wdkit_media_import() can only see attachments that already
2906 * exist. Pages import concurrently and share images — an icon first imported by one
2907 * page is referenced by several others — so a page that runs early legitimately cannot
2908 * resolve an image a sibling request has not created yet.
2909 *
2910 * This runs at the finalize step, once every page and attachment exists, and fixes
2911 * whatever the per-page pass had to leave behind.
2912 *
2913 * @since 2.6.2
2914 *
2915 * @param array $page_ids Imported post IDs.
2916 * @return int Number of pages actually rewritten.
2917 */
2918 private function wdkit_sweep_attachment_ids( $page_ids ) {
2919
2920 if ( empty( $page_ids ) || ! did_action( 'elementor/loaded' ) ) {
2921 return 0;
2922 }
2923
2924 $fixed = 0;
2925
2926 foreach ( array_unique( array_map( 'intval', $page_ids ) ) as $post_id ) {
2927
2928 if ( ! $post_id ) {
2929 continue;
2930 }
2931
2932 $raw = get_post_meta( $post_id, '_elementor_data', true );
2933
2934 if ( empty( $raw ) ) {
2935 continue;
2936 }
2937
2938 $data = is_array( $raw ) ? $raw : json_decode( $raw, true );
2939
2940 if ( ! is_array( $data ) ) {
2941 continue;
2942 }
2943
2944 $repaired = self::wdkit_repair_attachment_ids( $data );
2945
2946 if ( wp_json_encode( $repaired ) === wp_json_encode( $data ) ) {
2947 continue;
2948 }
2949
2950 // Save through the document API so Elementor regenerates the page CSS — the
2951 // background-image rules are only emitted once the IDs resolve.
2952 $document = \Elementor\Plugin::$instance->documents->get( $post_id );
2953
2954 // Count only a save that actually happened. Document::save() returns false
2955 // without saving when the current user cannot edit the post, and reporting
2956 // those as repaired hides the fact that nothing changed.
2957 if ( $document && $document->save( array( 'elements' => $repaired ) ) ) {
2958 ++$fixed;
2959 }
2960 }
2961
2962 if ( $fixed ) {
2963 \Elementor\Plugin::$instance->files_manager->clear_cache();
2964 }
2965
2966 return $fixed;
2967 }
2968
2969 /**
2970 * Repair media controls whose attachment ID does not resolve.
2971 *
2972 * Elementor media controls store `{ url, id }`. Controls flagged `has_sizes` — the
2973 * container/section **background image** among them — do not render from `url` at all:
2974 * CSS generation resolves the image through the attachment ID, so a dangling ID
2975 * produces no `background-image` rule and the section renders with no image even
2976 * though its URL is perfectly correct.
2977 *
2978 * IDs arrive dangling whenever Elementor's own importer does not rewrite a control —
2979 * it carries the source site's ID, which means nothing locally. Now that the URL is
2980 * already a local upload before import, the ID can simply be looked up from it.
2981 *
2982 * @since 2.6.2
2983 *
2984 * @param mixed $node Elementor data, walked recursively.
2985 * @return mixed Data with resolvable attachment IDs.
2986 */
2987 private static function wdkit_repair_attachment_ids( $node ) {
2988
2989 if ( ! is_array( $node ) ) {
2990 return $node;
2991 }
2992
2993 // A media control value: has a url, and an id slot to correct.
2994 if ( isset( $node['url'] ) && is_string( $node['url'] ) && array_key_exists( 'id', $node ) ) {
2995
2996 $current = (int) $node['id'];
2997 $is_live = $current && 'attachment' === get_post_type( $current );
2998
2999 if ( self::wdkit_is_foreign_media_url( $node['url'] ) ) {
3000 // Still pointing at the source site. Ask Elementor for the local copy: its
3001 // _elementor_source_image_hash lookup returns the attachment the create-time
3002 // import already made, so this normally costs a single query and no download.
3003 $local = self::wdkit_localise_media_url( $node['url'], $current );
3004
3005 if ( ! empty( $local['id'] ) && ! empty( $local['url'] ) ) {
3006 $node['id'] = $local['id'];
3007 $node['url'] = $local['url'];
3008 }
3009 } elseif ( ! $is_live && false !== strpos( $node['url'], '/wp-content/uploads/' ) ) {
3010 $resolved = self::wdkit_attachment_id_from_url( $node['url'] );
3011
3012 if ( $resolved ) {
3013 $node['id'] = $resolved;
3014 }
3015 }
3016 }
3017
3018 foreach ( $node as $key => $value ) {
3019 if ( is_array( $value ) ) {
3020 $node[ $key ] = self::wdkit_repair_attachment_ids( $value );
3021 }
3022 }
3023
3024 return $node;
3025 }
3026
3027 public function wdkit_media_import( $content = array(), $editor = '' ) {
3028
3029 if ( empty( $content ) && empty( $editor ) ) {
3030 $args = $this->wdkit_parse_args( $_POST );
3031 $content = ! empty( $args['content'] ) ? json_decode( $args['content'], true ) : array();
3032 } else {
3033 $args = array(
3034 'content' => $content,
3035 'editor' => $editor,
3036 );
3037 $content = ! empty( $args['content'] ) ? $args['content'] : array();
3038
3039 if ( 'elementor' === $args['editor'] ) {
3040 $content = json_decode( $content, true );
3041 }
3042 }
3043
3044 if ( ! class_exists( 'Wdkit_Import_Images' ) ) {
3045 require_once WDKIT_INCLUDES . 'admin/class-wdkit-import-images.php';
3046 }
3047
3048
3049 if ( ! empty( $args['editor'] ) && 'gutenberg' === $args['editor'] && ! empty( $content ) ) {
3050 $media_import = array( $content );
3051 $media_import = self::blocks_import_media_copy_content( $media_import );
3052 $content = $media_import[0];
3053 } elseif ( ! empty( $args['editor'] ) && 'elementor' === $args['editor'] && ! empty( $content ) ) {
3054 $media_import = array( $content );
3055 $media_import = self::widgets_elements_id_change( $media_import );
3056 $media_import = self::widgets_import_media_copy_content( $media_import );
3057 $content = $media_import[0];
3058
3059 // Last: point any control Elementor left holding a foreign attachment ID at the
3060 // local attachment its URL already refers to. Without this, has_sizes controls
3061 // such as container background images resolve to nothing and render empty.
3062 $content = self::wdkit_repair_attachment_ids( $content );
3063 }
3064
3065 return $content;
3066 }
3067
3068 /**
3069 * Widgets elements data
3070 *
3071 * @since 1.0.0
3072 * @param string $media_import it is store media data.
3073 */
3074 protected static function widgets_elements_id_change( $media_import ) {
3075 if ( did_action( 'elementor/loaded' ) ) {
3076 return \Elementor\Plugin::instance()->db->iterate_data(
3077 $media_import,
3078 function ( $element ) {
3079 $element['id'] = \Elementor\Utils::generate_random_string();
3080 return $element;
3081 }
3082 );
3083 } else {
3084 return $media_import;
3085 }
3086 }
3087
3088 /**
3089 * Widgets Media import copy content.
3090 *
3091 * @since 1.0.0
3092 *
3093 * @param string $media_import it is store media data.
3094 */
3095 protected static function widgets_import_media_copy_content( $media_import ) {
3096 if ( did_action( 'elementor/loaded' ) ) {
3097
3098 return \Elementor\Plugin::instance()->db->iterate_data(
3099 $media_import,
3100 function ( $element_data ) {
3101 $elements = \Elementor\Plugin::instance()->elements_manager->create_element_instance( $element_data );
3102
3103 if ( ! $elements ) {
3104 return null;
3105 }
3106
3107 return self::widgets_element_import_start( $elements );
3108 }
3109 );
3110 } else {
3111 return $media_import;
3112 }
3113 }
3114
3115 /**
3116 * Start element copy content for media import.
3117 *
3118 * @since 1.0.0
3119 *
3120 * @param string \Elementor\Controls_Stack $element it is store elementor data.
3121 */
3122 protected static function widgets_element_import_start( \Elementor\Controls_Stack $element ) {
3123 $get_element_instance = $element->get_data();
3124 $tp_mi_on_fun = 'on_import';
3125
3126 if ( method_exists( $element, $tp_mi_on_fun ) ) {
3127 $get_element_instance = $element->{$tp_mi_on_fun}( $get_element_instance );
3128 }
3129
3130 foreach ( $element->get_controls() as $get_control ) {
3131 $control_type = \Elementor\Plugin::instance()->controls_manager->get_control( $get_control['type'] );
3132 $control_name = $get_control['name'];
3133
3134 if ( ! $control_type ) {
3135 // Skip just this control. Returning here would abandon every control after
3136 // it, so a single unregistered type - routine when a kit uses an addon that
3137 // is not fully active yet - would silently leave the rest of the element's
3138 // media pointing at the source site.
3139 continue;
3140 }
3141
3142 if ( method_exists( $control_type, $tp_mi_on_fun ) ) {
3143 $get_element_instance['settings'][ $control_name ] = $control_type->{$tp_mi_on_fun}( $element->get_settings( $control_name ), $get_control );
3144 }
3145 }
3146
3147 return $get_element_instance;
3148 }
3149
3150 /**
3151 * Blocks Recursively data
3152 *
3153 * @param string $data_import gutenber data import.
3154 */
3155 public static function blocks_import_media_copy_content( $data_import ) {
3156 if ( ! empty( $data_import ) ) {
3157 foreach ( $data_import[0] as $key => $val ) {
3158 if ( array_key_exists( 'blockName', $val ) && ( empty( $val['blockName'] ) || null === $val['blockName'] || empty( $val['blockName'] ) || ' ' === $val['blockName'] ) ) {
3159 unset( $data_import[0][ $key ] );
3160 }
3161 }
3162 }
3163
3164 return self::blocks_array_recursively_data(
3165 $data_import,
3166 function ( $block_data ) {
3167 $elements = self::blocks_data_instance( $block_data );
3168 return $elements;
3169 }
3170 );
3171 }
3172
3173 /**
3174 * Blocks Recursively data
3175 *
3176 * @param array $data store data.
3177 * @param string $callback store data.
3178 * @param string $args store data.
3179 */
3180 public static function blocks_array_recursively_data( $data, $callback, $args = array() ) {
3181 if ( ( isset( $data['name'] ) && ! empty( $data['name'] ) ) || ( isset( $data['blockName'] ) && ! empty( $data['blockName'] ) ) ) {
3182 if ( ! empty( $data['innerBlocks'] ) ) {
3183 $data['innerBlocks'] = self::blocks_array_recursively_data( $data['innerBlocks'], $callback, $args );
3184 }
3185
3186 return call_user_func( $callback, $data, $args );
3187 }
3188
3189 if ( ! empty( $data ) ) {
3190 $data = (array) $data;
3191 foreach ( $data as $block_key => $block_value ) {
3192 $block_data = self::blocks_array_recursively_data( $data[ $block_key ], $callback, $args );
3193
3194 if ( null === $block_data ) {
3195 continue;
3196 }
3197
3198 $data[ $block_key ] = $block_data;
3199 }
3200 }
3201
3202 return $data;
3203 }
3204
3205 /**
3206 * Check Blocks data media Url
3207 *
3208 * @param array $block_data store data.
3209 * @param array $args store data.
3210 * @param array $block_args store data.
3211 */
3212 public static function blocks_data_instance( array $block_data, array $args = array(), $block_args = null ) {
3213
3214 if ( ( isset( $block_data['name'] ) && isset( $block_data['clientId'] ) && isset( $block_data['attributes'] ) ) || ( isset( $block_data['blockName'] ) && isset( $block_data['attrs'] ) && ! empty( $block_data['attrs'] ) ) ) {
3215 $blocks_attr = isset( $block_data['attributes'] ) ? $block_data['attributes'] : ( isset( $block_data['attrs'] ) ? $block_data['attrs'] : array() );
3216 $blocks_attr = self::wdkit_import_block_media( $blocks_attr );
3217 if ( isset( $block_data['attributes'] ) ) {
3218 $block_data['attributes'] = $blocks_attr;
3219 } elseif ( isset( $block_data['attrs'] ) ) {
3220 $block_data['attrs'] = $blocks_attr;
3221 }
3222
3223 $block_data = self::wdkit_relink_block_markup( $block_data );
3224 }
3225
3226 return $block_data;
3227 }
3228
3229 /**
3230 * Run block markup through the media import, the way the create path does.
3231 *
3232 * Used wherever block content is written from the browser: media import, then the Nexter
3233 * block processor so each block's rendered copy matches its attributes, then serialise.
3234 *
3235 * @since 2.6.2
3236 *
3237 * @param string $content Block markup.
3238 * @return string Block markup with local media.
3239 */
3240 private function wdkit_relink_gutenberg_content( $content ) {
3241
3242 if ( ! is_string( $content ) || false === strpos( $content, '<!-- wp:' ) ) {
3243 return $content;
3244 }
3245
3246 // wdkit_media_import() loads this itself, but it is referenced before that below.
3247 if ( ! class_exists( 'Wdkit_Import_Images' ) ) {
3248 require_once WDKIT_INCLUDES . 'admin/class-wdkit-import-images.php';
3249 }
3250
3251 // Thumbnail generation decodes each image, so keep the oversized-image guard in force.
3252 self::wdkit_guard_oversized_images();
3253
3254
3255 // Block attributes are JSON inside the block delimiters, so they only survive a parse
3256 // when the string carries exactly one level of escaping. Arrive with an extra level and
3257 // parse_blocks() reads no attributes at all - serialising that back out writes every
3258 // block bare, throwing away titles, body text, icons and styling.
3259 $parsable = self::wdkit_parsable_block_content( $content );
3260
3261 if ( null === $parsable ) {
3262
3263 return $content;
3264 }
3265
3266 $blocks = parse_blocks( $parsable );
3267 $blocks = $this->wdkit_media_import( $blocks, 'gutenberg' );
3268
3269 if ( empty( $blocks ) || ! is_array( $blocks ) ) {
3270 return $content;
3271 }
3272
3273 if ( class_exists( 'WDKIT_Nexter_Block_Processor' ) ) {
3274 $processor = new WDKIT_Nexter_Block_Processor();
3275 $blocks = $processor->run( $blocks );
3276 }
3277
3278 $serialised = serialize_blocks( $blocks );
3279
3280 // Last line of defence. This function exists to repoint media, so a result carrying
3281 // fewer block attributes than it started with is a broken round trip, not a rewrite.
3282 // Leaving the media wrong is recoverable; saving gutted content is not.
3283 $before = self::wdkit_block_attr_count( $parsable );
3284 $after = self::wdkit_block_attr_count( $serialised );
3285
3286 if ( $after < $before ) {
3287
3288 return $content;
3289 }
3290
3291 // Never hand back nothing: an empty result would blank the page.
3292 return ! empty( $serialised ) ? $serialised : $content;
3293 }
3294
3295 /**
3296 * Rebuild the block stylesheet for a page whose content we just rewrote.
3297 *
3298 * The addon keeps each block's styling in a generated per-page stylesheet, and every rule
3299 * is keyed to the block id it was written for. That file is produced when the page is
3300 * saved through the editor - not by wp_update_post() from an AJAX handler - so rewriting
3301 * content here leaves the page pointing at a stylesheet built for the previous markup.
3302 * Blocks whose ids are not in that file get no rules at all and render unstyled.
3303 *
3304 * @since 2.6.2
3305 *
3306 * @param int $post_id Page whose content changed.
3307 * @return bool True when a rebuild was triggered.
3308 */
3309 private static function wdkit_rebuild_block_css( $post_id ) {
3310
3311 if ( ! $post_id ) {
3312 return false;
3313 }
3314
3315 foreach ( get_declared_classes() as $class ) {
3316 if ( ! method_exists( $class, 'make_block_css_by_post_id' ) ) {
3317 continue;
3318 }
3319
3320 try {
3321 if ( method_exists( $class, 'instance' ) ) {
3322 $instance = $class::instance();
3323 } elseif ( method_exists( $class, 'get_instance' ) ) {
3324 $instance = $class::get_instance();
3325 } else {
3326 $instance = new $class();
3327 }
3328
3329 $instance->make_block_css_by_post_id( $post_id );
3330
3331
3332 return true;
3333 } catch ( \Throwable $e ) {
3334 // Styling is best-effort: a failure here must not fail the import.
3335
3336 return false;
3337 }
3338 }
3339
3340 return false;
3341 }
3342
3343 /**
3344 * How many block attributes does this markup actually yield when parsed?
3345 *
3346 * Used as a before/after measure: block attributes are the part of block markup a round
3347 * trip can silently drop, so counting them is how we tell a rewrite from a mangling.
3348 *
3349 * @since 2.6.2
3350 *
3351 * @param string $content Block markup.
3352 * @return int Total attributes across every block.
3353 */
3354 private static function wdkit_block_attr_count( $content ) {
3355 $total = 0;
3356
3357 $walk = function ( $blocks ) use ( &$walk, &$total ) {
3358 foreach ( $blocks as $block ) {
3359 if ( ! empty( $block['attrs'] ) && is_array( $block['attrs'] ) ) {
3360 $total += count( $block['attrs'] );
3361 }
3362
3363 if ( ! empty( $block['innerBlocks'] ) ) {
3364 $walk( $block['innerBlocks'] );
3365 }
3366 }
3367 };
3368
3369 $walk( parse_blocks( (string) $content ) );
3370
3371 return $total;
3372 }
3373
3374 /**
3375 * Return this content in a form whose block attributes actually parse.
3376 *
3377 * Content written straight to post_content never had to parse, so an extra level of
3378 * escaping on the way in did no harm. Parsing it - which repointing media requires - makes
3379 * that escaping fatal: `{\"Title\":\"…\"}` is not JSON, so every attribute is discarded.
3380 *
3381 * Rather than assume a slash depth, this measures: if stripping one level yields more
3382 * attributes, the content was over-escaped and the stripped form is the real one.
3383 *
3384 * @since 2.6.2
3385 *
3386 * @param string $content Block markup as received.
3387 * @return string|null Markup safe to parse, or null when no form of it parses.
3388 */
3389 private static function wdkit_parsable_block_content( $content ) {
3390
3391 $as_is = self::wdkit_block_attr_count( $content );
3392
3393 // Nothing claims to carry attributes, so there is nothing to lose either.
3394 if ( false === strpos( $content, '{' ) ) {
3395 return $content;
3396 }
3397
3398 $stripped = wp_unslash( $content );
3399 $stripped_attrs = self::wdkit_block_attr_count( $stripped );
3400
3401 if ( $stripped_attrs > $as_is ) {
3402 return $stripped;
3403 }
3404
3405 if ( $as_is > 0 ) {
3406 return $content;
3407 }
3408
3409 // Neither form parses into attributes even though the markup contains JSON: better to
3410 // leave the content exactly as it arrived than to rewrite it into something bare.
3411 return null;
3412 }
3413
3414 /**
3415 * Point a block's saved markup at the media that was just localised.
3416 *
3417 * A block stores a rendered copy of itself in `innerHTML` / `innerContent`, and for many
3418 * blocks that copy is what the front end actually outputs. Importing the attributes alone
3419 * therefore fixes the editor while leaving the page still loading from the site the
3420 * template came from - and those hosts answer 403, so the image renders broken.
3421 *
3422 * @since 2.6.2
3423 *
3424 * @param array $block_data One parsed block.
3425 * @return array The block with its markup repointed.
3426 */
3427 private static function wdkit_relink_block_markup( $block_data ) {
3428
3429 $map = Wdkit_Import_Images::get_url_map();
3430
3431 if ( empty( $map ) ) {
3432 return $block_data;
3433 }
3434
3435 $from = array_keys( $map );
3436 $to = array_values( $map );
3437
3438 if ( ! empty( $block_data['innerHTML'] ) && is_string( $block_data['innerHTML'] ) ) {
3439 $block_data['innerHTML'] = str_replace( $from, $to, $block_data['innerHTML'] );
3440 }
3441
3442 if ( ! empty( $block_data['innerContent'] ) && is_array( $block_data['innerContent'] ) ) {
3443 foreach ( $block_data['innerContent'] as $index => $chunk ) {
3444 if ( is_string( $chunk ) ) {
3445 $block_data['innerContent'][ $index ] = str_replace( $from, $to, $chunk );
3446 }
3447 }
3448 }
3449
3450 return $block_data;
3451 }
3452
3453 /**
3454 * Import every media reference held in a block's attributes.
3455 *
3456 * Block attributes nest arbitrarily - a repeater of cards each with an image, responsive
3457 * variants, nested inner settings - so this recurses rather than reaching a fixed number
3458 * of levels down. The previous version was unrolled exactly four levels deep and also
3459 * skipped any subtree carrying an `md` key, which meant anything below that simply kept
3460 * the source site's URL and attachment ID and rendered as an empty placeholder.
3461 *
3462 * A node counts as media when it has a non-empty string `url` and either an id slot or a
3463 * URL that names an image file. That pairing is what distinguishes a media control from
3464 * a link, which also carries a `url`.
3465 *
3466 * @since 2.6.2
3467 *
3468 * @param mixed $node Block attributes, walked recursively.
3469 * @return mixed Attributes with local media.
3470 */
3471 private static function wdkit_import_block_media( $node ) {
3472
3473 if ( ! is_array( $node ) ) {
3474 return $node;
3475 }
3476
3477 $url = isset( $node['url'] ) && is_string( $node['url'] ) ? $node['url'] : '';
3478
3479 if ( '' !== $url
3480 && ( array_key_exists( 'id', $node ) || array_key_exists( 'Id', $node )
3481 || preg_match( '/\.(?:jpe?g|png|gif|svg|webp|avif|bmp)$/i', (string) wp_parse_url( $url, PHP_URL_PATH ) ) )
3482 ) {
3483 $imported = Wdkit_Import_Images::wdkit_Import_media( $node );
3484
3485 // Only accept a real result. The importer returns the node untouched when it
3486 // cannot localise the file, and anything falsy here would wipe out the URL and
3487 // leave the block with no image at all.
3488 if ( ! empty( $imported['url'] ) ) {
3489 $node = array_merge( $node, $imported );
3490 }
3491 }
3492
3493 // Keep walking even after importing this node. A media value carries its own `sizes`
3494 // map of per-size URLs, and returning here left every one of those pointing at the
3495 // site the template came from - which is what the widgets actually render from.
3496 foreach ( $node as $key => $value ) {
3497 if ( is_array( $value ) ) {
3498 $node[ $key ] = self::wdkit_import_block_media( $value );
3499 }
3500 }
3501
3502 return $node;
3503 }
3504
3505 /**
3506 * Kit Template Import Pages/Sections
3507 *
3508 * @since 1.0.0
3509 * */
3510 protected function wdkit_import_kit_template() {
3511
3512 if ( ! current_user_can( 'manage_options' ) ) {
3513 return false;
3514 }
3515
3516 $builder = isset( $_POST['builder'] ) ? sanitize_text_field( wp_unslash( $_POST['builder'] ) ) : '';
3517
3518 $page_section = ! empty( $_POST['page_section'] ) ? sanitize_text_field( wp_unslash( $_POST['page_section'] ) ) : '';
3519
3520 if ( isset( $page_section ) ) {
3521 $args['page_section'] = ! empty( $page_section ) ? sanitize_text_field( wp_unslash( $page_section ) ) : '';
3522 }
3523
3524 $template_ids = ! empty( $_POST['template_ids'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['template_ids'] ) ), true ) : array();
3525 $email = ! empty( $_POST['email'] ) ? strtolower( sanitize_email( wp_unslash( $_POST['email'] ) ) ) : '';
3526 $editor = isset( $_POST['editor'] ) ? sanitize_text_field( wp_unslash( $_POST['editor'] ) ) : '';
3527 $website_kit = isset( $_POST['website_kit'] ) ? sanitize_text_field( wp_unslash( $_POST['website_kit'] ) ) : '';
3528 $api_type = isset( $_POST['api_type'] ) ? sanitize_text_field( wp_unslash( $_POST['api_type'] ) ) : 'import_template';
3529 $ai_compitible = isset( $_POST['ai_compitible'] ) ? sanitize_text_field( wp_unslash( $_POST['ai_compitible'] ) ) : false;
3530
3531 if ( empty( $template_ids ) ) {
3532 $output = array(
3533 'message' => esc_html__( 'Invalid import', 'wdesignkit' ),
3534 'description' => esc_html__( 'Invalid import: Check your details and try again.', 'wdesignkit' ),
3535 'success' => false,
3536 );
3537
3538 wp_send_json( $output );
3539 wp_die();
3540 }
3541
3542 /**Not Usefull*/
3543 if ( isset( $_POST['select'] ) ) {
3544 $args['post_type'] = ! empty( $_POST['select'] ) ? sanitize_text_field( wp_unslash( $_POST['select'] ) ) : '';
3545 }
3546
3547 $args['custom_meta'] = isset( $_POST['custom_meta'] ) ? sanitize_text_field( wp_unslash( $_POST['custom_meta'] ) ) : false;
3548 $args['editor'] = $editor;
3549
3550 $token = $this->wdkit_login_user_token( $email );
3551
3552 $temp_args = array(
3553 'token' => $token,
3554 'template_id' => $template_ids['id'],
3555 'editor' => $editor,
3556 'website_kit' => $website_kit,
3557 'unique_id' => get_option( 'wdkit_unique_id' ) ?? '',
3558 );
3559
3560 $response = WDesignKit_Data_Query::get_data( $api_type, $temp_args );
3561 $output = array();
3562
3563 if ( is_wp_error( $response ) ) {
3564
3565 wp_send_json( $response );
3566 wp_die();
3567 }
3568
3569 if ( isset( $response['content'] ) && 'error' === $response['content'] ) {
3570 wp_send_json( $response );
3571 wp_die();
3572 }
3573
3574 $result = array(
3575 'response' => $response,
3576 'args' => $args,
3577 'id' => $template_ids['id'],
3578 'temp_data' => $template_ids,
3579 );
3580
3581 $output['message'] = $response['message'];
3582 $output['description'] = $response['description'];
3583 $output['data'] = $result;
3584 $output['success'] = $response['success'];
3585
3586 wp_send_json( $output );
3587 wp_die();
3588 }
3589
3590 public function wdkit_enable_template_widgets() {
3591 $widget_list = ! empty( $_POST['widget_list'] ) ? json_decode( wp_unslash( $_POST['widget_list'] ), true ) : array();
3592 $extensions_list = ! empty( $_POST['extensions_list'] ) ? json_decode( wp_unslash( $_POST['extensions_list'] ), true ) : array();
3593
3594 if ( empty( $widget_list ) && empty( $extensions_list ) ) {
3595 $res = array(
3596 'massage' => __( 'Widget array not found', 'wdesignkit' ),
3597 'description' => __( 'Widget array not found', 'wdesignkit' ),
3598 'success' => false,
3599 );
3600 wp_send_json( $res );
3601 wp_die();
3602 }
3603
3604 if ( ! has_filter( 'tpae_enable_selected_widgets' ) ) {
3605 $res = array(
3606 'massage' => __( 'Relevant Plugin not Activated', 'wdesignkit' ),
3607 'description' => __( 'Relevant Plugin not Installed / Activated', 'wdesignkit' ),
3608 'success' => false,
3609 );
3610 wp_send_json( $res );
3611 wp_die();
3612 }
3613
3614 $w_list = array(
3615 'widgets' => $widget_list,
3616 'extensions' => $extensions_list,
3617 );
3618
3619 $result = apply_filters( 'tpae_enable_selected_widgets', $w_list );
3620
3621 if ( ! empty( $result['success'] ) ) {
3622 $res = array(
3623 'massage' => __( 'Enabled widgets successfully', 'wdesignkit' ),
3624 'description' => __( 'Used widgets have been enabled successfully', 'wdesignkit' ),
3625 'success' => true,
3626 );
3627 } else {
3628
3629 $message = isset( $result['message'] ) ? $result['message'] : __( 'Failed to enable widgets', 'wdesignkit' );
3630 $description = isset( $result['description'] ) ? $result['description'] : __( 'Failed to enable widgets', 'wdesignkit' );
3631
3632 $res = array(
3633 'massage' => $message,
3634 'description' => $description,
3635 'success' => false,
3636 );
3637 }
3638
3639 wp_send_json( $res );
3640 wp_die();
3641 }
3642
3643 /**
3644 * Import single template and section from plugin only
3645 * */
3646 protected function wdkit_import_multi_template() {
3647 $args = $this->wdkit_parse_args( $_POST );
3648 $api_type = isset( $_POST['api_type'] ) ? sanitize_text_field( wp_unslash( $_POST['api_type'] ) ) : 'import_template';
3649
3650 if ( ! current_user_can( 'manage_options' ) ) {
3651 return false;
3652 }
3653
3654 if ( empty( $_POST['template_ids'] ) ) {
3655 $output = array(
3656 'data' => array(),
3657 'message' => esc_html__( 'Invalid import', 'wdesignkit' ),
3658 'description' => esc_html__( 'Invalid import: Check your details and try again.', 'wdesignkit' ),
3659 'success' => false,
3660 );
3661
3662 wp_send_json( $output );
3663 wp_die();
3664 }
3665
3666 if ( isset( $_POST['template_ids'] ) ) {
3667 $args['template_ids'] = ! empty( $_POST['template_ids'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['template_ids'] ) ), true ) : array();
3668 }
3669
3670 if ( isset( $_POST['page_section'] ) ) {
3671 $args['page_section'] = ! empty( $_POST['page_section'] ) ? sanitize_text_field( wp_unslash( $_POST['page_section'] ) ) : '';
3672 }
3673
3674 if ( isset( $_POST['select'] ) ) {
3675 $args['post_type'] = ! empty( $_POST['select'] ) ? sanitize_text_field( wp_unslash( $_POST['select'] ) ) : '';
3676 }
3677
3678 $args['custom_meta'] = isset( $_POST['custom_meta'] ) ? sanitize_text_field( wp_unslash( $_POST['custom_meta'] ) ) : false;
3679
3680 if ( ! empty( $args['template_ids'] ) && ! empty( $args['page_section'] ) ) {
3681 $output = array();
3682 if ( ! empty( $args['template_ids']['id'] ) ) {
3683 $token = $this->wdkit_login_user_token( $args['email'] );
3684
3685 $temp_args = array(
3686 'token' => $token,
3687 'template_id' => $args['template_ids']['id'],
3688 'editor' => $args['editor'],
3689 'unique_id' => get_option( 'wdkit_unique_id' ) ?? '',
3690 );
3691
3692 $response = WDesignKit_Data_Query::get_data( $api_type, $temp_args );
3693
3694 if ( is_wp_error( $response ) ) {
3695 wp_send_json( array(
3696 'success' => false,
3697 'message' => $response->get_error_message(),
3698 ) );
3699 wp_die();
3700 }
3701
3702 if ( isset( $response['content'] ) && 'error' === $response['content'] ) {
3703 wp_send_json( $response );
3704 wp_die();
3705 }
3706
3707 $result = array(
3708 'response' => $response,
3709 'args' => $args,
3710 'id' => $args['template_ids'],
3711 'value' => $args['template_ids'],
3712 );
3713
3714 $output['message'] = $response['message'];
3715 $output['description'] = $response['description'];
3716 $output['data'] = $result;
3717 $output['success'] = true;
3718
3719 }
3720
3721 wp_send_json( $output );
3722 wp_die();
3723 }
3724 }
3725
3726 /**
3727 * It is Use for remove selected category from content.
3728 *
3729 * @since 2.0.5
3730 */
3731 public function wdkit_content_remover( &$data ) {
3732
3733 if ( is_array( $data ) ) {
3734
3735 foreach ( $data as $key => &$value ) {
3736 if ( $key === 'post_category' ) {
3737 $data[ $key ] = array();
3738 } else if ($key === 'include_products'){
3739 $data[ $key ] = "";
3740 } else {
3741 $this->wdkit_content_remover( $value );
3742 }
3743 }
3744 } elseif ( is_object( $data ) ) {
3745
3746 foreach ( $data as $key => &$value ) {
3747 if ( $key === 'post_category' ) {
3748 $data->$key = array();
3749 } else if ($key === 'include_products'){
3750 $data->$key = "";
3751 } else {
3752 $this->wdkit_content_remover( $value );
3753 }
3754 }
3755 }
3756
3757 return $data;
3758 }
3759
3760 protected function wkit_update_elementor_template(){
3761
3762 if ( isset( $_POST['data'] ) ) {
3763 $content = ! empty( $_POST['data'] ) ? json_decode( wp_unslash( $_POST['data'] ), true ) : '';
3764 }
3765
3766 if ( isset( $_POST['template_id'] ) ) {
3767 $template_id = ! empty( $_POST['template_id'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['template_id'] ), true ) ) : '';
3768 }
3769
3770 $document = \Elementor\Plugin::$instance->documents->get($template_id);
3771
3772 // This saves content posted straight from the browser, which carries local image
3773 // URLs but still the source template's attachment IDs. Without repairing them the
3774 // save undoes what wdkit_media_import() fixed on create, and has_sizes controls —
3775 // container background images especially — resolve to nothing and render empty.
3776 $content = self::wdkit_repair_attachment_ids( $content );
3777
3778 $document->save([
3779 'elements' => $content
3780 ]);
3781 }
3782
3783 /**
3784 * Update the content of an already-created page.
3785 *
3786 * Used by the async ("Site Ready first") import path: pages are created up front with
3787 * their un-rewritten template content, then this writes the AI-rewritten content into
3788 * each page in the background. Elementor saves via the document API (same as
3789 * wkit_update_elementor_template); Gutenberg writes post_content directly.
3790 *
3791 * @since 2.6.2
3792 */
3793 protected function wdkit_update_page_content() {
3794 $post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
3795 $builder = isset( $_POST['builder'] ) ? sanitize_text_field( wp_unslash( $_POST['builder'] ) ) : '';
3796
3797 if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
3798 return array(
3799 'success' => false,
3800 'message' => esc_html__( 'Invalid page or insufficient permission', 'wdesignkit' ),
3801 );
3802 }
3803
3804 if ( 'gutenberg' === $builder ) {
3805 // Do NOT run kses here: Gutenberg block delimiters are HTML comments
3806 // (<!-- wp:... -->) which kses strips. Mirror the create path, which stores
3807 // the block markup slashed and unfiltered (endpoint is manage_options-gated
3808 // and the content is plugin-generated).
3809 $content = isset( $_POST['content'] ) ? wp_unslash( $_POST['content'] ) : '';
3810
3811 // This content comes straight from the browser and still carries the template
3812 // site's media URLs and attachment IDs, so it has to go through the same pipeline
3813 // the create path uses. Without this the save simply undid the import: the files
3814 // were fetched, then overwritten by a copy still pointing at the source site.
3815 //
3816 // Re-running is cheap. Every URL already handled resolves from the source-hash
3817 // lookup, and media that is already local resolves straight from its URL, so no
3818 // image is fetched or stored twice.
3819 $content = $this->wdkit_relink_gutenberg_content( $content );
3820
3821 $result = wp_update_post(
3822 array(
3823 'ID' => $post_id,
3824 'post_content' => wp_slash( $content ),
3825 ),
3826 true
3827 );
3828
3829 if ( is_wp_error( $result ) ) {
3830 return array(
3831 'success' => false,
3832 'message' => $result->get_error_message(),
3833 );
3834 }
3835
3836 self::wdkit_rebuild_block_css( $post_id );
3837 } else {
3838 $elements = isset( $_POST['content'] ) ? json_decode( wp_unslash( $_POST['content'] ), true ) : array();
3839
3840 if ( ! class_exists( '\\Elementor\\Plugin' ) ) {
3841 return array(
3842 'success' => false,
3843 'message' => esc_html__( 'Elementor not available', 'wdesignkit' ),
3844 );
3845 }
3846
3847 $document = \Elementor\Plugin::$instance->documents->get( $post_id );
3848 if ( ! $document ) {
3849 return array(
3850 'success' => false,
3851 'message' => esc_html__( 'Elementor document not found', 'wdesignkit' ),
3852 );
3853 }
3854
3855 // Same as wkit_update_elementor_template(): browser-posted content keeps the
3856 // source template's attachment IDs, so repair them or this save undoes the
3857 // create-time fix and background images stop rendering.
3858 $elements = self::wdkit_repair_attachment_ids( $elements );
3859
3860 $document->save( array( 'elements' => $elements ) );
3861 }
3862
3863 return array(
3864 'success' => true,
3865 'message' => esc_html__( 'Page content updated', 'wdesignkit' ),
3866 );
3867 }
3868
3869 /**
3870 * Import single template and section from plugin only
3871 *
3872 * @param array $args store data.
3873 * @param array $template_id store data.
3874 * @param array $data store data.
3875 * @param array $temp_data store data.
3876 * */
3877 protected function import_page_section_content() {
3878
3879 // Elementor sideloads every image referenced by the page from inside this request.
3880 // A single oversized source image decodes to more than the whole memory limit, so
3881 // guard before any of that starts.
3882 $this->wdkit_guard_oversized_images();
3883
3884 // Sideloading images for image-heavy pages (wdkit_media_import → Imagick
3885 // thumbnail generation per image) can exceed the default 30s execution
3886 // limit and fatal the request mid-import. Give this single page import
3887 // more headroom; harmless no-op where set_time_limit() is disabled.
3888 if ( function_exists( 'set_time_limit' ) ) {
3889 @set_time_limit( 120 );
3890 }
3891
3892 if ( isset( $_POST['args'] ) ) {
3893 $args = ! empty( $_POST['args'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['args'] ) ), true ) : array();
3894 }
3895
3896 if ( isset( $_POST['temp_data'] ) ) {
3897 $temp_data = ! empty( $_POST['temp_data'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['temp_data'] ) ), true ) : array();
3898 }
3899
3900 if ( isset( $_POST['category_list'] ) ) {
3901 $category_list = ! empty( $_POST['category_list'] ) ? json_decode( wp_unslash( $_POST['category_list'] ), true ) : '';
3902 }
3903
3904 if ( isset( $_POST['tag_list'] ) ) {
3905 $tag_list = ! empty( $_POST['tag_list'] ) ? json_decode( wp_unslash( $_POST['tag_list'] ), true ) : '';
3906 }
3907
3908 if ( isset( $_POST['thumb_image'] ) ) {
3909 $thumb_image = ! empty( $_POST['thumb_image'] ) ? esc_url_raw( $_POST['thumb_image'] ) : '';
3910 }
3911
3912 if ( isset( $_POST['template_id'] ) ) {
3913 $template_id = ! empty( $_POST['template_id'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['template_id'] ), true ) ) : '';
3914 }
3915
3916 $temp_type = isset( $_POST['temp_type'] ) ? sanitize_text_field( wp_unslash( $_POST['temp_type'] ) ) : 'normal';
3917
3918 if ( isset( $_POST['data'] ) ) {
3919 $data = ! empty( $_POST['data'] ) ? json_decode( wp_unslash( $_POST['data'] ) ) : '';
3920 }
3921
3922 $enqueue_instance = new Wdkit_Enqueue();
3923 $get_post_type = $enqueue_instance->wdkit_get_post_type_list();
3924
3925 $post_type = ! empty( $temp_data['type'] ) ? sanitize_text_field( wp_unslash( $temp_data['type'] ) ) : 'page';
3926
3927 if ( 'section' === $post_type ) {
3928 $post_type = $temp_data['wp_post_type'];
3929 } else {
3930 $post_type = $temp_data['wp_post_type'];
3931 }
3932
3933 if ( ! array_key_exists( $post_type, $get_post_type ) ) {
3934 $post_type = 'page';
3935 }
3936
3937 if ( ! empty( $data ) && ! empty( $template_id ) && ! empty( $post_type ) && current_user_can( 'manage_options' ) ) {
3938 $post_content = $data;
3939 $post_title = isset( $post_content->title ) ? sanitize_text_field( $post_content->title ) : '';
3940 $post_slug = isset( $post_content->slug ) ? sanitize_text_field( $post_content->slug ) : '';
3941 $file_type = isset( $post_content->file_type ) ? sanitize_text_field( $post_content->file_type ) : '';
3942 $content = isset( $post_content->content ) ? wp_slash( $post_content->content ) : '';
3943 $temp_con = '';
3944
3945 if ( 'gutenberg' === $args['editor'] || ( 'wdkit' === $args['editor'] && ! empty( $file_type ) && 'wp_block' === $file_type ) ) {
3946 if ( empty( $content ) ) {
3947 wp_send_json(
3948 array(
3949 'template_id' => $template_id,
3950 'message' => __( 'Content is Empty.', 'wdesignkit' ),
3951 )
3952 );
3953 wp_die();
3954 } elseif ( ! empty( $content ) && ! empty( $file_type ) && 'wp_block' === $file_type ) {
3955
3956 $editor = ( 'wdkit' === $args['editor'] ) ? 'gutenberg' : $args['editor'];
3957 $blocks = parse_blocks( stripslashes( $content ) );
3958
3959 $blocks = $this->wdkit_media_import( $blocks, $editor );
3960
3961 $processor = new WDKIT_Nexter_Block_Processor();
3962 $blocks = $processor->run( $blocks );
3963 $content = serialize_blocks( $blocks );
3964
3965 $content = $this->replace_unicode_glitch( serialize_blocks( $blocks ) );
3966
3967 $inserted_post = wp_insert_post(
3968 array(
3969 'post_status' => 'publish',
3970 'post_type' => $post_type,
3971 'post_title' => $post_title,
3972 'post_name' => $post_slug,
3973 'post_content' => $content,
3974 )
3975 );
3976
3977 if ( is_wp_error( $inserted_post ) ) {
3978 wp_send_json(
3979 array(
3980 'import_failed' => $inserted_post->get_error_message(),
3981 'code' => $inserted_post->get_error_code(),
3982 )
3983 );
3984 wp_die();
3985 }
3986
3987 if ( ! empty( $thumb_image ) ) {
3988 // $featured_image_url = esc_url_raw( $thumb_image );
3989 $tmp = download_url( $thumb_image );
3990 if ( is_wp_error( $tmp ) ) {
3991 error_log( 'Image download failed: ' . esc_html( $tmp->get_error_message() ) );
3992 } else {
3993 $file_array = array(
3994 'name' => wp_basename( $thumb_image ),
3995 'tmp_name' => $tmp,
3996 );
3997
3998 $image_id = media_handle_sideload( $file_array, $inserted_post );
3999
4000 if ( is_wp_error( $image_id ) ) {
4001 error_log( 'Image sideload failed: ' . esc_html( $image_id->get_error_message() ) );
4002 } else {
4003 set_post_thumbnail( $inserted_post, $image_id );
4004 }
4005
4006 @unlink( $tmp );
4007 }
4008 }
4009
4010 if ( ! empty( $category_list ) && is_array( $category_list ) ) {
4011 $category_ids = array_map( 'intval', $category_list );
4012 wp_set_post_terms( $inserted_post, $category_ids, 'category' );
4013 }
4014
4015 if ( ! empty( $tag_list ) && is_array( $tag_list ) ) {
4016 $tag_ids = array_map( 'intval', $tag_list );
4017 wp_set_post_terms( $inserted_post, $tag_ids, 'post_tag' );
4018 }
4019
4020 if ( ! empty( $args['custom_meta'] ) && 'true' == $args['custom_meta'] ) {
4021 $custom_meta = isset( $post_content->custom_meta ) ? json_decode( wp_json_encode( $post_content->custom_meta ), true ) : '';
4022 if ( ! empty( $custom_meta ) ) {
4023 foreach ( $custom_meta as $meta_key => $meta_val ) {
4024 if ( isset( $meta_val[0] ) && ! empty( $meta_val[0] ) && is_serialized( $meta_val[0] ) ) {
4025 $meta_val[0] = maybe_unserialize( $meta_val[0] );
4026 }
4027
4028 if ( '' === get_post_meta( $inserted_post, $meta_key, true ) && isset( $meta_val[0] ) ) {
4029 add_post_meta( $inserted_post, $meta_key, $meta_val[0] );
4030 }
4031 }
4032 }
4033 }
4034
4035 $temp_detail = array(
4036 'title' => get_the_title( $inserted_post ),
4037 'edit_link' => get_edit_post_link( $inserted_post, 'internal' ),
4038 'view' => get_permalink( $inserted_post ),
4039 'id' => $inserted_post,
4040 );
4041
4042 if ( ! empty( $template_id->id ) ) {
4043 $temp_id = $template_id->id;
4044 } elseif ( ! empty( $template_id ) ) {
4045 $temp_id = $template_id;
4046 } else {
4047 $temp_id = '';
4048 }
4049
4050 wp_update_post([
4051 'ID' => $inserted_post,
4052 ]);
4053
4054 if (class_exists('Tpgb_Library') && method_exists('Tpgb_Library', 'remove_backend_dir_files')) {
4055 Tpgb_Library()->remove_backend_dir_files();
4056 }
4057
4058 clean_post_cache( $inserted_post );
4059 wp_send_json(
4060 array(
4061 $temp_id => $temp_detail,
4062 'description' => 'Yay! Your Section has been Successfully Imported.',
4063 'message' => __( 'Successfully Imported.', 'wdesignkit' ),
4064 'inserted_id' => $inserted_post,
4065 'success' => true,
4066 )
4067 );
4068 wp_die();
4069 }
4070 } elseif ( 'elementor' === $args['editor'] || ( 'wdkit' === $args['editor'] && ! empty( $file_type ) && 'elementor' === $file_type ) ) {
4071 if ( did_action( 'elementor/loaded' ) ) {
4072 if ( empty( $content ) ) {
4073 wp_send_json(
4074 array(
4075 'template_id' => $template_id,
4076 'message' => __( 'Content is Empty.', 'wdesignkit' ),
4077 )
4078 );
4079 wp_die();
4080 } elseif ( ! empty( $content ) && ! empty( $file_type ) && 'elementor' === $file_type ) {
4081
4082 $content = $this->wdkit_content_remover( $content );
4083
4084 $post_attributes = array(
4085 'post_title' => $post_title,
4086 'post_type' => $post_type,
4087 'post_status' => 'publish',
4088 'post_name' => $post_slug,
4089 );
4090
4091 if ( 'elementor_library' === $post_type ) {
4092 $el_type = ( isset( $post_content->el_type ) && ! empty( $post_content->el_type ) ) ? sanitize_text_field( $post_content->el_type ) : 'page';
4093 $new_document = \Elementor\Plugin::$instance->documents->create(
4094 $el_type,
4095 $post_attributes
4096 );
4097 } else {
4098 $new_document = \Elementor\Plugin::$instance->documents->create(
4099 $post_attributes['post_type'],
4100 $post_attributes
4101 );
4102 }
4103
4104 if ( is_wp_error( $new_document ) ) {
4105 wp_send_json(
4106 array(
4107 'import_failed' => $new_document->get_error_message(),
4108 'code' => $new_document->get_error_code(),
4109 )
4110 );
4111 wp_die();
4112 }
4113
4114 $inserted_id = $new_document->get_main_id();
4115
4116 if ( ! empty( $thumb_image ) ) {
4117 // $featured_image_url = esc_url_raw( $thumb_image );
4118 $tmp = download_url( $thumb_image );
4119 if ( is_wp_error( $tmp ) ) {
4120 error_log( 'Image download failed: ' . esc_html( $tmp->get_error_message() ) );
4121 } else {
4122 $file_array = array(
4123 'name' => wp_basename( $thumb_image ),
4124 'tmp_name' => $tmp,
4125 );
4126
4127 $image_id = media_handle_sideload( $file_array, $inserted_id );
4128
4129 if ( is_wp_error( $image_id ) ) {
4130 error_log( 'Image sideload failed: ' . esc_html( $image_id->get_error_message() ) );
4131 } else {
4132 set_post_thumbnail( $inserted_id, $image_id );
4133 }
4134
4135 @unlink( $tmp );
4136 }
4137 }
4138
4139 if ( ! empty( $category_list ) && is_array( $category_list ) ) {
4140 $category_ids = array_map( 'intval', $category_list );
4141 wp_set_post_terms( $inserted_id, $category_ids, 'category' );
4142 }
4143
4144 if ( ! empty( $tag_list ) && is_array( $tag_list ) ) {
4145 $tag_ids = array_map( 'intval', $tag_list );
4146 wp_set_post_terms( $inserted_id, $tag_ids, 'post_tag' );
4147 }
4148
4149 $settings = ( isset( $post_content->settings ) && ! empty( $post_content->settings ) ) ? json_decode( wp_json_encode( $post_content->settings ), true ) : array();
4150
4151 $content = wp_json_encode( $content );
4152 $content = $this->wdkit_media_import( $content, $file_type );
4153
4154 $new_document->save(
4155 array(
4156 'elements' => $content,
4157 'settings' => ! empty( $settings ) ? $settings : array(),
4158 )
4159 );
4160
4161 $inserted_id = $new_document->get_main_id();
4162
4163 if( $temp_type == 'navigation' ){
4164 $temp_con = $content;
4165 }
4166
4167 if ( ! empty( $args['custom_meta'] ) && 'true' == $args['custom_meta'] ) {
4168 $custom_meta = isset( $post_content->custom_meta ) ? json_decode( wp_json_encode( $post_content->custom_meta ), true ) : '';
4169 if ( ! empty( $custom_meta ) ) {
4170 foreach ( $custom_meta as $meta_key => $meta_val ) {
4171 if ( ! empty( $meta_val[0] ) && is_serialized( $meta_val[0] ) ) {
4172 $meta_val[0] = maybe_unserialize( $meta_val[0] );
4173 }
4174 if ( '' === get_post_meta( $inserted_id, $meta_key, true ) ) {
4175 add_post_meta( $inserted_id, $meta_key, $meta_val[0] );
4176 }
4177 }
4178 }
4179 }
4180
4181 $temp_detail = array(
4182 'title' => get_the_title( $inserted_id ),
4183 'edit_link' => get_edit_post_link( $inserted_id, 'internal' ),
4184 'view' => get_permalink( $inserted_id ),
4185 'id' => $inserted_id,
4186 );
4187
4188 if ( ! empty( $template_id->id ) ) {
4189 $temp_id = $template_id->id;
4190 } elseif ( ! empty( $template_id ) ) {
4191 $temp_id = $template_id;
4192 } else {
4193 $temp_id = '';
4194 }
4195
4196 \Elementor\Plugin::$instance->files_manager->clear_cache();
4197
4198 wp_send_json(
4199 array(
4200 $temp_id => $temp_detail,
4201 'content' => $temp_con,
4202 'description' => 'Yay! Your Section has been Successfully Imported.',
4203 'message' => __( 'Successfully Imported.', 'wdesignkit' ),
4204 'inserted_id' => $inserted_id,
4205 'success' => true,
4206 )
4207 );
4208 wp_die();
4209 }
4210 } else {
4211 wp_send_json(
4212 array(
4213 'template_id' => $template_id,
4214 'message' => esc_html__( 'Relevant Page Builder not installed or activated', 'wdesignkit' ),
4215 )
4216 );
4217 wp_die();
4218 }
4219 }
4220 }
4221
4222 wp_send_json(
4223 array(
4224 'success' => false,
4225 'message' => esc_html__( 'Something went wrong', 'wdesignkit' ),
4226 )
4227 );
4228 wp_die();
4229 }
4230
4231 /**
4232 * Replace unicode glitch
4233 *
4234 * @since 2.0.0
4235 */
4236 private function replace_unicode_glitch( $content ) {
4237
4238 // Fix escaped unicode like \u003c → <
4239 $content = preg_replace_callback(
4240 '/\\\\u([0-9a-fA-F]{4})/',
4241 function ( $match ) {
4242 return html_entity_decode(
4243 mb_convert_encoding(
4244 pack('H*', $match[1]),
4245 'UTF-8',
4246 'UCS-2BE'
4247 ),
4248 ENT_QUOTES,
4249 'UTF-8'
4250 );
4251 },
4252 $content
4253 );
4254
4255 return $content;
4256 }
4257
4258
4259 /**
4260 * change plugins setting for import kit
4261 *
4262 * @since 2.0.0
4263 */
4264 protected function update_plugin_setting() {
4265 $temp_id = isset( $_POST['plugin_type'] ) ? sanitize_text_field( $_POST['plugin_type'] ) : '';
4266
4267 if ( $temp_id == 'elementor' ) {
4268 $unfiltered_files = get_option( 'elementor_unfiltered_files_upload', false );
4269 $load_fa4 = get_option( 'elementor_load_fa4_shim', false );
4270 $Inline_font_icons = get_option( 'elementor_experiment-e_font_icon_svg', false );
4271 $container = get_option( 'elementor_experiment-container', false );
4272
4273 if ( isset( $unfiltered_files ) ) {
4274 update_option( 'elementor_unfiltered_files_upload', 1 );
4275 } else {
4276 add_option( 'elementor_unfiltered_files_upload', 1 );
4277 }
4278
4279 if ( isset( $load_fa4 ) ) {
4280 update_option( 'elementor_load_fa4_shim', 'yes' );
4281 } else {
4282 add_option( 'elementor_load_fa4_shim', 'yes' );
4283 }
4284
4285 if ( isset( $container ) ) {
4286 update_option( 'elementor_experiment-container', 'active' );
4287 } else {
4288 add_option( 'elementor_experiment-container', 'active' );
4289 }
4290
4291 if ( isset( $Inline_font_icons ) ) {
4292 update_option( 'elementor_experiment-e_font_icon_svg', 'inactive' );
4293 } else {
4294 add_option( 'elementor_experiment-e_font_icon_svg', 'inactive' );
4295 }
4296
4297 $response = array(
4298 'message' => esc_html__( 'Plugin Setting updated', 'wdesignkit' ),
4299 'description' => esc_html__( 'Plugin Setting updated', 'wdesignkit' ),
4300 'success' => true,
4301 );
4302 } else {
4303 $response = array(
4304 'message' => esc_html__( 'Plugin not found', 'wdesignkit' ),
4305 'description' => esc_html__( 'Plugin not found', 'wdesignkit' ),
4306 'success' => false,
4307 );
4308 }
4309
4310 wp_send_json( $response );
4311 wp_die();
4312 }
4313
4314 /**
4315 * generate different color logo
4316 *
4317 * @since 2.0.0
4318 */
4319 protected function wkit_generate_site_logo() {
4320
4321 if ( empty( $_POST['image_url'] ) ) {
4322 wp_send_json_error( 'Image URL not provided.' );
4323 }
4324
4325 if ( isset( $_POST['colors'] ) ) {
4326 $img_colors = ! empty( $_POST['colors'] ) ? json_decode( sanitize_text_field( wp_unslash( $_POST['colors'] ) ), true ) : array();
4327 }
4328
4329 if ( empty( $img_colors ) ) {
4330 wp_send_json_error( 'Image color not provided.' );
4331 }
4332
4333 $image_url = esc_url_raw( $_POST['image_url'] );
4334
4335 $tmp_file = download_url( $image_url );
4336 if ( is_wp_error( $tmp_file ) ) {
4337 wp_send_json_error( 'Image could not be downloaded.' );
4338 }
4339
4340 if ( mime_content_type( $tmp_file ) !== 'image/png' ) {
4341 unlink( $tmp_file );
4342 wp_send_json_error( 'Not a PNG file.' );
4343 }
4344
4345 $src = imagecreatefrompng( $tmp_file );
4346 imagesavealpha( $src, true );
4347
4348 $width = imagesx( $src );
4349 $height = imagesy( $src );
4350
4351 $hasTransparency = false;
4352 for ( $x = 0; $x < $width; $x++ ) {
4353 for ( $y = 0; $y < $height; $y++ ) {
4354 $rgba = imagecolorat( $src, $x, $y );
4355 $alpha = ( $rgba & 0x7F000000 ) >> 24;
4356
4357 if ( $alpha > 0 ) {
4358 $hasTransparency = true;
4359 break 2;
4360 }
4361 }
4362 }
4363
4364 if ( ! $hasTransparency ) {
4365 unlink( $tmp_file );
4366 wp_send_json_error( 'PNG has no transparent pixels.' );
4367 }
4368
4369 $upload_dir = wp_upload_dir();
4370 $result_urls = array();
4371
4372 foreach ( $img_colors as $name => $rgb ) {
4373 $new = imagecreatetruecolor( $width, $height );
4374 imagesavealpha( $new, true );
4375 imagealphablending( $new, false );
4376
4377 $transparent = imagecolorallocatealpha( $new, 0, 0, 0, 127 );
4378 imagefill( $new, 0, 0, $transparent );
4379
4380 for ( $x = 0; $x < $width; $x++ ) {
4381 for ( $y = 0; $y < $height; $y++ ) {
4382 $rgba = imagecolorat( $src, $x, $y );
4383 $alpha = ( $rgba & 0x7F000000 ) >> 24;
4384
4385 // Skip fully transparent pixels
4386 if ( $alpha === 127 ) {
4387 continue;
4388 }
4389
4390 // Replace pixel color directly
4391 $new_r = $rgb[0];
4392 $new_g = $rgb[1];
4393 $new_b = $rgb[2];
4394
4395 $color = imagecolorallocatealpha( $new, $new_r, $new_g, $new_b, $alpha );
4396 imagesetpixel( $new, $x, $y, $color );
4397 }
4398 }
4399
4400 $filename = 'colored-' . $name . '-' . time() . '.png';
4401 $filepath = $upload_dir['path'] . '/' . $filename;
4402
4403 imagepng( $new, $filepath );
4404 imagedestroy( $new );
4405
4406 $attachment = array(
4407 'post_mime_type' => 'image/png',
4408 'post_title' => sanitize_file_name( $filename ),
4409 'post_content' => '',
4410 'post_status' => 'inherit',
4411 );
4412
4413 $attach_id = wp_insert_attachment( $attachment, $filepath );
4414 require_once ABSPATH . 'wp-admin/includes/image.php';
4415 $attach_data = wp_generate_attachment_metadata( $attach_id, $filepath );
4416 wp_update_attachment_metadata( $attach_id, $attach_data );
4417
4418 $result_urls[ $name ] = wp_get_attachment_url( $attach_id );
4419 }
4420
4421 imagedestroy( $src );
4422 unlink( $tmp_file );
4423
4424 wp_send_json_success( $result_urls );
4425 }
4426
4427 /**
4428 * change theme setting for import kit
4429 *
4430 * @since 2.0.0
4431 */
4432 protected function update_theme_setting() {
4433 $theme_db = get_option( 'nxt-theme-options', false );
4434
4435 $container_type = 'container-fluid';
4436 $fluid_spacing = array(
4437 'md' => array(
4438 'left' => '0',
4439 'right' => '0',
4440 ),
4441 'sm' => array(
4442 'left' => '',
4443 'right' => '',
4444 ),
4445 'xs' => array(
4446 'left' => '',
4447 'right' => '',
4448 ),
4449 'md-unit' => 'px',
4450 'sm-unit' => 'px',
4451 'xs-unit' => 'px',
4452 );
4453
4454 if ( isset( $theme_db ) ) {
4455 $nexter_setting = $theme_db;
4456 $nexter_setting['site-header-container'] = $container_type;
4457 $nexter_setting['site-footer-container'] = $container_type;
4458 $nexter_setting['site-layout-container'] = $container_type;
4459 $nexter_setting['site-page-container'] = $container_type;
4460
4461 $nexter_setting['header-fluid-spacing'] = $fluid_spacing;
4462 $nexter_setting['footer-fluid-spacing'] = $fluid_spacing;
4463 $nexter_setting['site-fluid-spacing'] = $fluid_spacing;
4464 $nexter_setting['page-fluid-spacing'] = $fluid_spacing;
4465
4466 update_option( 'nxt-theme-options', $nexter_setting );
4467 } else {
4468 $nexter_setting = array(
4469 'site-header-container' => 'container-fluid',
4470 'header-fluid-spacing' => array(
4471 'md' => array(
4472 'left' => '0',
4473 'right' => '0',
4474 ),
4475 'sm' => array(
4476 'left' => '',
4477 'right' => '',
4478 ),
4479 'xs' => array(
4480 'left' => '',
4481 'right' => '',
4482 ),
4483 'md-unit' => 'px',
4484 'sm-unit' => 'px',
4485 'xs-unit' => 'px',
4486 ),
4487 'site-footer-container' => 'container-fluid',
4488 'footer-fluid-spacing' => array(
4489 'md' => array(
4490 'left' => '0',
4491 'right' => '0',
4492 ),
4493 'sm' => array(
4494 'left' => '',
4495 'right' => '',
4496 ),
4497 'xs' => array(
4498 'left' => '',
4499 'right' => '',
4500 ),
4501 'md-unit' => 'px',
4502 'sm-unit' => 'px',
4503 'xs-unit' => 'px',
4504 ),
4505 'site-layout-container' => 'container-fluid',
4506 'site-fluid-spacing' => array(
4507 'md' => array(
4508 'left' => '0',
4509 'right' => '0',
4510 ),
4511 'sm' => array(
4512 'left' => '',
4513 'right' => '',
4514 ),
4515 'xs' => array(
4516 'left' => '',
4517 'right' => '',
4518 ),
4519 'md-unit' => 'px',
4520 'sm-unit' => 'px',
4521 'xs-unit' => 'px',
4522 ),
4523 'site-page-container' => 'container-fluid',
4524 'page-fluid-spacing' => array(
4525 'md' => array(
4526 'left' => '0',
4527 'right' => '0',
4528 ),
4529 'sm' => array(
4530 'left' => '',
4531 'right' => '',
4532 ),
4533 'xs' => array(
4534 'left' => '',
4535 'right' => '',
4536 ),
4537 'md-unit' => 'px',
4538 'sm-unit' => 'px',
4539 'xs-unit' => 'px',
4540 ),
4541 'site-page-container' => '',
4542 'site-posts-container' => '',
4543 'site-archive-container' => '',
4544 );
4545
4546 add_option( 'nxt-theme-options', $nexter_setting );
4547 }
4548
4549 $response = array(
4550 'message' => esc_html__( 'Theme Setting updated', 'wdesignkit' ),
4551 'description' => esc_html__( 'Theme Setting updated', 'wdesignkit' ),
4552 'success' => true,
4553 );
4554
4555 wp_send_json( $response );
4556 wp_die();
4557 }
4558
4559 /**
4560 * change site setting for import kit
4561 *
4562 * @since 2.0.0
4563 */
4564 protected function update_site_setting() {
4565 $temp_id = isset( $_POST['id'] ) ? sanitize_text_field( wp_unslash( $_POST['id'] ) ) : '';
4566 $shop_id = isset( $_POST['shop_id'] ) ? sanitize_text_field( wp_unslash( $_POST['shop_id'] ) ) : '';
4567 $temp_type = isset( $_POST['temp_type'] ) ? sanitize_text_field( wp_unslash( $_POST['temp_type'] ) ) : 'page';
4568 $site_name = isset( $_POST['site_name'] ) ? sanitize_text_field( wp_unslash( $_POST['site_name'] ) ) : '';
4569 $site_tagline = isset( $_POST['site_tagline'] ) ? sanitize_text_field( wp_unslash( $_POST['site_tagline'] ) ) : '';
4570
4571 $this->wdkit_nxt_thembuilder_update();
4572
4573 if ( ! empty( $shop_id ) ) {
4574 update_option( 'woocommerce_shop_page_id', $shop_id );
4575 }
4576
4577 if ( $temp_id ) {
4578 update_option( 'show_on_front', $temp_type );
4579 update_option( 'page_on_front', $temp_id );
4580
4581 if ( ! empty( $site_name ) ) {
4582 update_option( 'blogname', $site_name );
4583 }
4584
4585 if ( ! empty( $site_tagline ) ) {
4586 update_option( 'blogdescription', $site_tagline );
4587 }
4588
4589 $response = array(
4590 'message' => esc_html__( 'Site link updated', 'wdesignkit' ),
4591 'description' => esc_html__( 'Site link updated', 'wdesignkit' ),
4592 'site_link' => get_site_url(),
4593 'success' => true,
4594 );
4595 } else {
4596 $response = array(
4597 'message' => esc_html__( 'Site not found', 'wdesignkit' ),
4598 'description' => esc_html__( 'Site not found', 'wdesignkit' ),
4599 'success' => false,
4600 );
4601 }
4602
4603 wp_send_json( $response );
4604 wp_die();
4605 }
4606
4607 /**
4608 * update theme builder
4609 *
4610 * @since 2.0.4
4611 */
4612 public function wdkit_nxt_thembuilder_update() {
4613
4614 $page_information = isset( $_POST['page_information'] ) ? sanitize_text_field( wp_unslash( $_POST['page_information'] ) ) : '';
4615 $page_information = json_decode( $page_information, true );
4616
4617 if ( ! empty( $page_information ) && is_array( $page_information ) ) {
4618
4619 // Every page and attachment now exists, so resolve any image ID the per-page
4620 // pass could not (siblings import concurrently and share icons).
4621 $this->wdkit_sweep_attachment_ids( wp_list_pluck( $page_information, 'inserted_id' ) );
4622
4623 // Step 1: banavo mapping [ old_id => new_id ]
4624 $id_mapping = array();
4625 foreach ( $page_information as $page_info ) {
4626 if ( ! empty( $page_info['old_page_id'] ) ) {
4627 $id_mapping[ $page_info['old_page_id'] ] = $page_info['inserted_id'];
4628 }
4629 }
4630
4631 // Step 2: loop karo and update exclude
4632 foreach ( $page_information as $page_info ) {
4633
4634 $post_id = $page_info['inserted_id'] ?? '';
4635 $old_post_id = $page_info['old_page_id'] ?? '';
4636 $post_type = $page_info['post_type'] ?? '';
4637
4638 if ( empty( $old_post_id ) ) {
4639 continue; // only update where old id exists
4640 }
4641
4642 if ( $post_type != 'nxt_builder' ) {
4643 continue;
4644 }
4645
4646 $include_specific = get_post_meta( $post_id, 'nxt-hooks-layout-specific', true );
4647 if ( ! empty( $include_specific ) && is_array( $include_specific ) ) {
4648
4649 foreach ( $include_specific as $key => $val ) {
4650
4651 // check karo ke koi old_id ka post match kare che ke nahi
4652 foreach ( $id_mapping as $old_id => $new_id ) {
4653 $search = 'post-' . $old_id;
4654 $replace = 'post-' . $new_id;
4655
4656 if ( $val === $search ) {
4657 $include_specific[ $key ] = $replace;
4658 }
4659 }
4660 }
4661
4662 // save back updated array
4663 update_post_meta( $post_id, 'nxt-hooks-layout-specific', $include_specific );
4664 }
4665
4666 // Get exclude meta
4667 $exclude_specific = get_post_meta( $post_id, 'nxt-hooks-layout-exclude-specific', true );
4668 if ( ! empty( $exclude_specific ) && is_array( $exclude_specific ) ) {
4669
4670 foreach ( $exclude_specific as $key => $val ) {
4671
4672 // check karo ke koi old_id ka post match kare che ke nahi
4673 foreach ( $id_mapping as $old_id => $new_id ) {
4674 $search = 'post-' . $old_id;
4675 $replace = 'post-' . $new_id;
4676
4677 if ( $val === $search ) {
4678 $exclude_specific[ $key ] = $replace;
4679 }
4680 }
4681 }
4682
4683 // save back updated array
4684 update_post_meta( $post_id, 'nxt-hooks-layout-exclude-specific', $exclude_specific );
4685 }
4686 }
4687 }
4688 }
4689
4690 /**
4691 *
4692 * select team image for import kit
4693 *
4694 * @since 2.2.2
4695 */
4696 public function wdkit_check_user_credit() {
4697 $array_data = array(
4698 'token' => isset( $_POST['token'] ) ? sanitize_text_field( $_POST['token'] ) : '',
4699 );
4700
4701 $response = $this->wkit_api_call( $array_data, 'ai/credits/get' );
4702 $success = ! empty( $response['success'] ) ? $response['success'] : false;
4703
4704 if ( empty( $success ) ) {
4705 $response = array(
4706 'success' => false,
4707 'message' => esc_html__( 'Data Not Found', 'wdesignkit' ),
4708 'description' => esc_html__( 'Data not found', 'wdesignkit' ),
4709 );
4710
4711 wp_send_json( $response );
4712 wp_die();
4713 }
4714
4715 $response = json_decode( wp_json_encode( $response['data'] ), true );
4716
4717 wp_send_json( $response );
4718 wp_die();
4719 }
4720
4721 public function wdkit_nxt_thembuilder_reset() {
4722 $post_id = isset( $_POST['post_id'] ) ? sanitize_text_field( $_POST['post_id'] ) : '';
4723 $sections_layout = get_post_meta( $post_id, 'nxt-hooks-layout-sections', true );
4724
4725 if ( ( ! empty( $sections_layout ) && ( $sections_layout == 'header' || $sections_layout == 'footer' || $sections_layout == 'breadcrumb' || $sections_layout == 'hooks' ) ) ) {
4726 if ( get_post_meta( $post_id, 'nxt-add-display-rule' ) ) {
4727 delete_post_meta( $post_id, 'nxt-add-display-rule' );
4728 }
4729
4730 if ( get_post_meta( $post_id, 'nxt-hooks-layout-specific' ) ) {
4731 update_post_meta( $post_id, 'nxt-hooks-layout-specific', '' );
4732 }
4733
4734 if ( get_post_meta( $post_id, 'nxt-exclude-display-rule' ) ) {
4735 update_post_meta( $post_id, 'nxt-exclude-display-rule', '' );
4736 }
4737
4738 if ( get_post_meta( $post_id, 'nxt-hooks-layout-exclude-specific' ) ) {
4739 update_post_meta( $post_id, 'nxt-hooks-layout-exclude-specific', '' );
4740 }
4741 }
4742 }
4743
4744
4745 /**
4746 * Share with Me Template and widgets
4747 *
4748 * @since 1.0.0
4749 */
4750 protected function wdkit_shared_with_me() {
4751 $data = isset( $_POST['api_info'] ) ? json_decode( stripslashes( sanitize_text_field( wp_unslash( $_POST['api_info'] ) ) ) ) : '';
4752
4753 $array_data = array(
4754 'token' => isset( $data->token ) ? sanitize_text_field( $data->token ) : '',
4755 'type' => isset( $data->type ) ? sanitize_text_field( wp_unslash( $data->type ) ) : '',
4756 'ParPage' => isset( $data->par_page ) ? (int) $data->par_page : 12,
4757 'CurrentPage' => isset( $data->current_page ) ? (int) $data->current_page : 1,
4758 'builder' => isset( $data->builder ) ? sanitize_text_field( wp_unslash( $data->builder ) ) : '',
4759 );
4760
4761 $response = $this->wkit_api_call( $array_data, 'shared_with_me' );
4762 $success = ! empty( $response['success'] ) ? $response['success'] : false;
4763
4764 wp_send_json( $response );
4765 wp_die();
4766 }
4767
4768 /**
4769 * Add new WorkSpace
4770 *
4771 * @since 1.0.0
4772 */
4773 protected function wdkit_manage_workspace() {
4774 $args = $this->wdkit_parse_args( $_POST );
4775
4776 $user_email = ! empty( $args['email'] ) ? strtolower( sanitize_email( $args['email'] ) ) : '';
4777 $current_wid = ! empty( $_POST['current_wid'] ) ? strtolower( sanitize_text_field( $_POST['current_wid'] ) ) : '';
4778
4779 $args['current_wid'] = $current_wid;
4780
4781 if ( empty( $user_email ) ) {
4782 $response = array(
4783 'message' => $this->e_msg_login,
4784 'description' => $this->e_desc_login,
4785 'success' => false,
4786 );
4787
4788 wp_send_json( $response );
4789 wp_die();
4790 }
4791
4792 $args['token'] = $this->wdkit_login_user_token( $user_email );
4793 unset( $user_email );
4794
4795 $response = WDesignKit_Data_Query::get_data( 'manage_workspace', $args );
4796
4797 return $response;
4798 }
4799
4800 /**
4801 *
4802 * It is Use for manage workspace
4803 *
4804 * @since 1.0.0
4805 */
4806 protected function wdkit_manage_widget_workspace() {
4807 $workspace_info = isset( $_POST['workspace_info'] ) ? sanitize_text_field( wp_unslash( $_POST['workspace_info'] ) ) : array();
4808 $data = isset( $workspace_info ) ? json_decode( stripslashes( $workspace_info ) ) : array();
4809
4810 $array_data = array(
4811 'token' => isset( $data->token ) ? sanitize_text_field( $data->token ) : '',
4812 'wstype' => isset( $data->type ) ? sanitize_text_field( $data->type ) : '',
4813 'widget_id' => isset( $data->widget_id ) ? (int) $data->widget_id : '',
4814 'wid' => isset( $data->wid ) ? (int) $data->wid : '',
4815 'current_wid' => isset( $data->current_wid ) ? (int) $data->current_wid : '',
4816 );
4817
4818 $response = $this->wkit_api_call( $array_data, 'manage_workspace' );
4819
4820 wp_send_json( $response['data'] );
4821 wp_die();
4822 }
4823
4824 /**
4825 *
4826 * It is Use for manage api key page
4827 *
4828 * @since 1.0.0
4829 */
4830 protected function wdkit_activate_key() {
4831 $email = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : '';
4832 $response = '';
4833
4834 // Bug C fix: variable was $user_email but only $email is set above — always triggered empty() guard.
4835 if ( empty( $email ) ) {
4836 $response = array(
4837 'message' => $this->e_msg_login,
4838 'description' => $this->e_desc_login,
4839 'success' => false,
4840 );
4841
4842 wp_send_json( $response );
4843 wp_die();
4844 }
4845
4846 $token = $this->wdkit_login_user_token( $email );
4847 $apikey = isset( $_POST['apikey'] ) ? sanitize_key( wp_unslash( $_POST['apikey'] ) ) : '';
4848 $product = isset( $_POST['product'] ) ? sanitize_text_field( wp_unslash( $_POST['product'] ) ) : '';
4849 $product_action = isset( $_POST['product_action'] ) ? sanitize_text_field( wp_unslash( $_POST['product_action'] ) ) : 'activate';
4850 if ( ! empty( $token ) && ! empty( $product ) && ! empty( $product_action ) ) {
4851 $args = array(
4852 'token' => $token,
4853 'product' => $product,
4854 'product_action' => $product_action,
4855 );
4856
4857 if ( 'activate' === $product_action ) {
4858 $args['apikey'] = $apikey;
4859 $args['site_url'] = home_url();
4860 }
4861
4862 $response = Wdkit_Data_Hooks::get_data( 'wkit_activate_key', $args );
4863 }
4864
4865 wp_send_json( $response );
4866 wp_die();
4867 }
4868
4869 /**
4870 *
4871 * Get list local Widget List
4872 *
4873 * @since 1.0.0
4874 */
4875 protected function wdkit_get_local_widgets() {
4876 $builder = array();
4877 $a_c_s_d_s_c = array();
4878 $j_s_o_n_array = array();
4879
4880 if ( Wdkit_Wdesignkit::wdkit_is_compatible( 'bricks', 'widget' ) ) {
4881 array_push( $builder, 'bricks' );
4882 }
4883
4884 if ( Wdkit_Wdesignkit::wdkit_is_compatible( 'elementor', 'widget' ) ) {
4885 array_push( $builder, 'elementor' );
4886 }
4887
4888 if ( Wdkit_Wdesignkit::wdkit_is_compatible( 'gutenberg', 'widget' ) ) {
4889 array_push( $builder, 'gutenberg' );
4890 }
4891
4892 if ( Wdkit_Wdesignkit::wdkit_is_compatible( 'gutenberg_core', 'widget' ) ) {
4893 array_push( $builder, 'gutenberg_core' );
4894 }
4895
4896 foreach ( $builder as $key => $name ) {
4897 $elementor_dir = WDKIT_BUILDER_PATH . '/' . $name;
4898
4899 if ( ! empty( $elementor_dir ) && is_dir( $elementor_dir ) ) {
4900 $elementor_list = scandir( $elementor_dir );
4901 $elementor_list = array_diff( $elementor_list, array( '.', '..' ) );
4902
4903 if ( ! empty( $elementor_list ) ) {
4904 foreach ( $elementor_list as $key => $value ) {
4905 $a_c_s_d_s_c[ filemtime( "{$elementor_dir}/{$value}" ) . $key ]['data'] = $value;
4906 $a_c_s_d_s_c[ filemtime( "{$elementor_dir}/{$value}" ) . $key ]['builder'] = $name;
4907 }
4908 }
4909 }
4910 }
4911
4912 ksort( $a_c_s_d_s_c );
4913 $a_c_s_d_s_c = array_reverse( $a_c_s_d_s_c );
4914
4915 foreach ( $a_c_s_d_s_c as $key => $value ) {
4916 $elementor_dir = WDKIT_BUILDER_PATH . '/' . $value['builder'];
4917
4918 if ( file_exists( "{$elementor_dir}/{$value['data']}" ) && is_dir( "{$elementor_dir}/{$value['data']}" ) ) {
4919 $sub_dir = scandir( "{$elementor_dir}/{$value['data']}" );
4920 $sub = array_diff( $sub_dir, array( '.', '..' ) );
4921
4922 foreach ( $sub as $sub_dir_value ) {
4923 $file = new SplFileInfo( $sub_dir_value );
4924 $check_ext = $file->getExtension();
4925 $ext = pathinfo( $sub_dir_value, PATHINFO_EXTENSION );
4926
4927 if ( 'json' === $ext ) {
4928 $widget1 = WDKIT_BUILDER_PATH . "/{$value['builder']}/{$value['data']}/{$sub_dir_value}";
4929 $filedata = wp_json_file_decode( $widget1 );
4930 $decode_data = json_decode( wp_json_encode( $filedata ), true );
4931 array_push( $j_s_o_n_array, $decode_data['widget_data'] );
4932 }
4933 }
4934 }
4935 }
4936
4937 return $j_s_o_n_array;
4938 }
4939
4940 /**
4941 *
4942 * It is Use for manage widget category.
4943 *
4944 * @since 1.0.0
4945 */
4946 protected function wdkit_manage_widget_category() {
4947 $data = isset( $_POST['info'] ) ? sanitize_text_field( wp_unslash( $_POST['info'] ) ) : '';
4948 $data = json_decode( stripslashes( $data ) );
4949
4950 $type = isset( $data->manage_type ) ? sanitize_text_field( wp_unslash( $data->manage_type ) ) : '';
4951 $wkit_builder_option = get_option( 'wkit_builder' );
4952
4953 if ( empty( $wkit_builder_option ) ) {
4954 add_option( 'wkit_builder', array( 'WDesignKit' ), '', 'yes' );
4955 }
4956
4957 if ( 'get' === $type ) {
4958 if ( ! in_array( 'WDesignKit', $wkit_builder_option ) ) {
4959 update_option( 'wkit_builder', array( 'WDesignKit' ) );
4960 }
4961 } elseif ( 'update' === $type ) {
4962 $list = isset( $data->category_list ) ? $data->category_list : array();
4963 $list = array_unique( $list );
4964 $list = array_values( $list );
4965
4966 if ( ! empty( $list ) ) {
4967 update_option( 'wkit_builder', $list );
4968 }
4969 }
4970
4971 wp_send_json( get_option( 'wkit_builder' ) );
4972 }
4973
4974 /**
4975 * Get Workspace data
4976 *
4977 * @since 2.2.5
4978 */
4979 public function wdkit_get_workspace_data() {
4980
4981 $wid = isset( $_POST['wid'] ) ? sanitize_text_field( $_POST['wid'] ) : '';
4982 $token = isset( $_POST['token'] ) ? sanitize_text_field( $_POST['token'] ) : '';
4983
4984 if ( empty( $wid ) ) {
4985 return array(
4986 'success' => false,
4987 'message' => esc_html__( 'Workspace ID Not Found', 'wdesignkit' ),
4988 'description' => esc_html__( 'Workspace ID is required', 'wdesignkit' ),
4989 );
4990 }
4991
4992 if ( empty( $token ) ) {
4993 return array(
4994 'success' => false,
4995 'message' => esc_html__( 'Token Not Found', 'wdesignkit' ),
4996 'description' => esc_html__( 'Token is required', 'wdesignkit' ),
4997 );
4998 }
4999
5000 $args = array(
5001 'token' => $token,
5002 'wid' => $wid,
5003 );
5004
5005 $this->wdkit_api = $this->wdkit_api_v2;
5006
5007 $url = "workspace/{$wid}/get";
5008
5009 $response = $this->wkit_api_call( $args, $url );
5010
5011 wp_send_json( $response['data'] );
5012 wp_die();
5013 }
5014
5015 /**
5016 *
5017 * Custom_upload_dir
5018 *
5019 * @since 1.0.0
5020 *
5021 * @param array $upload store data.
5022 */
5023 public function custom_upload_dir( $upload ) {
5024 // Specify the path to your custom upload directory.
5025 if ( isset( $this->widget_folder_u_r_l ) && ! empty( $this->widget_folder_u_r_l ) ) {
5026
5027 // Set the custom directory as the upload path.
5028 $upload['path'] = $this->widget_folder_u_r_l;
5029 // Set the URL for the uploaded file.
5030 $upload['url'] = $upload['baseurl'] . $upload['subdir'];
5031 }
5032
5033 return $upload;
5034 }
5035
5036 /**
5037 *
5038 * It is Use for delete widget from server
5039 *
5040 * @since 1.0.0
5041 */
5042 protected function wkit_widget_json() {
5043 $widget_type = ! empty( $_POST['widget_type'] ) ? wp_unslash( $_POST['widget_type'] ) : '';
5044 $folder_name = ! empty( $_POST['folder_name'] ) ? wp_unslash( $_POST['folder_name'] ) : '';
5045 $file_name = ! empty( $_POST['file_name'] ) ? ( wp_unslash( $_POST['file_name'] ) ) : '';
5046
5047 if ( empty( $widget_type ) || empty( $folder_name ) || empty( $file_name ) ) {
5048 return array(
5049 'success' => false,
5050 'message' => esc_html__( 'Widget JSON not found', 'wdesignkit' ),
5051 'description' => esc_html__( 'widget JSON file not found.', 'wdesignkit' ),
5052 );
5053 }
5054
5055 $json_path = WDKIT_BUILDER_PATH . "/{$widget_type}/{$folder_name}/{$file_name}";
5056
5057 $json_data = wp_json_file_decode( "$json_path.json" );
5058 if ( ! empty( $json_data ) ) {
5059 $result = (object) array(
5060 'success' => true,
5061 'data' => $json_data,
5062 'message' => esc_html__( 'Widget get Successfully', 'wdesignkit' ),
5063 'description' => esc_html__( 'Widget JSON get Successfully', 'wdesignkit' ),
5064 );
5065 } else {
5066 $result = (object) array(
5067 'success' => false,
5068 'message' => esc_html__( 'Widget not get', 'wdesignkit' ),
5069 'description' => esc_html__( 'Widget JSON not get', 'wdesignkit' ),
5070 );
5071 }
5072
5073 wp_send_json( $result );
5074 wp_die();
5075 }
5076
5077 /**
5078 *
5079 * It is Use for download widget from widget listing.
5080 *
5081 * @since 1.0.0
5082 */
5083 protected function wdkit_download_widget() {
5084 $data = ! empty( $_POST['widget_info'] ) ? $this->wdkit_sanitizer_bypass( $_POST, 'widget_info', 'none' ) : '';
5085 $data = json_decode( stripslashes( $data ) );
5086
5087 $array_data = array(
5088 'token' => isset( $data->token ) ? sanitize_text_field( $data->token ) : '',
5089 'type' => isset( $data->type ) ? sanitize_text_field( $data->type ) : '',
5090 'w_unique' => isset( $data->w_uniq ) ? sanitize_text_field( $data->w_uniq ) : '',
5091 // Bug F fix: u_id (widget owner's user ID) was missing — cloud cannot locate the widget without it.
5092 'u_id' => isset( $data->u_id ) ? sanitize_text_field( $data->u_id ) : '',
5093 );
5094
5095 $response = $this->wkit_api_call( $array_data, 'save_widget' );
5096 $success = ! empty( $response['success'] ) ? $response['success'] : false;
5097
5098 if ( empty( $success ) ) {
5099 $massage = ! empty( $response['massage'] ) ? $response['massage'] : esc_html__( 'server error', 'wdesignkit' );
5100 $result = (object) array(
5101 'success' => false,
5102 'message' => $massage,
5103 'description' => esc_html__( ' Widget not Downloaded', 'wdesignkit' ),
5104 );
5105
5106 wp_send_json( $result );
5107 wp_die();
5108 }
5109
5110 $response = json_decode( wp_json_encode( $response['data'] ), true );
5111
5112 if ( empty( $response ) || empty( $response['data'] ) ) {
5113 $message = ! empty( $response['message'] ) ? $response['message'] : 'No Response Found';
5114 $description = ! empty( $response['description'] ) ? $response['description'] : 'Widget not Downloaded';
5115
5116 $result = (object) array(
5117 'success' => false,
5118 'message' => esc_html( $message ),
5119 'description' => esc_html( $description ),
5120 );
5121
5122 wp_send_json( $result );
5123 wp_die();
5124 }
5125
5126 $img_url = ! empty( $response['data']['image'] ) ? $response['data']['image'] : '';
5127 $json_data = ! empty( $response['data']['json'] ) ? json_decode( $response['data']['json'], true ) : '';
5128
5129 // Bug E fix (part 1): $responce was a typo of $response — sent undefined variable (null) to frontend.
5130 if ( empty( $response['success'] ) ) {
5131 wp_send_json( $response );
5132 wp_die();
5133 }
5134
5135 if ( empty( $img_url ) && empty( $json_data ) ) {
5136 $responce = (object) array(
5137 'success' => false,
5138 'message' => esc_html__( 'No Response Found', 'wdesignkit' ),
5139 'description' => esc_html__( 'Widget not Downloaded', 'wdesignkit' ),
5140 );
5141
5142 wp_send_json( $responce );
5143 wp_die();
5144 }
5145
5146 include_once ABSPATH . 'wp-admin/includes/file.php';
5147 \WP_Filesystem();
5148 global $wp_filesystem;
5149
5150 if ( ! is_array( $json_data ) ) {
5151 $json_data = json_decode( $json_data, true );
5152 }
5153
5154 $title = ! empty( $json_data['widget_data']['widgetdata']['name'] ) ? sanitize_text_field( $json_data['widget_data']['widgetdata']['name'] ) : '';
5155 $builder = ! empty( $json_data['widget_data']['widgetdata']['type'] ) ? sanitize_text_field( $json_data['widget_data']['widgetdata']['type'] ) : '';
5156 $w_uniq = ! empty( $json_data['widget_data']['widgetdata']['widget_id'] ) ? sanitize_text_field( $json_data['widget_data']['widgetdata']['widget_id'] ) : '';
5157
5158 $folder_name = str_replace( ' ', '-', $title ) . '_' . $w_uniq;
5159 $file_name = str_replace( ' ', '_', $title ) . '_' . $w_uniq;
5160 $builder_type_path = WDKIT_BUILDER_PATH . "/{$builder}/";
5161
5162 if ( ! is_dir( $builder_type_path ) ) {
5163 wp_mkdir_p( $builder_type_path );
5164 }
5165
5166 if ( ! is_dir( $builder_type_path . $folder_name ) ) {
5167 wp_mkdir_p( $builder_type_path . $folder_name );
5168 }
5169
5170 if ( ! empty( $img_url ) ) {
5171 $img_body = wp_remote_get( $img_url );
5172 $img_ext = pathinfo( $img_url )['extension'];
5173
5174 $wp_filesystem->put_contents( WDKIT_BUILDER_PATH . "/$builder/$folder_name/$file_name.$img_ext", $img_body['body'] );
5175 $json_data['widget_data']['widgetdata']['w_image'] = WDKIT_SERVER_PATH . "/$builder/$folder_name/$file_name.$img_ext";
5176 }
5177
5178 // Bug E fix (part 2): success was hardcoded false on the successful download path — always reported failure.
5179 $result = (object) array(
5180 'success' => true,
5181 'message' => ! empty( $response['message'] ) ? $response['message'] : esc_html__( 'no message', 'wdesignkit' ),
5182 'description' => '',
5183 'json' => wp_json_encode( $json_data ),
5184 );
5185
5186 wp_send_json( $result );
5187 wp_die();
5188 }
5189
5190 /**
5191 *
5192 * It is Use for sync widget to server
5193 *
5194 * @since 1.0.0
5195 */
5196 protected function wdkit_add_widget() {
5197 $data = ! empty( $_POST['widget_info'] ) ? $this->wdkit_sanitizer_bypass( $_POST, 'widget_info', 'none' ) : '';
5198 $data = base64_decode( $data );
5199 $data = json_decode( $data );
5200
5201 $title = isset( $data->title ) ? sanitize_text_field( $data->title ) : '';
5202 $builder = isset( $data->builder ) ? sanitize_text_field( $data->builder ) : '';
5203 $w_uniq = isset( $data->w_uniq ) ? sanitize_text_field( $data->w_uniq ) : '';
5204 $w_image = isset( $data->w_image ) ? esc_url_raw( $data->w_image ) : '';
5205
5206 if ( ! empty( $w_image ) ) {
5207 $w_image = str_replace( '\\', '', $w_image );
5208 $w_image = wp_remote_get( $w_image )['body'];
5209 }
5210
5211 $array_data = array(
5212 'token' => isset( $data->token ) ? sanitize_text_field( $data->token ) : '',
5213 'type' => isset( $data->type ) ? sanitize_text_field( $data->type ) : '',
5214 'title' => isset( $data->title ) ? sanitize_text_field( $data->title ) : '',
5215 'content' => isset( $data->content ) ? sanitize_text_field( $data->content ) : '',
5216 'builder' => isset( $data->builder ) ? sanitize_text_field( $data->builder ) : '',
5217 'w_data' => isset( $data->w_data ) ? $data->w_data : '',
5218 'w_unique' => isset( $data->w_uniq ) ? sanitize_text_field( $data->w_uniq ) : '',
5219 'w_image' => $w_image,
5220 'w_imgext' => isset( $data->w_imgext ) ? sanitize_text_field( $data->w_imgext ) : '',
5221 'w_version' => isset( $data->w_version ) ? $data->w_version : '',
5222 'w_updates' => ! empty( $data->w_updates ) ? serialize( $data->w_updates ) : serialize( array() ),
5223 'r_id' => isset( $data->r_id ) ? $data->r_id : 0,
5224 'unique_id' => get_option( 'wdkit_unique_id' ) ?? '',
5225 );
5226
5227 $response = $this->wkit_api_call( $array_data, 'save_widget' );
5228 $success = ! empty( $response['success'] ) ? $response['success'] : false;
5229
5230 if ( empty( $success ) ) {
5231 $massage = ! empty( $response['massage'] ) ? $response['massage'] : esc_html__( 'server error', 'wdesignkit' );
5232
5233 $result = (object) array(
5234 'success' => false,
5235 'message' => $massage,
5236 'description' => esc_html__( 'Widget Not Added', 'wdesignkit' ),
5237 );
5238
5239 wp_send_json( $result );
5240 wp_die();
5241 }
5242
5243 $res = ! empty( $response['data'] ) ? $response['data'] : array();
5244
5245 $response = json_decode( wp_json_encode( $res ), true );
5246 $img_url = ! empty( $response['data']['imgurl'] ) ? $response['data']['imgurl'] : '';
5247
5248 if ( ! empty( $img_url ) && 'error' !== $res ) {
5249
5250 $img_body = wp_remote_get( $img_url );
5251 $img_ext = pathinfo( $img_url )['extension'];
5252 include_once ABSPATH . 'wp-admin/includes/file.php';
5253 \WP_Filesystem();
5254 global $wp_filesystem;
5255 $folder_name = str_replace( ' ', '-', $title ) . '_' . $w_uniq;
5256 $file_name = str_replace( ' ', '_', $title ) . '_' . $w_uniq;
5257 $file_path = WDKIT_BUILDER_PATH . "/$builder/$folder_name/$file_name";
5258
5259 $u_r_l = wp_json_file_decode( "$file_path.json" );
5260 $u_r_l->widget_data->widgetdata->w_image = WDKIT_SERVER_PATH . "/$builder/$folder_name/$file_name.$img_ext";
5261
5262 $wp_filesystem->put_contents( "$file_path.json", wp_json_encode( $u_r_l ) );
5263 $wp_filesystem->put_contents( "$file_path.$img_ext", $img_body['body'] );
5264 }
5265
5266 wp_send_json( $response );
5267 wp_die();
5268 }
5269
5270 /**
5271 *
5272 * It is Use for manage favourite widget
5273 *
5274 * @since 1.0.0
5275 */
5276 protected function wdkit_favourite_widget() {
5277 $data = isset( $_POST['widget_info'] ) ? json_decode( stripslashes( sanitize_text_field( wp_unslash( $_POST['widget_info'] ) ) ) ) : '';
5278 $array_data = array(
5279 'token' => isset( $data->token ) ? sanitize_text_field( $data->token ) : '',
5280 'type' => isset( $data->type ) ? sanitize_text_field( $data->type ) : '',
5281 'w_unique' => isset( $data->w_uniq ) ? sanitize_text_field( $data->w_uniq ) : '',
5282 );
5283
5284 $response = $this->wkit_api_call( $array_data, 'save_widget' );
5285 $success = ! empty( $response['success'] ) ? $response['success'] : false;
5286
5287 if ( empty( $success ) ) {
5288 $massage = ! empty( $response['massage'] ) ? $response['massage'] : esc_html__( 'server error', 'wdesignkit' );
5289
5290 $result = (object) array(
5291 'success' => false,
5292 'message' => $massage,
5293 'description' => '',
5294 );
5295
5296 wp_send_json( $result );
5297 wp_die();
5298 }
5299
5300 wp_send_json( $response );
5301 wp_die();
5302 }
5303
5304 /**
5305 * It is Used Setting Panel Defalut Data Get.
5306 *
5307 * @since 1.0.0
5308 */
5309 protected function wdkit_setting_panel() {
5310 $event = ! empty( $_POST['event'] ) ? sanitize_text_field( wp_unslash( $_POST['event'] ) ) : 'get';
5311
5312 if ( 'get' === $event ) {
5313 return self::wkit_get_settings_panel();
5314 } elseif ( 'set' === $event ) {
5315 $data = ! empty( $_POST['data'] ) ? stripslashes( sanitize_text_field( wp_unslash( $_POST['data'] ) ) ) : array();
5316
5317 $data = json_decode( $data, true );
5318
5319 update_option( 'wkit_settings_panel', $data );
5320 return self::wkit_get_settings_panel();
5321 } else {
5322 return false;
5323 }
5324 }
5325
5326 /**
5327 * Get Setting Panal Data
5328 *
5329 * @since 1.0.0
5330 */
5331 protected static function wkit_get_settings_panel() {
5332 $new_version = '';
5333 $current_version = WDKIT_VERSION;
5334 $response = wp_remote_get( 'https://api.wordpress.org/plugins/info/1.0/wdesignkit.json' );
5335
5336 if ( is_wp_error( $response ) ) {
5337 return false;
5338 }
5339
5340 $body = wp_remote_retrieve_body( $response );
5341 $data = json_decode( $body );
5342
5343 if ( isset( $data->version ) ) {
5344 $new_version = $data->version;
5345 }
5346
5347 $version_check = array();
5348
5349 if ( $new_version && version_compare( $current_version, $new_version, '<' ) ) {
5350 $version_check['success'] = true;
5351 $version_check['version'] = $new_version;
5352 } else {
5353 $version_check['success'] = false;
5354 $version_check['version'] = $new_version;
5355 }
5356
5357 $get_setting = get_option( 'wkit_settings_panel', false );
5358
5359 $setting_data = array(
5360 'builder' => isset( $get_setting['builder'] ) ? $get_setting['builder'] : true,
5361 'template' => isset( $get_setting['template'] ) ? $get_setting['template'] : true,
5362 'gutenberg_builder' => isset( $get_setting['gutenberg_builder'] ) ? $get_setting['gutenberg_builder'] : true,
5363 'gutenberg_core_builder' => isset( $get_setting['gutenberg_core_builder'] ) ? $get_setting['gutenberg_core_builder'] : false,
5364 'elementor_builder' => isset( $get_setting['elementor_builder'] ) ? $get_setting['elementor_builder'] : true,
5365 'bricks_builder' => isset( $get_setting['bricks_builder'] ) ? $get_setting['bricks_builder'] : false,
5366 'gutenberg_template' => isset( $get_setting['gutenberg_template'] ) ? $get_setting['gutenberg_template'] : true,
5367 'elementor_template' => isset( $get_setting['elementor_template'] ) ? $get_setting['elementor_template'] : true,
5368 'code_snippet' => isset( $get_setting['code_snippet'] ) ? $get_setting['code_snippet'] : true,
5369 'cross_copy_paste' => isset( $get_setting['cross_copy_paste'] ) ? $get_setting['cross_copy_paste'] : false,
5370 'cross_copy_paste_elementor' => isset( $get_setting['cross_copy_paste_elementor'] ) ? $get_setting['cross_copy_paste_elementor'] : false,
5371 'cross_copy_paste_gutenberg' => isset( $get_setting['cross_copy_paste_gutenberg'] ) ? $get_setting['cross_copy_paste_gutenberg'] : false,
5372 'cross_copy_paste_bricks' => isset( $get_setting['cross_copy_paste_bricks'] ) ? $get_setting['cross_copy_paste_bricks'] : false,
5373 'plugin_version' => $version_check,
5374 );
5375
5376 if ( isset( $get_setting['remove_db'] ) ) {
5377 $setting_data['remove_db'] = $get_setting['remove_db'];
5378 }
5379
5380 if ( isset( $get_setting['debugger_mode'] ) ) {
5381 $setting_data['debugger_mode'] = $get_setting['debugger_mode'];
5382 }
5383
5384 return $setting_data;
5385 }
5386
5387 /**
5388 * Updated White Label Data.
5389 *
5390 * @since 1.1.8
5391 */
5392 protected function wkit_white_label() {
5393
5394 $get_wl_data = ! empty( $_POST['WhiteLabelData'] ) ? wp_unslash( $_POST['WhiteLabelData'] ) : array();
5395
5396 if ( ! empty( $get_wl_data ) ) {
5397 $white_label_data = json_decode( $get_wl_data, true );
5398 $plugin_name = $white_label_data['plugin_name'];
5399 } else {
5400 $result = array(
5401 'success' => false,
5402 'message' => esc_html__( 'Data Not Found', 'wdesignkit' ),
5403 );
5404
5405 wp_send_json( $result );
5406 wp_die();
5407 }
5408
5409 if ( ! empty( $plugin_name ) ) {
5410 $get_white_label = get_option( 'wkit_white_label', false );
5411 if ( ! empty( $get_white_label ) ) {
5412 update_option( 'wkit_white_label', $white_label_data );
5413 } else {
5414 add_option( 'wkit_white_label', $white_label_data );
5415 }
5416 } else {
5417 $result = array(
5418 'success' => false,
5419 'message' => esc_html__( 'Plugin Name Not Found', 'wdesignkit' ),
5420 );
5421
5422 wp_send_json( $result );
5423 wp_die();
5424 }
5425
5426 $get_updated_data = get_option( 'wkit_white_label', false );
5427 $response = array(
5428 'message' => __( 'Data Added successfully', 'wdesignkit' ),
5429 'success' => true,
5430 'data' => $get_updated_data,
5431 );
5432
5433 wp_send_json( $response );
5434 }
5435
5436 /**
5437 * Reset White Label Data.
5438 *
5439 * @since 1.1.8
5440 */
5441 public function wkit_reset_wl() {
5442 $wl_data = get_option( 'wkit_white_label' );
5443
5444 if ( ! empty( $wl_data ) ) {
5445 delete_option( 'wkit_white_label' );
5446
5447 $result = array(
5448 'success' => true,
5449 'message' => esc_html__( 'Reset White Label Successfully', 'wdesignkit' ),
5450 );
5451
5452 wp_send_json( $result );
5453 wp_die();
5454 }
5455 }
5456
5457 /**
5458 *
5459 * Use for Add new licence key.
5460 *
5461 * @since 1.0.0
5462 */
5463 protected function wdkit_activate_licence() {
5464 $args = array(
5465 'token' => ! empty( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : '',
5466 'licencekey' => ! empty( $_POST['licencekey'] ) ? sanitize_text_field( wp_unslash( $_POST['licencekey'] ) ) : '',
5467 'licencename' => ! empty( $_POST['licencename'] ) ? sanitize_text_field( wp_unslash( $_POST['licencename'] ) ) : '',
5468 'uichemyid' => ! empty( $_POST['uichemyid'] ) ? sanitize_text_field( wp_unslash( $_POST['uichemyid'] ) ) : '',
5469 );
5470
5471 $response = $this->wkit_api_call( $args, 'wkit_activate_key' );
5472
5473 if ( ! empty( $response['data'] ) ) {
5474 $response = json_decode( wp_json_encode( $response['data'] ), true );
5475
5476 if ( ! empty( $response['data']['tpae_licence'] ) && is_serialized( $response['data']['tpae_licence'] ) ) {
5477 $response['data']['tpae_licence'] = unserialize( $response['data']['tpae_licence'] );
5478 }
5479
5480 if ( ! empty( $response['data']['tpag_licence'] ) && is_serialized( $response['data']['tpag_licence'] ) ) {
5481 $response['data']['tpag_licence'] = unserialize( $response['data']['tpag_licence'] );
5482 }
5483
5484 if ( ! empty( $response['data']['uichemy_licence'] ) && is_serialized( $response['data']['uichemy_licence'] ) ) {
5485 $response['data']['uichemy_licence'] = unserialize( $response['data']['uichemy_licence'] );
5486 }
5487
5488 if ( ! empty( $response['data']['wdkit_licence'] ) && is_serialized( $response['data']['wdkit_licence'] ) ) {
5489 $response['data']['wdkit_licence'] = unserialize( $response['data']['wdkit_licence'] );
5490
5491 // Store WDesignKit license status locally for quick access
5492 if ( ! empty( $response['data']['wdkit_licence'] ) && is_array( $response['data']['wdkit_licence'] ) ) {
5493 update_option( 'wdkit_licence_data', $response['data']['wdkit_licence'] );
5494 }
5495 }
5496
5497 if ( ! empty( $response['data']['wdkit_licence_extra'] ) && is_serialized( $response['data']['wdkit_licence_extra'] ) ) {
5498 $response['data']['wdkit_licence_extra'] = unserialize( $response['data']['wdkit_licence_extra'] );
5499 }
5500 }
5501
5502 wp_send_json( $response );
5503 wp_die();
5504 }
5505
5506 /**
5507 *
5508 * Use for Delete licence key.
5509 *
5510 * @since 1.0.0
5511 */
5512 protected function wdkit_delete_licence_key() {
5513 $token = ! empty( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : '';
5514 $licencename = ! empty( $_POST['licencename'] ) ? sanitize_text_field( wp_unslash( $_POST['licencename'] ) ) : '';
5515 $apikey = ! empty( $_POST['apikey'] ) ? sanitize_text_field( wp_unslash( $_POST['apikey'] ) ) : '';
5516
5517 $args = array(
5518 'token' => $token,
5519 'licencename' => $licencename,
5520 'apikey' => $apikey,
5521 );
5522
5523 $response = $this->wkit_api_call( $args, 'licence_delete' );
5524
5525 // Remove local WDesignKit license data if deleting WDesignKit license
5526 if ( 'wdkit' === $licencename ) {
5527 delete_option( 'wdkit_licence_data' );
5528 }
5529
5530 wp_send_json( $response['data'] );
5531 wp_die();
5532 }
5533
5534 /**
5535 *
5536 * Use for Sync licence key.
5537 *
5538 * @since 1.0.0
5539 */
5540 protected function wdkit_sync_licence_key() {
5541 $token = ! empty( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : '';
5542 $licencename = ! empty( $_POST['licencename'] ) ? sanitize_text_field( wp_unslash( $_POST['licencename'] ) ) : '';
5543 // Needed to identify which extra-credit key to sync (wdkit_extra / wdkit_ai_extra
5544 // are arrays matched by the api key's last digits on the server).
5545 $apikey = ! empty( $_POST['apikey'] ) ? sanitize_text_field( wp_unslash( $_POST['apikey'] ) ) : '';
5546
5547 $args = array(
5548 'token' => $token,
5549 'licencename' => $licencename,
5550 'apikey' => $apikey,
5551 );
5552
5553 $response = $this->wkit_api_call( $args, 'licence_sync' );
5554
5555 wp_send_json( $response['data'] );
5556 wp_die();
5557 }
5558
5559 /**
5560 * Rollback to Previous Versions
5561 *
5562 * @since 1.1.0
5563 */
5564 protected function wdkit_prev_version() {
5565
5566 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
5567
5568 $plugin_info = plugins_api(
5569 'plugin_information',
5570 array(
5571 'slug' => 'wdesignkit',
5572 )
5573 );
5574
5575 if ( empty( $plugin_info->versions ) || ! is_array( $plugin_info->versions ) ) {
5576 return array();
5577 }
5578
5579 krsort( $plugin_info->versions );
5580
5581 $versions_list = array();
5582 $index = 0;
5583
5584 foreach ( $plugin_info->versions as $version => $download_link ) {
5585
5586 $lowercase_version = strtolower( $version );
5587
5588 $is_valid_version = ! preg_match( '/(beta|rc|trunk|dev)/i', $lowercase_version );
5589
5590 $is_valid_version = apply_filters( 'wdkit_check_rollback_version', $is_valid_version, $lowercase_version );
5591
5592 if ( ! $is_valid_version || version_compare( $version, WDKIT_VERSION, '>=' ) ) {
5593 continue;
5594 }
5595
5596 $versions_list[] = $version;
5597 ++$index;
5598 }
5599
5600 // set_transient( 'wdkit_rollback_version_' . WDKIT_VERSION, $versions_list, WEEK_IN_SECONDS );
5601
5602 return $versions_list;
5603 }
5604
5605 /**
5606 * Rollback to Previous Versions
5607 *
5608 * @since 1.1.0
5609 */
5610 protected function wdkit_rollback_check() {
5611
5612 $current_ver = isset( $_POST['version'] ) ? sanitize_text_field( wp_unslash( $_POST['version'] ) ) : '';
5613 $rv = $this->wdkit_prev_version();
5614
5615 if ( empty( $current_ver ) || ! in_array( $current_ver, $rv ) ) {
5616 return array(
5617 'message' => esc_html__( 'Invalid Nonce or version not found', 'wdesignkit' ),
5618 'status' => 'error',
5619 'success' => false,
5620 );
5621 }
5622
5623 $plugin_slug = basename( WDKIT_PBNAME, '.php' );
5624
5625 $this_version = $current_ver;
5626 $this_pluginname = WDKIT_PBNAME;
5627 $this_plugin_u_r_l = sprintf( 'https://downloads.wordpress.org/plugin/%s.%s.zip', $plugin_slug, $this_version );
5628
5629 $plugin_info = new \stdClass();
5630 $plugin_info->new_version = $this_version;
5631 $plugin_info->slug = $plugin_slug;
5632 $plugin_info->package = $this_plugin_u_r_l;
5633 $plugin_info->url = 'https://wdesignkit.com/';
5634
5635 $update_plugins_data = get_site_transient( 'update_plugins' );
5636
5637 if ( ! is_object( $update_plugins_data ) ) {
5638 $update_plugins_data = new \stdClass();
5639 }
5640
5641 $update_plugins_data->response[ $this_pluginname ] = $plugin_info;
5642
5643 set_site_transient( 'update_plugins', $update_plugins_data );
5644
5645 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
5646
5647 $logo_url = WDKIT_URL . 'assets/images/jpg/Wdesignkit-logo.png';
5648
5649 $args = array(
5650 'url' => 'update.php?action=upgrade-plugin&plugin=' . rawurlencode( $this_pluginname ),
5651 'plugin' => $this_pluginname,
5652 'nonce' => 'upgrade-plugin_' . $this_pluginname,
5653 'title' => '<img src="' . esc_url( $logo_url ) . '" alt="wdesignkit-logo"><div class="theplus-rb-subtitle">' . esc_html__( 'Rollback to Previous Version', 'wdesignkit' ) . '</div>',
5654 );
5655
5656 $upgrader_plugin = new \Plugin_Upgrader( new \Plugin_Upgrader_Skin( $args ) );
5657 $upgrader_plugin->upgrade( $this_pluginname );
5658
5659 activate_plugin( $this_pluginname );
5660
5661 return array(
5662 'message' => esc_html__( 'Rollback Successful, Plugin Re-activated', 'wdesignkit' ),
5663 'status' => 'Success',
5664 'success' => true,
5665 );
5666 }
5667
5668 /**
5669 *
5670 * It is Use for logout.
5671 *
5672 * @since 1.0.0
5673 */
5674 protected function wdkit_logout() {
5675 $email = isset( $_POST['email'] ) ? strtolower( sanitize_email( wp_unslash( $_POST['email'] ) ) ) : false;
5676 $logout_type = isset( $_POST['logout_type'] ) ? strtolower( sanitize_text_field( wp_unslash( $_POST['logout_type'] ) ) ) : '';
5677
5678 $response = '';
5679
5680 if ( ! empty( $email ) ) {
5681 $token = $this->wdkit_login_user_token( $email );
5682 $args = array( 'token' => $token );
5683
5684 if ( 'session' !== $logout_type ) {
5685 delete_transient( 'wdkit_auth_' . $email );
5686 // Clear stored license data on logout so banner shows again
5687 delete_option( 'wdkit_licence_data' );
5688 $response = WDesignKit_Data_Query::get_data( 'logout', $args );
5689 }
5690 }
5691
5692 wp_send_json( $response );
5693 wp_die();
5694 }
5695
5696 /**
5697 *
5698 * It is Use for get token of login user.
5699 *
5700 * @since 1.0.0
5701 *
5702 * @param string $email check user email.
5703 */
5704 protected function wdkit_login_user_token( $email = '' ) {
5705
5706 if ( ! empty( $email ) ) {
5707 $user_key = strstr( $email, '@', true );
5708 $get_login = get_transient( 'wdkit_auth_' . $user_key );
5709
5710 if ( ! empty( $get_login ) && ! empty( $get_login['token'] ) ) {
5711 return $get_login['token'];
5712 }
5713 }
5714
5715 return false;
5716 }
5717
5718 /**
5719 * Parse args $_POST
5720 *
5721 * @since 1.0.0
5722 *
5723 * @param string $data send all post data.
5724 * @param string $type store text data.
5725 * @param string $condition store text data.
5726 */
5727 protected function wdkit_sanitizer_bypass( $data, $type, $condition = 'none' ) {
5728
5729 if ( 'none' === $condition ) {
5730 return $data[ $type ];
5731 } elseif ( 'cr_widget' === $condition ) {
5732 return $data[ $type ];
5733 }
5734 }
5735
5736
5737 /**
5738 * Parse args $_POST
5739 *
5740 * @since 1.0.0
5741 *
5742 * @param string $data send all post data.
5743 */
5744 protected function wdkit_parse_args( $data = array() ) {
5745 if ( empty( $data ) ) {
5746 return array();
5747 }
5748
5749 $args = array();
5750 if ( isset( $data['email'] ) ) {
5751 $args['email'] = isset( $data['email'] ) ? sanitize_email( $data['email'] ) : '';
5752 }
5753
5754 if ( isset( $data['data'] ) ) {
5755 $args['data'] = isset( $data['data'] ) ? wp_unslash( $data['data'] ) : array();
5756 }
5757
5758 if ( isset( $data['plugins'] ) ) {
5759 $args['plugins'] = isset( $data['plugins'] ) ? wp_unslash( $data['plugins'] ) : array();
5760 }
5761
5762 if ( isset( $data['template_id'] ) ) {
5763 $args['template_id'] = isset( $data['template_id'] ) ? intval( strtolower( sanitize_text_field( $data['template_id'] ) ) ) : '';
5764 }
5765
5766 if ( isset( $data['builder'] ) ) {
5767 $args['builder'] = isset( $data['builder'] ) ? wp_unslash( $data['builder'] ) : '';
5768 }
5769
5770 if ( isset( $data['editor'] ) ) {
5771 $args['editor'] = isset( $data['editor'] ) ? sanitize_text_field( $data['editor'] ) : '';
5772 }
5773
5774 if ( isset( $data['type_upload'] ) ) {
5775 $args['type_upload'] = isset( $data['type_upload'] ) ? sanitize_text_field( $data['type_upload'] ) : '';
5776 }
5777
5778 if ( isset( $data['title'] ) ) {
5779 $args['title'] = isset( $data['title'] ) ? wp_strip_all_tags( $data['title'] ) : '';
5780 }
5781
5782 if ( isset( $data['template_type'] ) ) {
5783 $args['template_type'] = isset( $data['template_type'] ) ? sanitize_text_field( $data['template_type'] ) : '';
5784 }
5785
5786 if ( isset( $data['wstype'] ) ) {
5787 $args['wstype'] = isset( $data['wstype'] ) ? wp_strip_all_tags( $data['wstype'] ) : '';
5788 }
5789
5790 if ( isset( $data['wid'] ) ) {
5791 $args['wid'] = isset( $data['wid'] ) ? intval( strtolower( sanitize_text_field( $data['wid'] ) ) ) : '';
5792 }
5793
5794 if ( isset( $data['perpage'] ) ) {
5795 $args['perpage'] = isset( $data['perpage'] ) ? intval( strtolower( sanitize_text_field( $data['perpage'] ) ) ) : 12;
5796 }
5797
5798 if ( isset( $data['page'] ) ) {
5799 $args['page'] = isset( $data['page'] ) ? intval( strtolower( sanitize_text_field( $data['page'] ) ) ) : 1;
5800 }
5801
5802 if ( isset( $data['buildertype'] ) ) {
5803 $args['buildertype'] = isset( $data['buildertype'] ) ? sanitize_text_field( $data['buildertype'] ) : '';
5804 }
5805
5806 if ( isset( $data['search'] ) ) {
5807 $args['search'] = isset( $data['search'] ) ? sanitize_text_field( $data['search'] ) : '';
5808 }
5809
5810 if ( isset( $data['plugin'] ) ) {
5811 $args['plugin'] = isset( $data['plugin'] ) ? wp_unslash( $data['plugin'] ) : array();
5812 }
5813
5814 if ( isset( $data['plugin_exclude'] ) ) {
5815 $args['plugin_exclude'] = isset( $data['plugin_exclude'] ) ? wp_unslash( $data['plugin_exclude'] ) : array();
5816 }
5817
5818 if ( isset( $data['ai_compatibility'] ) ) {
5819 $args['ai_compatibility'] = isset( $data['ai_compatibility'] ) ? wp_unslash( $data['ai_compatibility'] ) : array();
5820 }
5821
5822 // if ( isset( $data['global_color'] ) ) {
5823 // $args['global_color'] = isset( $data['global_color'] ) ? wp_unslash( $data['global_color'] ) : array();
5824 // }
5825
5826 // if ( isset( $data['global_font_family'] ) ) {
5827 // $args['global_font_family'] = isset( $data['global_font_family'] ) ? wp_unslash( $data['global_font_family'] ) : array();
5828 // }
5829
5830 if ( isset( $data['global_data'] ) ) {
5831 $args['global_data'] = isset( $data['global_data'] ) ? wp_unslash( $data['global_data'] ) : array();
5832 }
5833
5834 if ( isset( $data['tag'] ) ) {
5835 $args['tag'] = isset( $data['tag'] ) ? wp_unslash( $data['tag'] ) : array();
5836 }
5837
5838 if ( isset( $data['category'] ) ) {
5839 $args['category'] = isset( $data['category'] ) ? wp_unslash( $data['category'] ) : array();
5840 }
5841
5842 if ( isset( $data['free_pro'] ) ) {
5843 $args['free_pro'] = isset( $data['free_pro'] ) ? sanitize_text_field( wp_unslash( $data['free_pro'] ) ) : '';
5844 }
5845
5846 if ( isset( $data['wp_post_type'] ) ) {
5847 $args['wp_post_type'] = isset( $data['wp_post_type'] ) ? sanitize_text_field( wp_unslash( $data['wp_post_type'] ) ) : '';
5848 }
5849
5850 if ( isset( $data['favorite'] ) ) {
5851 $args['favorite'] = isset( $data['favorite'] ) ? sanitize_text_field( wp_unslash( $data['favorite'] ) ) : '';
5852 }
5853
5854 if ( isset( $data['content'] ) ) {
5855 $args['content'] = isset( $data['content'] ) ? wp_unslash( $data['content'] ) : '';
5856 }
5857
5858 if ( isset( $data['page_type'] ) ) {
5859 $args['page_type'] = isset( $data['page_type'] ) ? wp_unslash( $data['page_type'] ) : array();
5860 }
5861
5862 return $args;
5863 }
5864
5865 /**
5866 * Dark Mode
5867 *
5868 * @since 2.0.0
5869 *
5870 * @param string store darkmode value in database.
5871 */
5872 protected function wdkit_dark_mode() {
5873 $dark_mode = ! empty( $_POST['dark_mode'] ) ? sanitize_text_field( $_POST['dark_mode'] ) : 'light';
5874
5875 if ( get_option( 'wdkit_dark_mode' ) ) {
5876 update_option( 'wdkit_dark_mode', $dark_mode );
5877 } else {
5878 add_option( 'wdkit_dark_mode', $dark_mode );
5879 }
5880
5881 $response = array(
5882 'message' => esc_html__( 'Dark Mode Updated', 'wdesignkit' ),
5883 'status' => 'Success',
5884 'success' => true,
5885 );
5886
5887 wp_send_json( $response );
5888 wp_die();
5889 }
5890 }
5891
5892 Wdkit_Api_Call::get_instance();
5893 }
5894