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

admin-settings.php in Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets 4.1.4, at admin/admin-settings.php

4,195 lines 157.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use UltimatePostKit\Notices;
4 use UltimatePostKit\Utils;
5 use UltimatePostKit\Admin\ModuleService;
6 use Elementor\Modules\Usage\Module;
7 use Elementor\Tracker;
8
9
10 /**
11 * Ultimate Post Kit Admin Settings Class
12 */
13
14 class UltimatePostKit_Admin_Settings {
15
16 public static $modules_list = null;
17 public static $modules_names = null;
18
19 public static $modules_list_only_widgets = null;
20 public static $modules_names_only_widgets = null;
21
22 public static $modules_list_only_3rdparty = null;
23 public static $modules_names_only_3rdparty = null;
24
25 const PAGE_ID = 'ultimate_post_kit_options';
26
27 private $settings_api;
28
29 public $responseObj;
30 public $licenseMessage;
31 public $showMessage = false;
32 private $is_activated = false;
33
34 /**
35 * Rollback version instance
36 *
37 * @var Rollback_Version
38 */
39 public $rollback_version;
40
41 function __construct() {
42 $this->settings_api = new UltimatePostKit_Settings_API;
43
44 if (!defined('BDTUPK_HIDE')) {
45 add_action('admin_init', [$this, 'admin_init']);
46 add_action('admin_menu', [$this, 'admin_menu'], 201);
47 }
48
49 // Handle white label access link
50 $this->handle_white_label_access();
51
52 // Add custom CSS/JS functionality
53 $this->init_custom_code_functionality();
54
55 // White label settings (admin only)
56 add_action( 'wp_ajax_upk_save_white_label', [ $this, 'save_white_label_ajax' ] );
57 add_action( 'wp_ajax_upk_revoke_white_label_token', [ $this, 'revoke_white_label_token_ajax' ] );
58 add_action( 'admin_head', [ $this, 'inject_white_label_icon_css' ] );
59
60 // Plugin installation (admin only)
61 add_action('wp_ajax_upk_install_plugin', [$this, 'install_plugin_ajax']);
62
63
64
65 if (_is_upk_pro_activated()) {
66 // Initialize rollback version functionality
67 add_action('admin_init', [$this, 'rollback_init']);
68 }
69
70 }
71
72 public function rollback_init() {
73 if ( class_exists('\UltimatePostKitPro\Rollback_Version') ) {
74 $this->rollback_version = new \UltimatePostKitPro\Rollback_Version();
75 }
76 }
77
78
79
80
81 /**
82 * Initialize Custom Code Functionality
83 *
84 * @access public
85 * @return void
86 */
87 public function init_custom_code_functionality() {
88 // AJAX handler for saving custom code (admin only)
89 add_action( 'wp_ajax_upk_save_custom_code', [ $this, 'save_custom_code_ajax' ] );
90
91
92 // Admin scripts (admin only)
93 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_custom_code_scripts' ] );
94
95 // Frontend injection is now handled by global functions in the main plugin file
96 self::init_frontend_injection();
97 }
98
99 /**
100 * Initialize frontend injection hooks (works on both admin and frontend)
101 *
102 * @access public static
103 * @return void
104 */
105 public static function init_frontend_injection() {
106 // Frontend hooks are now registered in the main plugin file
107 // This method is kept for backwards compatibility but does nothing
108 }
109
110 /**
111 * Enqueue scripts for custom code editor
112 *
113 * @access public
114 * @return void
115 */
116 public function enqueue_custom_code_scripts( $hook ) {
117 if ( $hook !== 'toplevel_page_ultimate_post_kit_options' ) {
118 return;
119 }
120
121 // Enqueue WordPress built-in CodeMirror
122 wp_enqueue_code_editor( array( 'type' => 'text/css' ) );
123 wp_enqueue_code_editor( array( 'type' => 'application/javascript' ) );
124
125 // Enqueue WordPress media library scripts
126 wp_enqueue_media();
127
128 // Enqueue the admin script if it exists
129 $admin_script_path = BDTUPK_ASSETS_PATH . 'js/upk-admin.js';
130 if ( file_exists( $admin_script_path ) ) {
131 wp_enqueue_script(
132 'upk-admin-script',
133 BDTUPK_ASSETS_URL . 'js/upk-admin.js',
134 [ 'jquery', 'media-upload', 'media-views', 'code-editor' ],
135 BDTUPK_VER,
136 true
137 );
138
139 // Localize script with AJAX data
140 wp_localize_script( 'upk-admin-script', 'upk_admin_ajax', [
141 'ajax_url' => admin_url( 'admin-ajax.php' ),
142 'nonce' => wp_create_nonce( 'upk_custom_code_nonce' ),
143 'white_label_nonce' => wp_create_nonce( 'upk_white_label_nonce' )
144 ] );
145 } else {
146 // Fallback: localize to jquery if the admin script doesn't exist
147 wp_localize_script( 'jquery', 'upk_admin_ajax', [
148 'ajax_url' => admin_url( 'admin-ajax.php' ),
149 'nonce' => wp_create_nonce( 'upk_custom_code_nonce' ),
150 'white_label_nonce' => wp_create_nonce( 'upk_white_label_nonce' )
151 ] );
152 }
153 }
154
155 /**
156 * AJAX handler for saving white label settings
157 *
158 * @access public
159 * @return void
160 */
161 public function save_white_label_ajax() {
162
163 // Check nonce and permissions
164 if (!wp_verify_nonce($_POST['nonce'], 'upk_white_label_nonce')) {
165 wp_send_json_error(['message' => __('Security check failed', 'ultimate-post-kit')]);
166 }
167
168 if (!current_user_can('manage_options')) {
169 wp_send_json_error(['message' => __('You do not have permission to manage white label settings', 'ultimate-post-kit')]);
170 }
171
172 // Check license eligibility
173 if (!self::is_white_label_license()) {
174 wp_send_json_error(['message' => __('Your license does not support white label features', 'ultimate-post-kit')]);
175 }
176
177 // Get white label settings
178 $white_label_enabled = isset($_POST['upk_white_label_enabled']) ? (bool) $_POST['upk_white_label_enabled'] : false;
179 $hide_license = isset($_POST['upk_white_label_hide_license']) ? (bool) $_POST['upk_white_label_hide_license'] : false;
180 $bdtupk_hide = isset($_POST['upk_white_label_bdtupk_hide']) ? (bool) $_POST['upk_white_label_bdtupk_hide'] : false;
181 $white_label_title = isset($_POST['upk_white_label_title']) ? sanitize_text_field($_POST['upk_white_label_title']) : '';
182 $white_label_icon = isset($_POST['upk_white_label_icon']) ? esc_url_raw($_POST['upk_white_label_icon']) : '';
183 $white_label_icon_id = isset($_POST['upk_white_label_icon_id']) ? absint($_POST['upk_white_label_icon_id']) : 0;
184 $white_label_logo = isset($_POST['upk_white_label_logo']) ? esc_url_raw($_POST['upk_white_label_logo']) : '';
185 $upk_white_label_logo_id = isset($_POST['upk_white_label_logo_id']) ? absint($_POST['upk_white_label_logo_id']) : 0;
186
187 // Save settings
188 update_option('upk_white_label_enabled', $white_label_enabled);
189 update_option('upk_white_label_hide_license', $hide_license);
190 update_option('upk_white_label_bdtupk_hide', $bdtupk_hide);
191 update_option('upk_white_label_title', $white_label_title);
192 update_option('upk_white_label_icon', $white_label_icon);
193 update_option('upk_white_label_icon_id', $white_label_icon_id);
194 update_option('upk_white_label_logo', $white_label_logo);
195 update_option('upk_white_label_logo_id', $upk_white_label_logo_id);
196
197 // Set license title status
198 if ($white_label_enabled) {
199 update_option('ultimate_post_kit_license_title_status', true);
200 } else {
201 delete_option('ultimate_post_kit_license_title_status');
202 }
203
204 // Only send access email if both white label mode AND BDTUPK_HIDE are enabled
205 if ($white_label_enabled && $bdtupk_hide) {
206 $email_sent = $this->send_white_label_access_email();
207 }
208
209 wp_send_json_success([
210 'message' => __('White label settings saved successfully', 'ultimate-post-kit'),
211 'bdtupk_hide' => $bdtupk_hide,
212 'email_sent' => isset($email_sent) ? $email_sent : false
213 ]);
214 }
215
216 /**
217 * Send white label access email with special link
218 *
219 * @access private
220 * @return bool
221 */
222 private function send_white_label_access_email() {
223
224 $license_email = self::get_license_email();
225 $admin_email = get_bloginfo( 'admin_email' );
226 $license_key = self::get_license_key();
227 $site_name = get_bloginfo( 'name' );
228 $site_url = get_bloginfo( 'url' );
229
230 // Generate secure access token with additional entropy
231 $access_token = wp_hash( $license_key . time() . wp_salt() . wp_generate_password( 32, false ) );
232
233 // Store access token in database with no expiration
234 $token_data = [
235 'token' => $access_token,
236 'license_key' => $license_key,
237 'created_at' => current_time( 'timestamp' ),
238 'user_id' => get_current_user_id()
239 ];
240
241 update_option( 'upk_white_label_access_token', $token_data );
242
243 // Generate access URL using token instead of license key for security
244 // Add white_label_tab=1 parameter to automatically switch to White Label tab
245 $access_url = admin_url( 'admin.php?page=ultimate_post_kit_options&upk_wl=1&token=' . $access_token . '&white_label_tab=1#ultimate_post_kit_extra_options' );
246
247 // Email subject
248 $subject = sprintf( '[%s] Ultimate Post Kit White Label Access Instructions', $site_name );
249
250 // Email message
251 $message = $this->get_white_label_email_template( $site_name, $site_url, $access_url, $license_key );
252
253 // Email headers
254 $headers = [
255 'Content-Type: text/html; charset=UTF-8',
256 'From: ' . $site_name . ' <' . $admin_email . '>'
257 ];
258
259 $email_sent = false;
260
261 // Send to license email
262 if ( ! empty( $license_email ) && is_email( $license_email ) ) {
263 $email_sent = wp_mail( $license_email, $subject, $message, $headers );
264
265 // If on localhost or email failed, save email content for manual access
266 if ( ! $email_sent || $this->is_localhost() ) {
267 $this->save_email_content_for_localhost( $access_url, $message, $license_email );
268 }
269 }
270
271 return $email_sent;
272 }
273
274 /**
275 * Check if running on localhost
276 *
277 * @access private
278 * @return bool
279 */
280 private function is_localhost() {
281 $server_name = $_SERVER['SERVER_NAME'] ?? '';
282 $server_addr = $_SERVER['SERVER_ADDR'] ?? '';
283
284 $localhost_indicators = [
285 'localhost',
286 '127.0.0.1',
287 '::1',
288 '.local',
289 '.test',
290 '.dev'
291 ];
292
293 foreach ( $localhost_indicators as $indicator ) {
294 if ( strpos( $server_name, $indicator ) !== false ||
295 strpos( $server_addr, $indicator ) !== false ) {
296 return true;
297 }
298 }
299
300 return false;
301 }
302
303 /**
304 * Save email content for localhost testing
305 *
306 * @access private
307 * @param string $access_url
308 * @param string $email_content
309 * @param string $recipient_email
310 * @return void
311 */
312 private function save_email_content_for_localhost( $access_url, $email_content, $recipient_email ) {
313 $email_data = [
314 'access_url' => $access_url,
315 'email_content' => $email_content,
316 'recipient_email' => $recipient_email,
317 'message' => 'Email functionality not available on localhost. Use the access URL below:'
318 ];
319
320 // Save for admin notice display
321 update_option( 'upk_localhost_email_data', $email_data );
322 }
323
324 /**
325 * Get white label email template
326 *
327 * @access private
328 * @param string $site_name
329 * @param string $site_url
330 * @param string $access_url
331 * @param string $license_key
332 * @return string
333 */
334 private function get_white_label_email_template( $site_name, $site_url, $access_url, $license_key ) {
335 $masked_license = substr( $license_key, 0, 8 ) . '****-****-****-' . substr( $license_key, -4 );
336
337 ob_start();
338 ?>
339 <!DOCTYPE html>
340 <html>
341 <head>
342 <meta charset="UTF-8">
343 <title>Ultimate Post Kit White Label Access</title>
344 <style>
345 body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
346 .container { max-width: 600px; margin: 0 auto; padding: 20px; }
347 .header { background: #2196F3; color: white; padding: 20px; text-align: center; border-radius: 8px 8px 0 0; }
348 .content { background: #f9f9f9; padding: 30px; border-radius: 0 0 8px 8px; }
349 .access-link { background: #2196F3; color: white; padding: 15px 25px; text-decoration: none; border-radius: 5px; display: inline-block; margin: 20px 0; }
350 .warning { background: #fff3cd; border: 1px solid #ffeaa7; padding: 15px; border-radius: 5px; margin: 20px 0; }
351 .footer { margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; font-size: 12px; color: #666; }
352 </style>
353 </head>
354 <body>
355 <div class="container">
356 <div class="header">
357 <h1>🔒 Ultimate Post Kit White Label Access</h1>
358 </div>
359 <div class="content">
360 <h2>Important: Save This Email!</h2>
361
362 <p>Hello,</p>
363
364 <p>You have successfully enabled <strong>BDTUPK_HIDE mode</strong> for Ultimate Post Kit Pro on <strong><?php echo esc_html( $site_name ); ?></strong>.</p>
365
366 <div class="warning">
367 <h3>⚠️ IMPORTANT</h3>
368 <p>The plugin interface is hidden from your WordPress admin. Use below link to modify white label settings.</p>
369
370 <p style="text-align: center;">
371 <a href="<?php echo esc_url( $access_url ); ?>" class="access-link">Access White Label Settings</a>
372 </p>
373 </div>
374
375 <p><strong>Direct Link:</strong><br>
376 <a href="<?php echo esc_url( $access_url ); ?>"><?php echo esc_html( $access_url ); ?></a></p>
377
378
379 <h3>🔧 What You Can Do</h3>
380 <p>Using the access link above, you can:</p>
381 <ul>
382 <li>Disable BDTUPK_HIDE mode</li>
383 <li>Modify white label settings</li>
384 </ul>
385
386 <p>Need help? <a href="https://bdthemes.com/support/" target="_blank">Contact support</a> with your license key.</p>
387
388 </div>
389 </div>
390 </body>
391 </html>
392 <?php
393 return ob_get_clean();
394 }
395
396 /**
397 * Handle white label access link
398 *
399 * @access private
400 * @return void
401 */
402 private function handle_white_label_access() {
403 // Check if this is a white label access request
404 if ( ! isset( $_GET['upk_wl'] ) || ! isset( $_GET['token'] ) ) {
405 return;
406 }
407
408 // Check user capability
409 if ( ! current_user_can( 'manage_options' ) ) {
410 wp_die( 'You do not have sufficient permissions to access this page.' );
411 }
412
413 $upk_wl = sanitize_text_field( $_GET['upk_wl'] );
414 $access_token = sanitize_text_field( $_GET['token'] );
415
416 // Check if upk_wl is set to 1
417 if ( $upk_wl !== '1' ) {
418 $this->show_access_error( 'Invalid access parameter. Please use the correct link from your email.' );
419 return;
420 }
421
422 // Validate the access token
423 if ( ! $this->validate_white_label_access_token( $access_token ) ) {
424 $this->show_access_error( 'Invalid or expired access token. Please use the correct access link from your email.' );
425 return;
426 }
427
428 // Valid access - temporarily allow access by setting a flag
429 add_action('admin_init', [$this, 'admin_init']);
430 add_action('admin_menu', [$this, 'admin_menu'], 201);
431
432 // Add success notice
433 add_action( 'admin_notices', function() {
434 echo '<div class="notice notice-success is-dismissible">';
435 echo '<p><strong>�
436 White Label Access Granted!</strong> You can now modify white label settings.</p>';
437 echo '</div>';
438 } );
439 }
440
441 /**
442 * Show access error page
443 *
444 * @access private
445 * @param string $message
446 * @return void
447 */
448 private function show_access_error( $message ) {
449 wp_die(
450 '<h1>🔒 Ultimate Post Kit White Label Access</h1>' .
451 '<p><strong>Access Denied:</strong> ' . esc_html( $message ) . '</p>' .
452 '<p>If you need assistance, please contact support with your license information.</p>' .
453 '<p><a href="' . admin_url() . '" class="button button-primary"> Return to Dashboard</a></p>',
454 'Access Denied',
455 [ 'response' => 403 ]
456 );
457 }
458
459 /**
460 * Inject white label icon CSS
461 *
462 * @access public
463 * @return void
464 */
465 public function inject_white_label_icon_css() {
466 $white_label_enabled = get_option('upk_white_label_enabled', false);
467 $white_label_icon = get_option('upk_white_label_icon', '');
468
469 // Only inject CSS when white label is enabled AND a custom icon is set
470 if ( $white_label_enabled && ! empty( $white_label_icon ) ) {
471 echo '<style type="text/css">';
472 echo '#toplevel_page_ultimate_post_kit_options .wp-menu-image {';
473 echo 'background-image: url(' . esc_url( $white_label_icon ) . ') !important;';
474 echo 'background-size: 20px 20px !important;';
475 echo 'background-repeat: no-repeat !important;';
476 echo 'background-position: center !important;';
477 echo '}';
478 echo '#toplevel_page_ultimate_post_kit_options .wp-menu-image:before {';
479 echo 'display: none !important;';
480 echo '}';
481 echo '#toplevel_page_ultimate_post_kit_options .wp-menu-image img {';
482 echo 'display: none !important;';
483 echo '}';
484 echo '</style>';
485 }
486 // When white label is disabled or no icon is set, don't inject any CSS
487 // This allows WordPress's original icon to display naturally
488 }
489
490 /**
491 * Get used widgets.
492 *
493 * @access public
494 * @return array
495 * @since 6.0.0
496 *
497 */
498 public static function get_used_widgets() {
499
500 $used_widgets = array();
501
502 if (class_exists('Elementor\Modules\Usage\Module')) {
503
504 $module = Module::instance();
505
506 $old_error_level = error_reporting();
507 error_reporting(E_ALL & ~E_WARNING); // Suppress warnings
508 $elements = $module->get_formatted_usage('raw');
509 error_reporting($old_error_level); // Restore
510
511 $upk_widgets = self::get_upk_widgets_names();
512
513 if (is_array($elements) || is_object($elements)) {
514
515 foreach ($elements as $post_type => $data) {
516 foreach ($data['elements'] as $element => $count) {
517 if (in_array($element, $upk_widgets, true)) {
518 if (isset($used_widgets[$element])) {
519 $used_widgets[$element] += $count;
520 } else {
521 $used_widgets[$element] = $count;
522 }
523 }
524 }
525 }
526 }
527 }
528
529 return $used_widgets;
530 }
531
532 /**
533 * Get used separate widgets.
534 *
535 * @access public
536 * @return array
537 * @since 6.0.0
538 *
539 */
540
541 public static function get_used_only_widgets() {
542
543 $used_widgets = array();
544
545 if (class_exists('Elementor\Modules\Usage\Module')) {
546
547 $module = Module::instance();
548
549 $old_error_level = error_reporting();
550 error_reporting(E_ALL & ~E_WARNING); // Suppress warnings
551 $elements = $module->get_formatted_usage('raw');
552 error_reporting($old_error_level); // Restore
553
554 $upk_widgets = self::get_upk_only_widgets();
555
556 if (is_array($elements) || is_object($elements)) {
557
558 foreach ($elements as $post_type => $data) {
559 foreach ($data['elements'] as $element => $count) {
560 if (in_array($element, $upk_widgets, true)) {
561 if (isset($used_widgets[$element])) {
562 $used_widgets[$element] += $count;
563 } else {
564 $used_widgets[$element] = $count;
565 }
566 }
567 }
568 }
569 }
570 }
571
572 return $used_widgets;
573 }
574
575 /**
576 * Get unused widgets.
577 *
578 * @access public
579 * @return array
580 * @since 6.0.0
581 *
582 */
583
584 public static function get_unused_widgets() {
585
586 if (!current_user_can('install_plugins')) {
587 die();
588 }
589
590 $upk_widgets = self::get_upk_widgets_names();
591
592 $used_widgets = self::get_used_widgets();
593
594 $unused_widgets = array_diff($upk_widgets, array_keys($used_widgets));
595
596 return $unused_widgets;
597 }
598
599 /**
600 * Get unused separate widgets.
601 *
602 * @access public
603 * @return array
604 * @since 6.0.0
605 *
606 */
607
608 public static function get_unused_only_widgets() {
609
610 if (!current_user_can('install_plugins')) {
611 die();
612 }
613
614 $upk_widgets = self::get_upk_only_widgets();
615
616 $used_widgets = self::get_used_only_widgets();
617
618 $unused_widgets = array_diff($upk_widgets, array_keys($used_widgets));
619
620 return $unused_widgets;
621 }
622
623 /**
624 * Get widgets name
625 *
626 * @access public
627 * @return array
628 * @since 6.0.0
629 *
630 */
631
632 public static function get_upk_widgets_names() {
633 $names = self::$modules_names;
634
635 if (null === $names) {
636 $names = array_map(
637 function ($item) {
638 return isset($item['name']) ? 'upk-' . str_replace('_', '-', $item['name']) : 'none';
639 },
640 self::$modules_list
641 );
642 }
643
644 return $names;
645 }
646
647 /**
648 * Get separate widgets name
649 *
650 * @access public
651 * @return array
652 * @since 6.0.0
653 *
654 */
655
656 public static function get_upk_only_widgets() {
657 $names = self::$modules_names_only_widgets;
658
659 if (null === $names) {
660 $names = array_map(
661 function ($item) {
662 return isset($item['name']) ? 'upk-' . str_replace('_', '-', $item['name']) : 'none';
663 },
664 self::$modules_list_only_widgets
665 );
666 }
667
668 return $names;
669 }
670
671 /**
672 * Get separate 3rdParty widgets name
673 *
674 * @access public
675 * @return array
676 * @since 6.0.0
677 *
678 */
679
680 public static function get_upk_only_3rdparty_names() {
681 $names = self::$modules_names_only_3rdparty;
682
683 if (null === $names) {
684 $names = array_map(
685 function ($item) {
686 return isset($item['name']) ? 'upk-' . str_replace('_', '-', $item['name']) : 'none';
687 },
688 self::$modules_list_only_3rdparty
689 );
690 }
691
692 return $names;
693 }
694
695 /**
696 * Get URL with page id
697 *
698 * @access public
699 *
700 */
701
702 public static function get_url() {
703 return admin_url('admin.php?page=' . self::PAGE_ID);
704 }
705
706 /**
707 * Init settings API
708 *
709 * @access public
710 *
711 */
712
713 public function admin_init() {
714
715 //set the settings
716 $this->settings_api->set_sections($this->get_settings_sections());
717 $this->settings_api->set_fields($this->ultimate_post_kit_admin_settings());
718
719 //initialize settings
720 $this->settings_api->admin_init();
721 $this->upk_redirect_to_get_pro();
722 if (true === _is_upk_pro_activated()) {
723 $this->bdt_redirect_to_renew_link();
724 }
725 }
726
727 /**
728 * Add Plugin Menus
729 *
730 * @access public
731 *
732 */
733
734 // Redirect to Ultimate Post Kit Pro pricing page
735 public function upk_redirect_to_get_pro() {
736 if (isset($_GET['page']) && $_GET['page'] === self::PAGE_ID . '_get_pro') {
737 wp_redirect('https://postkit.pro/pricing/');
738 exit;
739 }
740 }
741
742 /**
743 * Redirect to license renewal page
744 *
745 * @access public
746 *
747 */
748 public function bdt_redirect_to_renew_link() {
749 if (isset($_GET['page']) && $_GET['page'] === self::PAGE_ID . '_license_renew') {
750 wp_redirect('https://account.bdthemes.com/');
751 exit;
752 }
753 }
754
755 /**
756 * Add Plugin Menus
757 *
758 * @access public
759 *
760 */
761
762 public function admin_menu() {
763 add_menu_page(
764 BDTUPK_TITLE . ' ' . esc_html__('Dashboard', 'ultimate-post-kit'),
765 BDTUPK_TITLE,
766 'manage_options',
767 self::PAGE_ID,
768 [$this, 'plugin_page'],
769 $this->ultimate_post_kit_icon(),
770 58
771 );
772
773 add_submenu_page(
774 self::PAGE_ID,
775 BDTUPK_TITLE,
776 esc_html__('Core Widgets', 'ultimate-post-kit'),
777 'manage_options',
778 self::PAGE_ID . '#ultimate_post_kit_active_modules',
779 [$this, 'plugin_page']
780 );
781
782 add_submenu_page(
783 self::PAGE_ID,
784 BDTUPK_TITLE,
785 esc_html__('Extensions', 'ultimate-post-kit'),
786 'manage_options',
787 self::PAGE_ID . '#ultimate_post_kit_elementor_extend',
788 [$this, 'plugin_page']
789 );
790
791 add_submenu_page(
792 self::PAGE_ID,
793 BDTUPK_TITLE,
794 esc_html__('Special Features', 'ultimate-post-kit'),
795 'manage_options',
796 self::PAGE_ID . '#ultimate_post_kit_other_settings',
797 [$this, 'plugin_page']
798 );
799
800 add_submenu_page(
801 self::PAGE_ID,
802 BDTUPK_TITLE,
803 esc_html__('API Settings', 'ultimate-post-kit'),
804 'manage_options',
805 self::PAGE_ID . '#ultimate_post_kit_api_settings',
806 [$this, 'plugin_page']
807 );
808
809 add_submenu_page(
810 self::PAGE_ID,
811 BDTUPK_TITLE,
812 esc_html__('Extra Options', 'ultimate-post-kit'),
813 'manage_options',
814 self::PAGE_ID . '#ultimate_post_kit_extra_options',
815 [$this, 'plugin_page']
816 );
817
818 add_submenu_page(
819 self::PAGE_ID,
820 BDTUPK_TITLE,
821 esc_html__('System Status', 'ultimate-post-kit'),
822 'manage_options',
823 self::PAGE_ID . '#ultimate_post_kit_analytics_system_req',
824 [$this, 'plugin_page']
825 );
826
827 add_submenu_page(
828 self::PAGE_ID,
829 BDTUPK_TITLE,
830 esc_html__('Other Plugins', 'ultimate-post-kit'),
831 'manage_options',
832 self::PAGE_ID . '#ultimate_post_kit_other_plugins',
833 [$this, 'plugin_page']
834 );
835
836 // add_submenu_page(
837 // self::PAGE_ID,
838 // BDTUPK_TITLE,
839 // esc_html__('Get Up to 60%', 'ultimate-post-kit'),
840 // 'manage_options',
841 // self::PAGE_ID . '#ultimate_post_kit_affiliate',
842 // [$this, 'plugin_page']
843 // );
844
845 if (true == _is_upk_pro_activated()) {
846 add_submenu_page(
847 self::PAGE_ID,
848 BDTUPK_TITLE,
849 esc_html__('Rollback Version', 'ultimate-post-kit'),
850 'manage_options',
851 self::PAGE_ID . '#ultimate_post_kit_rollback_version',
852 [$this, 'plugin_page']
853 );
854
855 add_submenu_page(
856 self::PAGE_ID,
857 BDTUPK_TITLE,
858 esc_html__('Template Builder', 'ultimate-post-kit'),
859 'edit_pages',
860 'edit.php?post_type=upk-template-builder',
861 );
862 }
863
864 }
865
866 /**
867 * Get SVG Icons of Ultimate Post Kit
868 *
869 * @access public
870 * @return string
871 */
872
873 public function ultimate_post_kit_icon() {
874 return 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyNC4wLjAsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiDQoJIHZpZXdCb3g9IjAgMCA5MDkuMyA4ODMuOCIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgOTA5LjMgODgzLjg7IiB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+DQoJLnN0MHtmaWxsOiNBN0FBQUQ7fQ0KPC9zdHlsZT4NCjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik04MTEuMiwyNzIuOUg2ODEuNnYxMjkuN2MwLDEzLjYtMTEsMjQuNy0yNC43LDI0LjdoLTEwNWMtMTMuNiwwLTI0LjctMTEtMjQuNy0yNC43YzAsMCwwLDAsMCwwdi0xMDUNCgljMC0xMy42LDExLTI0LjcsMjQuNi0yNC43YzAsMCwwLDAsMCwwaDEyOS43VjE0My4zYzAtMTMuNi0xMS0yNC43LTI0LjctMjQuN0gzOTcuNmMtMTMuNiwwLTI0LjcsMTEtMjQuNywyNC43YzAsMCwwLDAsMCwwdjQ3MS41DQoJYzAsMTMuNi0xMSwyNC42LTI0LjYsMjQuN2MwLDAsMCwwLDAsMGgtMTA1Yy0xMy42LDAtMjQuNy0xMS0yNC43LTI0Ljd2LTM3NWMwLTEzLjYtMTEtMjQuNy0yNC43LTI0LjdIODljLTEzLjYsMC0yNC43LDExLTI0LjcsMjQuNw0KCWMwLDAsMCwwLDAsMHY1MjkuNGMwLDEzLjYsMTEsMjQuNywyNC43LDI0LjdoNDEzLjZjMTMuNiwwLDI0LjctMTEuMSwyNC43LTI0LjdWNjA2LjJjMC0xMy42LDExLTI0LjcsMjQuNy0yNC43aDI1OS4zDQoJYzEzLjYsMCwyNC43LTExLDI0LjctMjQuN1YyOTcuNkM4MzUuOSwyODQsODI0LjksMjczLDgxMS4yLDI3Mi45QzgxMS4yLDI3Mi45LDgxMS4yLDI3Mi45LDgxMS4yLDI3Mi45eiIvPg0KPHJlY3QgeD0iNzMyIiB5PSI4Mi42IiBjbGFzcz0ic3QwIiB3aWR0aD0iMzQuOCIgaGVpZ2h0PSIzNC44Ii8+DQo8cmVjdCB4PSI3OTEiIHk9IjE0OS43IiBjbGFzcz0ic3QwIiB3aWR0aD0iMjMuOSIgaGVpZ2h0PSIyMy45Ii8+DQo8cmVjdCB4PSI4MDMiIHk9IjgyLjYiIGNsYXNzPSJzdDAiIHdpZHRoPSIxNy44IiBoZWlnaHQ9IjE3LjgiLz4NCjxyZWN0IHg9Ijg2Ni43IiB5PSIxNTUuOCIgY2xhc3M9InN0MCIgd2lkdGg9IjE3LjgiIGhlaWdodD0iMTcuOCIvPg0KPHJlY3QgeD0iODI4LjkiIHk9IjQ0LjMiIGNsYXNzPSJzdDAiIHdpZHRoPSI4LjkiIGhlaWdodD0iOC45Ii8+DQo8cmVjdCB4PSI4NzcuNCIgeT0iMzgiIGNsYXNzPSJzdDAiIHdpZHRoPSI3LjIiIGhlaWdodD0iNy4yIi8+DQo8cmVjdCB4PSI4NTIuNiIgeT0iODciIGNsYXNzPSJzdDAiIHdpZHRoPSI4LjkiIGhlaWdodD0iOC45Ii8+DQo8cmVjdCB4PSI3MzUuNCIgeT0iMTgyLjgiIGNsYXNzPSJzdDAiIHdpZHRoPSIxOS43IiBoZWlnaHQ9IjE5LjciLz4NCjxyZWN0IHg9IjgyNi4zIiB5PSIyMDQuNiIgY2xhc3M9InN0MCIgd2lkdGg9IjE0LjEiIGhlaWdodD0iMTQuMSIvPg0KPC9zdmc+DQo=';
875 }
876
877 /**
878 * Get SVG Icons of Element Pack
879 *
880 * @access public
881 * @return array
882 */
883
884 public function get_settings_sections() {
885 $sections = [
886 [
887 'id' => 'ultimate_post_kit_active_modules',
888 'title' => esc_html__('Core Widgets', 'ultimate-post-kit'),
889 'icon' => 'dashicons dashicons-screenoptions',
890 ],
891 [
892 'id' => 'ultimate_post_kit_elementor_extend',
893 'title' => esc_html__('Extensions', 'ultimate-post-kit'),
894 'icon' => 'dashicons dashicons-screenoptions',
895 ],
896 [
897 'id' => 'ultimate_post_kit_other_settings',
898 'title' => esc_html__('Special Features', 'ultimate-post-kit'),
899 'icon' => 'dashicons dashicons-screenoptions',
900 ],
901 [
902 'id' => 'ultimate_post_kit_api_settings',
903 'title' => esc_html__('API Settings', 'ultimate-post-kit'),
904 'icon' => 'dashicons dashicons-admin-settings',
905 ],
906 ];
907
908 return $sections;
909 }
910
911 /**
912 * Merge Admin Settings
913 *
914 * @access protected
915 * @return array
916 */
917
918 protected function ultimate_post_kit_admin_settings() {
919
920 return ModuleService::get_widget_settings(function ($settings) {
921 $settings_fields = $settings['settings_fields'];
922
923 self::$modules_list = $settings_fields['ultimate_post_kit_active_modules'];
924 self::$modules_list_only_widgets = $settings_fields['ultimate_post_kit_active_modules'];
925
926 return $settings_fields;
927 });
928 }
929
930 /**
931 * Get Welcome Panel
932 *
933 * @access public
934 * @return void
935 */
936
937 public function ultimate_post_kit_welcome() {
938
939 ?>
940
941 <div class="upk-dashboard-panel"
942 bdt-scrollspy="target: > div > div > .bdt-card; cls: bdt-animation-slide-bottom-small; delay: 300">
943
944 <div class="upk-dashboard-welcome-container">
945
946 <div class="upk-dashboard-item upk-dashboard-welcome bdt-card bdt-card-body">
947 <h1 class="upk-feature-title upk-dashboard-welcome-title">
948 <?php esc_html_e('Welcome to Ultimate Post Kit!', 'ultimate-post-kit'); ?>
949 </h1>
950 <p class="upk-dashboard-welcome-desc">
951 <?php esc_html_e('Empower your web creation with powerful widgets, advanced extensions, ready templates and more.', 'ultimate-post-kit'); ?>
952 </p>
953 <a href="<?php echo admin_url('?upk_setup_wizard=show'); ?>"
954 class="bdt-button bdt-welcome-button bdt-margin-small-top"
955 target="_blank"><?php esc_html_e('Setup Ultimate Post Kit', 'ultimate-post-kit'); ?></a>
956
957 <div class="upk-dashboard-compare-section">
958 <h4 class="upk-feature-sub-title">
959 <?php printf(esc_html__('Unlock %sPremium Features%s', 'ultimate-post-kit'), '<strong class="upk-highlight-text">', '</strong>'); ?>
960 </h4>
961 <h1 class="upk-feature-title upk-dashboard-compare-title">
962 <?php esc_html_e('Create Your Sleek Website with Ultimate Post Kit Pro!', 'ultimate-post-kit'); ?>
963 </h1>
964 <p><?php esc_html_e('Don\'t need more plugins. This pro addon helps you build complex or professional websites—visually stunning, functional and customizable.', 'ultimate-post-kit'); ?>
965 </p>
966 <ul>
967 <li><?php esc_html_e('Dynamic Content and Integrations', 'ultimate-post-kit'); ?></li>
968 <li><?php esc_html_e('Live Copy Paste', 'ultimate-post-kit'); ?></li>
969 <li><?php esc_html_e('Template Builder', 'ultimate-post-kit'); ?></li>
970 <li><?php esc_html_e('Custom Meta Fields - Category Image, Audio Link, Video Link', 'ultimate-post-kit'); ?></li>
971 <li><?php esc_html_e('Powerful Widgets and Advanced Extensions', 'ultimate-post-kit'); ?>
972 </li>
973 </ul>
974 <div class="upk-dashboard-compare-section-buttons">
975 <a href="https://postkit.pro/pricing/"
976 class="bdt-button bdt-welcome-button bdt-margin-small-right"
977 target="_blank"><?php esc_html_e('Compare Free Vs Pro', 'ultimate-post-kit'); ?></a>
978 <a href="https://store.bdthemes.com/ultimate-post-kit?utm_source=UltimatePostKit&utm_medium=PluginPage&utm_campaign=UltimatePostKit&coupon=FREETOPRO"
979 class="bdt-button bdt-dashboard-sec-btn"
980 target="_blank"><?php esc_html_e('Get Premium at 30% OFF', 'ultimate-post-kit'); ?></a>
981 </div>
982 </div>
983 </div>
984
985 <div class="upk-dashboard-item upk-dashboard-template-quick-access bdt-card bdt-card-body">
986 <div class="upk-dashboard-template-section">
987 <img src="<?php echo BDTUPK_ADMIN_URL . 'assets/images/template.jpg'; ?>"
988 alt="Ultimate Post Kit Dashboard Template">
989 <h1 class="upk-feature-title ">
990 <?php esc_html_e('Faster Web Creation with Sleek and Ready-to-Use Templates!', 'ultimate-post-kit'); ?>
991 </h1>
992 <p><?php esc_html_e('Build your wordpress websites of any niche—not from scratch and in a single click.', 'ultimate-post-kit'); ?>
993 </p>
994 <a href="https://postkit.pro/"
995 class="bdt-button bdt-dashboard-sec-btn bdt-margin-small-top"
996 target="_blank"><?php esc_html_e('View Templates', 'ultimate-post-kit'); ?></a>
997 </div>
998
999 <div class="upk-dashboard-quick-access bdt-margin-medium-top">
1000 <img src="<?php echo BDTUPK_ADMIN_URL . 'assets/images/support.jpg'; ?>"
1001 alt="Ultimate Post Kit Dashboard Template">
1002 <h1 class="upk-feature-title">
1003 <?php esc_html_e('Getting Started with Quick Access', 'ultimate-post-kit'); ?>
1004 </h1>
1005 <ul>
1006 <li><a href="https://postkit.pro/contact/"
1007 target="_blank"><?php esc_html_e('Contact Us', 'ultimate-post-kit'); ?></a></li>
1008 <li><a href="https://bdthemes.com/support/"
1009 target="_blank"><?php esc_html_e('Help Centre', 'ultimate-post-kit'); ?></a></li>
1010 <li><a href="https://feedback.bdthemes.com/b/6vr2250l/feature-requests/idea/new"
1011 target="_blank"><?php esc_html_e('Request a Feature', 'ultimate-post-kit'); ?></a>
1012 </li>
1013 </ul>
1014 <div class="upk-dashboard-support-section">
1015 <h1 class="upk-feature-title">
1016 <i class="dashicons dashicons-phone"></i>
1017 <?php esc_html_e('24/7 Support', 'ultimate-post-kit'); ?>
1018 </h1>
1019 <p><?php esc_html_e('Helping you get real-time solutions related to web creation with WordPress, Elementor, and Ultimate Post Kit.', 'ultimate-post-kit'); ?>
1020 </p>
1021 <a href="https://bdthemes.com/support/" class="bdt-margin-small-top"
1022 target="_blank"><?php esc_html_e('Get Your Support', 'ultimate-post-kit'); ?></a>
1023 </div>
1024 </div>
1025 </div>
1026
1027 <div class="upk-dashboard-item upk-dashboard-request-feature bdt-card bdt-card-body">
1028 <h1 class="upk-feature-title upk-dashboard-template-quick-title">
1029 <?php esc_html_e('What\'s Stacking You?', 'ultimate-post-kit'); ?>
1030 </h1>
1031 <p><?php esc_html_e('We are always here to help you. If you have any feature request, please let us know.', 'ultimate-post-kit'); ?>
1032 </p>
1033 <a href="https://feedback.bdthemes.com/b/6vr2250l/feature-requests/idea/new"
1034 class="bdt-button bdt-dashboard-sec-btn bdt-margin-small-top"
1035 target="_blank"><?php esc_html_e('Request Your Features', 'ultimate-post-kit'); ?></a>
1036 </div>
1037
1038 <a href="https://www.youtube.com/watch?v=zNeoRz94cPw&list=PLP0S85GEw7DNBnZCb4RtJzlf38GCJ7z1b" target="_blank"
1039 class="upk-dashboard-item upk-dashboard-footer-item upk-dashboard-video-tutorial bdt-card bdt-card-body bdt-card-small">
1040 <span class="upk-dashboard-footer-item-icon">
1041 <i class="dashicons dashicons-video-alt3"></i>
1042 </span>
1043 <h1 class="upk-feature-title"><?php esc_html_e('Watch Video Tutorials', 'ultimate-post-kit'); ?></h1>
1044 <p><?php esc_html_e('An invaluable resource for mastering WordPress, Elementor, and Web Creation', 'ultimate-post-kit'); ?>
1045 </p>
1046 </a>
1047 <a href="https://bdthemes.com/all-knowledge-base-of-ultimate-post-kit/" target="_blank"
1048 class="upk-dashboard-item upk-dashboard-footer-item upk-dashboard-documentation bdt-card bdt-card-body bdt-card-small">
1049 <span class="upk-dashboard-footer-item-icon">
1050 <i class="dashicons dashicons-admin-tools"></i>
1051 </span>
1052 </span>
1053 <h1 class="upk-feature-title"><?php esc_html_e('Read Easy Documentation', 'ultimate-post-kit'); ?></h1>
1054 <p><?php esc_html_e('A way to eliminate the challenges you might face', 'ultimate-post-kit'); ?></p>
1055 </a>
1056 <a href="https://www.facebook.com/bdthemes" target="_blank"
1057 class="upk-dashboard-item upk-dashboard-footer-item upk-dashboard-community bdt-card bdt-card-body bdt-card-small">
1058 <span class="upk-dashboard-footer-item-icon">
1059 <i class="dashicons dashicons-admin-users"></i>
1060 </span>
1061 <h1 class="upk-feature-title"><?php esc_html_e('Join Our Community', 'ultimate-post-kit'); ?></h1>
1062 <p><?php esc_html_e('A platform for the opportunity to network, collaboration and innovation', 'ultimate-post-kit'); ?>
1063 </p>
1064 </a>
1065 <a href="https://wordpress.org/plugins/ultimate-post-kit/#reviews" target="_blank"
1066 class="upk-dashboard-item upk-dashboard-footer-item upk-dashboard-review bdt-card bdt-card-body bdt-card-small">
1067 <span class="upk-dashboard-footer-item-icon">
1068 <i class="dashicons dashicons-star-filled"></i>
1069 </span>
1070 <h1 class="upk-feature-title"><?php esc_html_e('Show Your Love', 'ultimate-post-kit'); ?></h1>
1071 <p><?php esc_html_e('A way of the assessment of code', 'ultimate-post-kit'); ?></p>
1072 </a>
1073 </div>
1074
1075 </div>
1076
1077 <?php
1078 }
1079
1080 /**
1081 * Get Pro
1082 *
1083 * @access public
1084 * @return void
1085 */
1086
1087 function ultimate_post_kit_get_pro() {
1088 ?>
1089 <div class="upk-dashboard-panel" bdt-scrollspy="target: > div > div > .bdt-card; cls: bdt-animation-slide-bottom-small; delay: 300">
1090
1091 <div class="bdt-grid" bdt-grid bdt-height-match="target: > div > .bdt-card" style="max-width: 800px; margin-left: auto; margin-right: auto;">
1092 <div class="bdt-width-1-1@m upk-comparision bdt-text-center">
1093
1094 <div class="bdt-flex bdt-flex-between bdt-flex-middle">
1095 <div class="bdt-text-left">
1096 <h1 class="bdt-text-bold">
1097 <?php echo esc_html_x('WHY GO WITH PRO?', 'Frontend', 'ultimate-post-kit'); ?>
1098 </h1>
1099 <h2>
1100 <?php echo esc_html_x('Just Compare With Ultimate Post Kit Free Vs Pro', 'Frontend', 'ultimate-post-kit'); ?>
1101 </h2>
1102
1103 </div>
1104 <?php if (true !== _is_upk_pro_activated()) : ?>
1105 <div class="upk-purchase-button">
1106 <a href="https://postkit.pro/pricing/" target="_blank">
1107 <?php echo esc_html_x('Purchase Now', 'Frontend', 'ultimate-post-kit'); ?>
1108 </a>
1109 </div>
1110 <?php endif; ?>
1111 </div>
1112
1113
1114 <div>
1115
1116 <ul class="bdt-list bdt-list-divider bdt-text-left bdt-text-normal" style="font-size: 15px;">
1117
1118
1119 <li class="bdt-text-bold">
1120 <div class="bdt-grid">
1121 <div class="bdt-width-expand@m">
1122 <?php echo esc_html_x('Features', 'Frontend', 'ultimate-post-kit'); ?>
1123 </div>
1124 <div class="bdt-width-auto@m">
1125 <?php echo esc_html_x('Free', 'Frontend', 'ultimate-post-kit'); ?>
1126 </div>
1127 <div class="bdt-width-auto@m">
1128 <?php echo esc_html_x('Pro', 'Frontend', 'ultimate-post-kit'); ?>
1129 </div>
1130 </div>
1131 </li>
1132 <li class="">
1133 <div class="bdt-grid">
1134 <div class="bdt-width-expand@m"><span bdt-tooltip="pos: top-left; title: Lite have 35+ Widgets but Pro have 100+ core widgets">
1135 <?php echo esc_html_x('Core Widgets', 'Frontend', 'ultimate-post-kit'); ?>
1136 </span></div>
1137 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1138 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1139 </div>
1140 </li>
1141 <li class="">
1142 <div class="bdt-grid">
1143 <div class="bdt-width-expand@m">
1144 <?php echo esc_html_x('Theme Compatibility', 'Frontend', 'ultimate-post-kit'); ?>
1145 </div>
1146 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1147 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1148 </div>
1149 </li>
1150 <li class="">
1151 <div class="bdt-grid">
1152 <div class="bdt-width-expand@m">
1153 <?php echo esc_html_x('Dynamic Content & Custom Fields Capabilities', 'Frontend', 'ultimate-post-kit'); ?>
1154 </div>
1155 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1156 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1157 </div>
1158 </li>
1159 <li class="">
1160 <div class="bdt-grid">
1161 <div class="bdt-width-expand@m">
1162 <?php echo esc_html_x('Proper Documentation', 'Frontend', 'ultimate-post-kit'); ?>
1163 </div>
1164 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1165 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1166 </div>
1167 </li>
1168 <li class="">
1169 <div class="bdt-grid">
1170 <div class="bdt-width-expand@m">
1171 <?php echo esc_html_x('Updates & Support', 'Frontend', 'ultimate-post-kit'); ?>
1172 </div>
1173 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1174 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1175 </div>
1176 </li>
1177
1178 <li class="">
1179 <div class="bdt-grid">
1180 <div class="bdt-width-expand@m">
1181 <?php echo esc_html_x('Ready Made Pages', 'Frontend', 'ultimate-post-kit'); ?>
1182 </div>
1183 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1184 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1185 </div>
1186 </li>
1187 <li class="">
1188 <div class="bdt-grid">
1189 <div class="bdt-width-expand@m">
1190 <?php echo esc_html_x('Ready Made Blocks', 'Frontend', 'ultimate-post-kit'); ?>
1191 </div>
1192 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1193 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1194 </div>
1195 </li>
1196 <li class="">
1197 <div class="bdt-grid">
1198 <div class="bdt-width-expand@m">
1199 <?php echo esc_html_x('Elementor Extended Widgets', 'Frontend', 'ultimate-post-kit'); ?>
1200 </div>
1201 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1202 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1203 </div>
1204 </li>
1205 <li class="">
1206 <div class="bdt-grid">
1207 <div class="bdt-width-expand@m">
1208 <?php echo esc_html_x('Live Copy or Paste', 'Frontend', 'ultimate-post-kit'); ?>
1209 </div>
1210 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1211 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1212 </div>
1213 </li>
1214 <li class="">
1215 <div class="bdt-grid">
1216 <div class="bdt-width-expand@m">
1217 <?php echo esc_html_x('Duplicator', 'Frontend', 'ultimate-post-kit'); ?>
1218 </div>
1219 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1220 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1221 </div>
1222 </li>
1223 <li class="">
1224 <div class="bdt-grid">
1225 <div class="bdt-width-expand@m">
1226 <?php echo esc_html_x('Video Link Meta', 'Frontend', 'ultimate-post-kit'); ?>
1227 </div>
1228 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1229 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1230 </div>
1231 </li>
1232 <li class="">
1233 <div class="bdt-grid">
1234 <div class="bdt-width-expand@m">
1235 <?php echo esc_html_x('Category Image', 'Frontend', 'ultimate-post-kit'); ?>
1236 </div>
1237 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1238 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1239 </div>
1240 </li>
1241 <li class="">
1242 <div class="bdt-grid">
1243 <div class="bdt-width-expand@m">
1244 <?php echo esc_html_x('Rooten Theme Pro Features', 'Frontend', 'ultimate-post-kit'); ?>
1245 </div>
1246 <div class="bdt-width-auto@m"><span class="dashicons dashicons-no"></span></div>
1247 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1248 </div>
1249 </li>
1250 <li class="">
1251 <div class="bdt-grid">
1252 <div class="bdt-width-expand@m">
1253 <?php echo esc_html_x('Priority Support', 'Frontend', 'ultimate-post-kit'); ?>
1254 </div>
1255 <div class="bdt-width-auto@m"><span class="dashicons dashicons-no"></span></div>
1256 <div class="bdt-width-auto@m"><span class="dashicons dashicons-yes"></span></div>
1257 </div>
1258 </li>
1259
1260 </ul>
1261
1262
1263 <!-- <div class="upk-dashboard-divider"></div> -->
1264
1265
1266 <div class="upk-more-features bdt-card bdt-card-body bdt-margin-medium-top bdt-padding-large">
1267 <ul class="bdt-list bdt-list-divider bdt-text-left" style="font-size: 15px;">
1268 <li>
1269 <div class="bdt-grid bdt-grid-small">
1270 <div class="bdt-width-1-3@m">
1271 <span class="dashicons dashicons-heart"></span>
1272 <?php echo esc_html_x('Incredibly Advanced', 'Frontend', 'ultimate-post-kit'); ?>
1273 </div>
1274 <div class="bdt-width-1-3@m">
1275 <span class="dashicons dashicons-heart"></span>
1276 <?php echo esc_html_x('Refund or Cancel Anytime', 'Frontend', 'ultimate-post-kit'); ?>
1277 </div>
1278 <div class="bdt-width-1-3@m">
1279 <span class="dashicons dashicons-heart"></span>
1280 <?php echo esc_html_x('Dynamic Content', 'Frontend', 'ultimate-post-kit'); ?>
1281 </div>
1282 </div>
1283 </li>
1284
1285 <li>
1286 <div class="bdt-grid bdt-grid-small">
1287 <div class="bdt-width-1-3@m">
1288 <span class="dashicons dashicons-heart"></span>
1289 <?php echo esc_html_x('Super-Flexible Widgets', 'Frontend', 'ultimate-post-kit'); ?>
1290 </div>
1291 <div class="bdt-width-1-3@m">
1292 <span class="dashicons dashicons-heart"></span>
1293 <?php echo esc_html_x('24/7 Premium Support', 'Frontend', 'ultimate-post-kit'); ?>
1294 </div>
1295 <div class="bdt-width-1-3@m">
1296 <span class="dashicons dashicons-heart"></span>
1297 <?php echo esc_html_x('Third Party Plugins', 'Frontend', 'ultimate-post-kit'); ?>
1298 </div>
1299 </div>
1300 </li>
1301
1302 <li>
1303 <div class="bdt-grid bdt-grid-small">
1304 <div class="bdt-width-1-3@m">
1305 <span class="dashicons dashicons-heart"></span>
1306 <?php echo esc_html_x('Special Discount!', 'Frontend', 'ultimate-post-kit'); ?>
1307 </div>
1308 <div class="bdt-width-1-3@m">
1309 <span class="dashicons dashicons-heart"></span>
1310 <?php echo esc_html_x('Custom Field Integration', 'Frontend', 'ultimate-post-kit'); ?>
1311 </div>
1312 <div class="bdt-width-1-3@m">
1313 <span class="dashicons dashicons-heart"></span>
1314 <?php echo esc_html_x('With Live Chat Support', 'Frontend', 'ultimate-post-kit'); ?>
1315 </div>
1316 </div>
1317 </li>
1318
1319 <li>
1320 <div class="bdt-grid bdt-grid-small">
1321 <div class="bdt-width-1-3@m">
1322 <span class="dashicons dashicons-heart"></span>
1323 <?php echo esc_html_x('Trusted Payment Methods', 'Frontend', 'ultimate-post-kit'); ?>
1324 </div>
1325 <div class="bdt-width-1-3@m">
1326 <span class="dashicons dashicons-heart"></span>
1327 <?php echo esc_html_x('Interactive Effects', 'Frontend', 'ultimate-post-kit'); ?>
1328 </div>
1329 <div class="bdt-width-1-3@m">
1330 <span class="dashicons dashicons-heart"></span>
1331 <?php echo esc_html_x('Video Tutorial', 'Frontend', 'ultimate-post-kit'); ?>
1332 </div>
1333 </div>
1334 </li>
1335 </ul>
1336
1337 <!-- <div class="upk-dashboard-divider"></div> -->
1338
1339 <?php if (true !== _is_upk_pro_activated()) : ?>
1340 <div class="upk-purchase-button bdt-margin-medium-top">
1341 <a href="https://postkit.pro/pricing/" target="_blank">
1342 <?php echo esc_html_x('Purchase Now', 'Frontend', 'ultimate-post-kit'); ?>
1343 </a>
1344 </div>
1345 <?php endif; ?>
1346
1347 </div>
1348
1349 </div>
1350 </div>
1351 </div>
1352
1353 </div>
1354 <?php
1355 }
1356
1357 /**
1358 * Display Plugin Page
1359 *
1360 * @access public
1361 * @return void
1362 */
1363
1364 public function plugin_page() {
1365
1366 ?>
1367
1368 <div class="wrap ultimate-post-kit-dashboard">
1369 <h1></h1> <!-- don't remove this div, it's used for the notice container -->
1370
1371 <div class="upk-dashboard-wrapper bdt-margin-top">
1372 <div class="upk-dashboard-header bdt-flex bdt-flex-wrap bdt-flex-between bdt-flex-middle"
1373 bdt-sticky="offset: 32; animation: bdt-animation-slide-top-small; duration: 300">
1374
1375 <div class="bdt-flex bdt-flex-wrap bdt-flex-middle">
1376 <!-- Header Shape Elements -->
1377 <div class="upk-header-elements">
1378 <span class="upk-header-element upk-header-circle"></span>
1379 <span class="upk-header-element upk-header-dots"></span>
1380 <span class="upk-header-element upk-header-line"></span>
1381 <span class="upk-header-element upk-header-square"></span>
1382 <span class="upk-header-element upk-header-wave"></span>
1383 </div>
1384
1385 <div class="upk-logo">
1386 <?php
1387 $white_label_enabled = get_option( 'upk_white_label_enabled', false );
1388 $white_label_logo = get_option( 'upk_white_label_logo', '' );
1389 $white_label_title = get_option( 'upk_white_label_title', '' );
1390
1391 if ($white_label_enabled && !empty($white_label_logo)) {
1392
1393 $alt_text = !empty($white_label_title) ? $white_label_title . ' Logo' : 'Custom Logo';
1394 echo '<img src="' . esc_url($white_label_logo) . '" alt="' . esc_attr($alt_text) . '" style="max-height: 40px;">';
1395 } else {
1396 echo '<img src="' . BDTUPK_URL . 'assets/images/logo-with-text.svg" alt="Ultimate Post Kit Logo">';
1397 }
1398 ?>
1399 </div>
1400 </div>
1401
1402 <div class="upk-dashboard-new-page-wrapper bdt-flex bdt-flex-wrap bdt-flex-middle">
1403
1404
1405 <!-- Always render save button, JavaScript will control visibility -->
1406 <div class="upk-dashboard-save-btn" style="display: none;">
1407 <button class="bdt-button bdt-button-primary ultimate-post-kit-settings-save-btn" type="submit">
1408 <?php esc_html_e('Save Settings', 'ultimate-post-kit'); ?>
1409 </button>
1410 </div>
1411
1412 <!-- Custom Code Save Button Section -->
1413 <div class="upk-code-save-section" style="display: none;">
1414 <button type="button" id="upk-save-custom-code" class="bdt-button bdt-button-primary ultimate-post-kit-custom-code-save-btn">
1415 <?php esc_html_e('Save Custom Code', 'ultimate-post-kit'); ?>
1416 </button>
1417 <button type="button" id="upk-reset-custom-code" class="bdt-button bdt-button-primary ultimate-post-kit-custom-code-reset-btn">
1418 <?php esc_html_e('Reset Code', 'ultimate-post-kit'); ?>
1419 </button>
1420 </div>
1421
1422 <!-- White Label Save Button Section -->
1423 <?php if (self::is_white_label_license()): ?>
1424 <div class="upk-white-label-save-section" style="display: none;">
1425 <button type="button"
1426 id="upk-save-white-label"
1427 class="bdt-button bdt-button-primary ultimate-post-kit-white-label-save-btn">
1428 <?php esc_html_e('Save White Label Settings', 'ultimate-post-kit'); ?>
1429 </button>
1430 </div>
1431 <?php endif; ?>
1432
1433 <div class="upk-dashboard-new-page">
1434 <a class="bdt-flex bdt-flex-middle" href="<?php echo esc_url(admin_url('post-new.php?post_type=page')); ?>" class=""><i class="dashicons dashicons-admin-page"></i>
1435 <?php echo esc_html__('Create New Page', 'ultimate-post-kit') ?>
1436 </a>
1437 </div>
1438 </div>
1439 </div>
1440
1441 <div class="upk-dashboard-container bdt-flex">
1442 <div class="upk-dashboard-nav-container-wrapper">
1443 <div class="upk-dashboard-nav-container-inner" bdt-sticky="end: !.upk-dashboard-container; offset: 115; animation: bdt-animation-slide-top-small; duration: 300">
1444
1445 <!-- Navigation Shape Elements -->
1446 <div class="upk-nav-elements">
1447 <span class="upk-nav-element upk-nav-circle"></span>
1448 <span class="upk-nav-element upk-nav-dots"></span>
1449 <span class="upk-nav-element upk-nav-line"></span>
1450 <span class="upk-nav-element upk-nav-square"></span>
1451 <span class="upk-nav-element upk-nav-triangle"></span>
1452 <span class="upk-nav-element upk-nav-plus"></span>
1453 <span class="upk-nav-element upk-nav-wave"></span>
1454 </div>
1455
1456 <?php $this->settings_api->show_navigation(); ?>
1457 </div>
1458 </div>
1459
1460
1461 <div class="bdt-switcher bdt-tab-container bdt-container-xlarge bdt-flex-1">
1462 <div id="ultimate_post_kit_welcome_page" class="upk-option-page group">
1463 <?php $this->ultimate_post_kit_welcome(); ?>
1464 </div>
1465
1466 <?php $this->settings_api->show_forms(); ?>
1467
1468 <div id="ultimate_post_kit_extra_options_page" class="upk-option-page group">
1469 <?php $this->ultimate_post_kit_extra_options(); ?>
1470 </div>
1471
1472 <div id="ultimate_post_kit_analytics_system_req_page" class="upk-option-page group">
1473 <?php $this->ultimate_post_kit_analytics_system_req_content(); ?>
1474 </div>
1475
1476 <div id="ultimate_post_kit_other_plugins_page" class="upk-option-page group">
1477 <?php $this->ultimate_post_kit_others_plugin(); ?>
1478 </div>
1479
1480 <!-- <div id="ultimate_post_kit_affiliate_page" class="upk-option-page group">
1481 <?php //$this->ultimate_post_kit_affiliate_content(); ?>
1482 </div> -->
1483
1484 <?php if (true == _is_upk_pro_activated()) : ?>
1485 <div id="ultimate_post_kit_rollback_version_page" class="upk-option-page group">
1486 <?php $this->upk_rollback_version_content(); ?>
1487 </div>
1488 <?php endif; ?>
1489
1490 <?php if (_is_upk_pro_activated() !== true) : ?>
1491 <div id="ultimate_post_kit_get_pro" class="upk-option-page group">
1492 <?php $this->ultimate_post_kit_get_pro(); ?>
1493 </div>
1494 <?php endif; ?>
1495
1496 <div id="ultimate_post_kit_license_settings_page" class="upk-option-page group">
1497
1498 <?php
1499 if (_is_upk_pro_activated() == true) {
1500 apply_filters('upk_license_page', '');
1501 }
1502
1503 ?>
1504 </div>
1505
1506 </div>
1507 </div>
1508
1509 <?php if (!defined('BDTUPK_WL') || false == self::license_wl_status()) {
1510 $this->footer_info();
1511 } ?>
1512 </div>
1513
1514 </div>
1515
1516 <?php
1517
1518 $this->script();
1519
1520 }
1521
1522
1523
1524
1525 /**
1526 * Tabbable JavaScript codes & Initiate Color Picker
1527 *
1528 * This code uses localstorage for displaying active tabs
1529 */
1530 function script() {
1531 ?>
1532 <script>
1533 jQuery(document).ready(function() {
1534 jQuery('.upk-no-result').removeClass('bdt-animation-shake');
1535 });
1536
1537 function filterSearch(e) {
1538 var parentID = '#' + jQuery(e).data('id');
1539 var search = jQuery(parentID).find('.bdt-search-input').val().toLowerCase();
1540
1541 jQuery(".upk-options .upk-option-item").filter(function() {
1542 jQuery(this).toggle(jQuery(this).attr('data-widget-name').toLowerCase().indexOf(search) > -1)
1543 });
1544
1545 if (!search) {
1546 jQuery(parentID).find('.bdt-search-input').attr('bdt-filter-control', "");
1547 jQuery(parentID).find('.upk-widget-all').trigger('click');
1548 } else {
1549 jQuery(parentID).find('.bdt-search-input').attr('bdt-filter-control', "filter: [data-widget-name*='" + search + "']");
1550 jQuery(parentID).find('.bdt-search-input').removeClass('bdt-active'); // Thanks to Bar-Rabbas
1551 jQuery(parentID).find('.bdt-search-input').trigger('click');
1552 }
1553 }
1554
1555 jQuery('.upk-options-parent').each(function(e, item) {
1556 var eachItem = '#' + jQuery(item).attr('id');
1557 jQuery(eachItem).on("beforeFilter", function() {
1558 jQuery(eachItem).find('.upk-no-result').removeClass('bdt-animation-shake');
1559 });
1560
1561 jQuery(eachItem).on("afterFilter", function() {
1562
1563 var isElementVisible = false;
1564 var i = 0;
1565
1566 if (jQuery(eachItem).closest(".upk-options-parent").eq(i).is(":visible")) {} else {
1567 isElementVisible = true;
1568 }
1569
1570 while (!isElementVisible && i < jQuery(eachItem).find(".upk-option-item").length) {
1571 if (jQuery(eachItem).find(".upk-option-item").eq(i).is(":visible")) {
1572 isElementVisible = true;
1573 }
1574 i++;
1575 }
1576
1577 if (isElementVisible === false) {
1578 jQuery(eachItem).find('.upk-no-result').addClass('bdt-animation-shake');
1579 }
1580 });
1581
1582
1583 });
1584
1585
1586 jQuery('.upk-widget-filter-nav li a').on('click', function(e) {
1587 jQuery(this).closest('.bdt-widget-filter-wrapper').find('.bdt-search-input').val('');
1588 jQuery(this).closest('.bdt-widget-filter-wrapper').find('.bdt-search-input').val('').attr('bdt-filter-control', '');
1589 });
1590
1591
1592 jQuery(document).ready(function($) {
1593 'use strict';
1594
1595 function hashHandler() {
1596 var $tab = jQuery('.ultimate-post-kit-dashboard .bdt-tab');
1597 if (window.location.hash) {
1598 var hash = window.location.hash.substring(1);
1599 bdtUIkit.tab($tab).show(jQuery('#bdt-' + hash).data('tab-index'));
1600 }
1601 }
1602
1603 function onWindowLoad() {
1604 hashHandler();
1605 }
1606
1607 if (document.readyState === 'complete') {
1608 onWindowLoad();
1609 } else {
1610 jQuery(window).on('load', onWindowLoad);
1611 }
1612
1613 window.addEventListener("hashchange", hashHandler, true);
1614
1615 jQuery('.toplevel_page_ultimate_post_kit_options > ul > li > a ').on('click', function(event) {
1616 jQuery(this).parent().siblings().removeClass('current');
1617 jQuery(this).parent().addClass('current');
1618 });
1619
1620 jQuery('#ultimate_post_kit_active_modules_page a.upk-active-all-widget').on('click', function(e) {
1621 e.preventDefault();
1622
1623 jQuery('#ultimate_post_kit_active_modules_page .upk-option-item:not(.upk-pro-inactive) .checkbox:visible').each(function() {
1624 jQuery(this).attr('checked', 'checked').prop("checked", true);
1625 });
1626
1627 jQuery(this).addClass('bdt-active');
1628 jQuery('a.upk-deactive-all-widget').removeClass('bdt-active');
1629 });
1630
1631 jQuery('#ultimate_post_kit_active_modules_page a.upk-deactive-all-widget').on('click', function(e) {
1632 e.preventDefault();
1633 jQuery('#ultimate_post_kit_active_modules_page .upk-option-item:not(.upk-pro-inactive) .checkbox:visible').each(function() {
1634 jQuery(this).removeAttr('checked');
1635 });
1636
1637 jQuery(this).addClass('bdt-active');
1638 jQuery('a.upk-active-all-widget').removeClass('bdt-active');
1639 });
1640
1641 jQuery('#ultimate_post_kit_elementor_extend_page a.upk-active-all-widget').on('click', function(e) {
1642 e.preventDefault();
1643
1644 jQuery('#ultimate_post_kit_elementor_extend_page .checkbox:visible').each(function() {
1645 jQuery(this).attr('checked', 'checked').prop("checked", true);
1646 });
1647
1648 jQuery(this).addClass('bdt-active');
1649 jQuery('a.upk-deactive-all-widget').removeClass('bdt-active');
1650 });
1651
1652 jQuery('#ultimate_post_kit_elementor_extend_page a.upk-deactive-all-widget').on('click', function(e) {
1653 e.preventDefault();
1654 jQuery('#ultimate_post_kit_elementor_extend_page .checkbox:visible').each(function() {
1655 jQuery(this).removeAttr('checked');
1656 });
1657
1658 jQuery(this).addClass('bdt-active');
1659 jQuery('a.upk-active-all-widget').removeClass('bdt-active');
1660 });
1661
1662 // Activate/Deactivate all widgets functionality
1663 $('#ultimate_post_kit_active_modules_page a.upk-active-all-widget').on('click', function (e) {
1664 e.preventDefault();
1665
1666 $('#ultimate_post_kit_active_modules_page .upk-option-item:not(.upk-pro-inactive) .checkbox:visible').each(function () {
1667 $(this).attr('checked', 'checked').prop("checked", true);
1668 });
1669
1670 $(this).addClass('bdt-active');
1671 $('#ultimate_post_kit_active_modules_page a.upk-deactive-all-widget').removeClass('bdt-active');
1672
1673 // Ensure save button remains visible
1674 setTimeout(function() {
1675 $('.upk-dashboard-save-btn').show();
1676 }, 100);
1677 });
1678
1679 $('#ultimate_post_kit_active_modules_page a.upk-deactive-all-widget').on('click', function (e) {
1680 e.preventDefault();
1681
1682 $('#ultimate_post_kit_active_modules_page .checkbox:visible').each(function () {
1683 $(this).removeAttr('checked').prop("checked", false);
1684 });
1685
1686 $(this).addClass('bdt-active');
1687 $('#ultimate_post_kit_active_modules_page a.upk-active-all-widget').removeClass('bdt-active');
1688
1689 // Ensure save button remains visible
1690 setTimeout(function() {
1691 $('.upk-dashboard-save-btn').show();
1692 }, 100);
1693 });
1694
1695 $('#ultimate_post_kit_elementor_extend_page a.upk-active-all-widget').on('click', function (e) {
1696 e.preventDefault();
1697
1698 $('#ultimate_post_kit_elementor_extend_page .upk-option-item:not(.upk-pro-inactive) .checkbox:visible').each(function () {
1699 $(this).attr('checked', 'checked').prop("checked", true);
1700 });
1701
1702 $(this).addClass('bdt-active');
1703 $('#ultimate_post_kit_elementor_extend_page a.upk-deactive-all-widget').removeClass('bdt-active');
1704
1705 // Ensure save button remains visible
1706 setTimeout(function() {
1707 $('.upk-dashboard-save-btn').show();
1708 }, 100);
1709 });
1710
1711 $('#ultimate_post_kit_elementor_extend_page a.upk-deactive-all-widget').on('click', function (e) {
1712 e.preventDefault();
1713
1714 $('#ultimate_post_kit_elementor_extend_page .checkbox:visible').each(function () {
1715 $(this).removeAttr('checked').prop("checked", false);
1716 });
1717
1718 $(this).addClass('bdt-active');
1719 $('#ultimate_post_kit_elementor_extend_page a.upk-active-all-widget').removeClass('bdt-active');
1720
1721 // Ensure save button remains visible
1722 setTimeout(function() {
1723 $('.upk-dashboard-save-btn').show();
1724 }, 100);
1725 });
1726
1727 jQuery('#ultimate_post_kit_active_modules_page .upk-pro-inactive .checkbox').each(function() {
1728 jQuery(this).removeAttr('checked');
1729 jQuery(this).attr("disabled", true);
1730 });
1731
1732 });
1733
1734 jQuery(document).ready(function ($) {
1735 const getProLink = $('a[href="admin.php?page=ultimate_post_kit_options_get_pro"]');
1736 if (getProLink.length) {
1737 getProLink.attr('target', '_blank');
1738 }
1739 });
1740
1741 // License Renew Redirect
1742 jQuery(document).ready(function ($) {
1743 const renewalLink = $('a[href="admin.php?page=ultimate_post_kit_options_license_renew"]');
1744 if (renewalLink.length) {
1745 renewalLink.attr('target', '_blank');
1746 }
1747 });
1748
1749 // Dynamic Save Button Control
1750 jQuery(document).ready(function ($) {
1751 // Define pages that need save button - only specific settings pages
1752 const pagesWithSave = [
1753 'ultimate_post_kit_active_modules', // Core widgets
1754 'ultimate_post_kit_elementor_extend', // Extensions
1755 'ultimate_post_kit_other_settings', // Special features
1756 'ultimate_post_kit_api_settings' // API settings
1757 ];
1758
1759 function toggleSaveButton() {
1760 const currentHash = window.location.hash.substring(1);
1761 const saveButton = $('.upk-dashboard-save-btn');
1762
1763 // Check if current page should have save button
1764 if (pagesWithSave.includes(currentHash)) {
1765 saveButton.fadeIn(200);
1766 } else {
1767 saveButton.fadeOut(200);
1768 }
1769 }
1770
1771 // Force save button to be visible for settings pages
1772 function forceSaveButtonVisible() {
1773 const currentHash = window.location.hash.substring(1);
1774 const saveButton = $('.upk-dashboard-save-btn');
1775
1776 if (pagesWithSave.includes(currentHash)) {
1777 saveButton.show();
1778 }
1779 }
1780
1781 // Initial check
1782 toggleSaveButton();
1783
1784 // Listen for hash changes
1785 $(window).on('hashchange', function() {
1786 toggleSaveButton();
1787 });
1788
1789 // Listen for tab clicks
1790 $('.bdt-dashboard-navigation a').on('click', function() {
1791 setTimeout(toggleSaveButton, 100);
1792 });
1793
1794 // Also listen for navigation menu clicks (from show_navigation())
1795 $(document).on('click', '.bdt-tab a, .bdt-subnav a, .upk-dashboard-nav a, [href*="#ultimate_post_kit"]', function() {
1796 setTimeout(toggleSaveButton, 100);
1797 });
1798
1799 // Listen for bulk active/deactive button clicks to maintain save button visibility
1800 $(document).on('click', '.upk-active-all-widget, .upk-deactive-all-widget', function() {
1801 setTimeout(forceSaveButtonVisible, 50);
1802 });
1803
1804 // Listen for individual checkbox changes to maintain save button visibility
1805 $(document).on('change', '#ultimate_post_kit_elementor_extend_page .checkbox, #ultimate_post_kit_active_modules_page .checkbox', function() {
1806 setTimeout(forceSaveButtonVisible, 50);
1807 });
1808
1809 // Update URL when navigation items are clicked
1810 $(document).on('click', '.bdt-tab a, .bdt-subnav a, .upk-dashboard-nav a', function(e) {
1811 const href = $(this).attr('href');
1812 if (href && href.includes('#')) {
1813 const hash = href.substring(href.indexOf('#'));
1814 if (hash && hash.length > 1) {
1815 // Update browser URL with the hash
1816 const currentUrl = window.location.href.split('#')[0];
1817 const newUrl = currentUrl + hash;
1818 window.history.pushState(null, null, newUrl);
1819
1820 // Trigger hash change event for other listeners
1821 $(window).trigger('hashchange');
1822 }
1823 }
1824 });
1825
1826 // Handle save button click
1827 $(document).on('click', '.ultimate-post-kit-settings-save-btn', function(e) {
1828 e.preventDefault();
1829
1830 // Find the active form in the current tab
1831 const currentHash = window.location.hash.substring(1);
1832 let targetForm = null;
1833
1834 // Look for forms in the active tab content
1835 if (currentHash) {
1836 // Try to find form in the specific tab page
1837 targetForm = $('#' + currentHash + '_page form.settings-save');
1838
1839 // If not found, try without _page suffix
1840 if (!targetForm || targetForm.length === 0) {
1841 targetForm = $('#' + currentHash + ' form.settings-save');
1842 }
1843
1844 // Try to find any form in the active tab content
1845 if (!targetForm || targetForm.length === 0) {
1846 targetForm = $('#' + currentHash + '_page form');
1847 }
1848 }
1849
1850 // Fallback to any visible form with settings-save class
1851 if (!targetForm || targetForm.length === 0) {
1852 targetForm = $('form.settings-save:visible').first();
1853 }
1854
1855 // Last fallback - any visible form
1856 if (!targetForm || targetForm.length === 0) {
1857 targetForm = $('.bdt-switcher .group:visible form').first();
1858 }
1859
1860 if (targetForm && targetForm.length > 0) {
1861 // Show loading notification
1862 // bdtUIkit.notification({
1863 // message: '<div bdt-spinner></div> <?php //esc_html_e('Please wait, Saving settings...', 'ultimate-post-kit') ?>',
1864 // timeout: false
1865 // });
1866
1867 // Submit form using AJAX (same logic as existing form submission)
1868 targetForm.ajaxSubmit({
1869 success: function () {
1870 // Show success message using UIkit notification (same as main settings)
1871 bdtUIkit.notification.closeAll();
1872 bdtUIkit.notification({
1873 message: '<span class="dashicons dashicons-yes"></span> <?php esc_html_e('Settings Saved Successfully.', 'ultimate-post-kit') ?>',
1874 status: 'primary',
1875 pos: 'top-center'
1876 });
1877 },
1878 error: function (data) {
1879 bdtUIkit.notification.closeAll();
1880 bdtUIkit.notification({
1881 message: '<span bdt-icon=\'icon: warning\'></span> <?php esc_html_e('Unknown error, make sure access is correct!', 'ultimate-post-kit') ?>',
1882 status: 'warning'
1883 });
1884 }
1885 });
1886 } else {
1887 // Show error if no form found
1888 bdtUIkit.notification({
1889 message: '<span bdt-icon="icon: warning"></span> <?php esc_html_e('No settings form found to save.', 'ultimate-post-kit') ?>',
1890 status: 'warning'
1891 });
1892 }
1893 });
1894
1895 //White Label Settings Functionality
1896 //Check if upk_admin_ajax is available
1897 if (typeof upk_admin_ajax === 'undefined') {
1898 window.upk_admin_ajax = {
1899 ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
1900 white_label_nonce: '<?php echo wp_create_nonce('upk_white_label_nonce'); ?>'
1901 };
1902 }
1903
1904 // Initialize CodeMirror editors for custom code
1905 var codeMirrorEditors = {};
1906
1907 function initializeCodeMirrorEditors() {
1908 // CSS Editor 1
1909 if (document.getElementById('upk-custom-css')) {
1910 codeMirrorEditors['upk-custom-css'] = wp.codeEditor.initialize('upk-custom-css', {
1911 type: 'text/css',
1912 codemirror: {
1913 lineNumbers: true,
1914 mode: 'css',
1915 theme: 'default',
1916 lineWrapping: true,
1917 autoCloseBrackets: true,
1918 matchBrackets: true,
1919 lint: false
1920 }
1921 });
1922 }
1923
1924 // JavaScript Editor 1
1925 if (document.getElementById('upk-custom-js')) {
1926 codeMirrorEditors['upk-custom-js'] = wp.codeEditor.initialize('upk-custom-js', {
1927 type: 'application/javascript',
1928 codemirror: {
1929 lineNumbers: true,
1930 mode: 'javascript',
1931 theme: 'default',
1932 lineWrapping: true,
1933 autoCloseBrackets: true,
1934 matchBrackets: true,
1935 lint: false
1936 }
1937 });
1938 }
1939
1940 // CSS Editor 2
1941 if (document.getElementById('upk-custom-css-2')) {
1942 codeMirrorEditors['upk-custom-css-2'] = wp.codeEditor.initialize('upk-custom-css-2', {
1943 type: 'text/css',
1944 codemirror: {
1945 lineNumbers: true,
1946 mode: 'css',
1947 theme: 'default',
1948 lineWrapping: true,
1949 autoCloseBrackets: true,
1950 matchBrackets: true,
1951 lint: false
1952 }
1953 });
1954 }
1955
1956 // JavaScript Editor 2
1957 if (document.getElementById('upk-custom-js-2')) {
1958 codeMirrorEditors['upk-custom-js-2'] = wp.codeEditor.initialize('upk-custom-js-2', {
1959 type: 'application/javascript',
1960 codemirror: {
1961 lineNumbers: true,
1962 mode: 'javascript',
1963 theme: 'default',
1964 lineWrapping: true,
1965 autoCloseBrackets: true,
1966 matchBrackets: true,
1967 lint: false
1968 }
1969 });
1970 }
1971
1972 // Refresh all editors after a short delay to ensure proper rendering
1973 setTimeout(function() {
1974 refreshAllCodeMirrorEditors();
1975 }, 100);
1976 }
1977
1978 // Function to refresh all CodeMirror editors
1979 function refreshAllCodeMirrorEditors() {
1980 Object.keys(codeMirrorEditors).forEach(function(editorKey) {
1981 if (codeMirrorEditors[editorKey] && codeMirrorEditors[editorKey].codemirror) {
1982 codeMirrorEditors[editorKey].codemirror.refresh();
1983 }
1984 });
1985 }
1986
1987 // Function to refresh editors when tab becomes visible
1988 function refreshEditorsOnTabShow() {
1989 // Listen for tab changes (UIkit tab switching)
1990 if (typeof bdtUIkit !== 'undefined' && bdtUIkit.tab) {
1991 // When tab becomes active, refresh editors
1992 bdtUIkit.util.on(document, 'shown', '.bdt-tab', function() {
1993 setTimeout(function() {
1994 refreshAllCodeMirrorEditors();
1995 }, 50);
1996 });
1997 }
1998
1999 // Also listen for direct tab clicks
2000 $('.bdt-tab a').on('click', function() {
2001 setTimeout(function() {
2002 refreshAllCodeMirrorEditors();
2003 }, 100);
2004 });
2005
2006 // Listen for switcher changes (UIkit switcher)
2007 if (typeof bdtUIkit !== 'undefined' && bdtUIkit.switcher) {
2008 bdtUIkit.util.on(document, 'shown', '.bdt-switcher', function() {
2009 setTimeout(function() {
2010 refreshAllCodeMirrorEditors();
2011 }, 50);
2012 });
2013 }
2014 }
2015
2016 // Initialize editors when page loads - with delay for better rendering
2017 setTimeout(function() {
2018 initializeCodeMirrorEditors();
2019 }, 100);
2020
2021 // Setup tab switching handlers
2022 setTimeout(function() {
2023 refreshEditorsOnTabShow();
2024 }, 100);
2025
2026 // Handle window resize events
2027 $(window).on('resize', function() {
2028 setTimeout(function() {
2029 refreshAllCodeMirrorEditors();
2030 }, 100);
2031 });
2032
2033 // Handle page visibility changes (when switching browser tabs)
2034 document.addEventListener('visibilitychange', function() {
2035 if (!document.hidden) {
2036 setTimeout(function() {
2037 refreshAllCodeMirrorEditors();
2038 }, 200);
2039 }
2040 });
2041
2042 // Force refresh when clicking on the Custom CSS & JS tab specifically
2043 $('a[href="#"]').on('click', function() {
2044 var tabText = $(this).text().trim();
2045 if (tabText === 'Custom CSS & JS') {
2046 setTimeout(function() {
2047 refreshAllCodeMirrorEditors();
2048 }, 150);
2049 }
2050 });
2051
2052 //Toggle white label fields visibility
2053 $('#upk-white-label-enabled').on('change', function() {
2054 if ($(this).is(':checked')) {
2055 $('.upk-white-label-fields').slideDown(300);
2056 } else {
2057 $('.upk-white-label-fields').slideUp(300);
2058 }
2059 });
2060
2061 //WordPress Media Library Integration for Icon Upload
2062 var mediaUploader;
2063
2064 $('#upk-upload-icon').on('click', function(e) {
2065 e.preventDefault();
2066
2067 // If the uploader object has already been created, reopen the dialog
2068 if (mediaUploader) {
2069 mediaUploader.open();
2070 return;
2071 }
2072
2073 // Create the media frame
2074 mediaUploader = wp.media.frames.file_frame = wp.media({
2075 title: 'Select Icon',
2076 button: {
2077 text: 'Use This Icon'
2078 },
2079 library: {
2080 type: ['image/jpeg', 'image/jpg', 'image/png', 'image/svg+xml']
2081 },
2082 multiple: false
2083 });
2084
2085 // When an image is selected, run a callback
2086 mediaUploader.on('select', function() {
2087 var attachment = mediaUploader.state().get('selection').first().toJSON();
2088
2089 // Set the hidden inputs
2090 $('#upk-white-label-icon').val(attachment.url);
2091 $('#upk-white-label-icon-id').val(attachment.id);
2092
2093 // Update preview
2094 $('#upk-icon-preview-img').attr('src', attachment.url);
2095 $('.upk-icon-preview-container').show();
2096 });
2097
2098 // Open the uploader dialog
2099 mediaUploader.open();
2100 });
2101
2102 //Remove icon functionality
2103 $('#upk-remove-icon').on('click', function(e) {
2104 e.preventDefault();
2105
2106 // Clear the hidden inputs
2107 $('#upk-white-label-icon').val('');
2108 $('#upk-white-label-icon-id').val('');
2109
2110 // Hide preview
2111 $('.upk-icon-preview-container').hide();
2112 $('#upk-icon-preview-img').attr('src', '');
2113 });
2114
2115 // WordPress Media Library Integration for Logo Upload
2116 var logoUploader;
2117
2118 $('#upk-upload-logo').on('click', function(e) {
2119 e.preventDefault();
2120
2121 // If the uploader object has already been created, reopen the dialog
2122 if (logoUploader) {
2123 logoUploader.open();
2124 return;
2125 }
2126
2127 // Create the media frame
2128 logoUploader = wp.media.frames.file_frame = wp.media({
2129 title: 'Select Logo',
2130 button: {
2131 text: 'Use This Logo'
2132 },
2133 library: {
2134 type: ['image/jpeg', 'image/jpg', 'image/png', 'image/svg+xml']
2135 },
2136 multiple: false
2137 });
2138
2139 // When an image is selected, run a callback
2140 logoUploader.on('select', function() {
2141 var attachment = logoUploader.state().get('selection').first().toJSON();
2142
2143 // Set the hidden inputs
2144 $('#upk-white-label-logo').val(attachment.url);
2145 $('#upk-white-label-logo-id').val(attachment.id);
2146
2147 // Update preview
2148 $('#upk-logo-preview-img').attr('src', attachment.url);
2149 $('.upk-logo-preview-container').show();
2150 });
2151
2152 // Open the uploader dialog
2153 logoUploader.open();
2154 });
2155
2156 // Remove logo functionality
2157 $('#upk-remove-logo').on('click', function(e) {
2158 e.preventDefault();
2159
2160 // Clear the hidden inputs
2161 $('#upk-white-label-logo').val('');
2162 $('#upk-white-label-logo-id').val('');
2163
2164 // Hide preview
2165 $('.upk-logo-preview-container').hide();
2166 $('#upk-logo-preview-img').attr('src', '');
2167 });
2168
2169 //BDTUPK_HIDE Warning when checkbox is enabled
2170 $('#upk-white-label-bdtupk-hide').on('change', function() {
2171 if ($(this).is(':checked')) {
2172 // Show warning modal/alert
2173 var warningMessage = '⚠️ WARNING: ADVANCED FEATURE\n\n' +
2174 'Enabling BDTUPK_HIDE will activate advanced white label mode that:\n\n' +
2175 '• Hides ALL Element Pack branding and menus\n' +
2176 '• Makes these settings difficult to access later\n' +
2177 '• Requires the special access link to return\n' +
2178 '• Is intended for client/agency use only\n\n' +
2179 'An email with access instructions will be sent if you proceed.\n\n' +
2180 'Are you sure you want to enable this advanced mode?';
2181
2182 if (!confirm(warningMessage)) {
2183 // User cancelled, uncheck the box
2184 $(this).prop('checked', false);
2185 return false;
2186 }
2187
2188 // Show additional info message
2189 if ($('#upk-bdtupk-hide-info').length === 0) {
2190 $(this).closest('.upk-option-item').after(
2191 '<div id="upk-bdtupk-hide-info" class="bdt-alert bdt-alert-warning bdt-margin-small-top">' +
2192 '<p><strong>BDTUPK_HIDE Mode Enabled</strong></p>' +
2193 '<p>When you save these settings, an email will be sent with instructions to access white label settings in the future.</p>' +
2194 '</div>'
2195 );
2196 }
2197 } else {
2198 // Remove info message when unchecked
2199 $('#upk-bdtupk-hide-info').remove();
2200 }
2201 });
2202
2203 // Save white label settings with confirmation
2204 $('#upk-save-white-label').on('click', function(e) {
2205 e.preventDefault();
2206
2207 // Check if button is disabled (no license or no white label eligible license)
2208 if ($(this).prop('disabled')) {
2209 var buttonText = $(this).text().trim();
2210 var alertMessage = '';
2211
2212 if (buttonText.includes('License Not Activated')) {
2213 alertMessage = '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2214 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2215 '<p><strong>License Not Activated</strong><br>You need to activate your Ultimate Post Kit license to access White Label functionality. Please activate your license first.</p>' +
2216 '</div>';
2217 } else {
2218 alertMessage = '<div class="bdt-alert bdt-alert-warning" bdt-alert>' +
2219 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2220 '<p><strong>Eligible License Required</strong><br>White Label functionality is available for Agency, Extended, Developer, AppSumo Lifetime, and other eligible license holders. Please upgrade your license to access these features.</p>' +
2221 '</div>';
2222 }
2223
2224 $('#upk-white-label-message').html(alertMessage).show();
2225 return false;
2226 }
2227
2228 // Check if white label mode is being enabled
2229 var whiteLabelEnabled = $('#upk-white-label-enabled').is(':checked');
2230 var bdtupkHideEnabled = $('#upk-white-label-bdtupk-hide').is(':checked');
2231
2232 // Only show confirmation dialog if white label is enabled AND BDTUPK_HIDE is enabled
2233 if (whiteLabelEnabled && bdtupkHideEnabled) {
2234 var confirmMessage = '🔒 FINAL CONFIRMATION\n\n' +
2235 'You are about to save settings with BDTUPK_HIDE enabled.\n\n' +
2236 'This will:\n' +
2237 '• Hide Ultimate Post Kit from WordPress admin immediately\n' +
2238 '• Send access instructions to your email addresses\n' +
2239 '• Require the special link to modify these settings\n\n' +
2240 'Email will be sent to:\n' +
2241 '• License email: <?php echo esc_js(self::get_license_email()); ?>\n' +
2242 'Are you absolutely sure you want to proceed?';
2243
2244 if (!confirm(confirmMessage)) {
2245 return false;
2246 }
2247 }
2248
2249 var $button = $(this);
2250 var originalText = $button.html();
2251
2252 // Show loading state
2253 $button.html('Saving...');
2254 $button.prop('disabled', true);
2255
2256 // Collect form data
2257 var formData = {
2258 action: 'upk_save_white_label',
2259 nonce: upk_admin_ajax.white_label_nonce,
2260 upk_white_label_enabled: $('#upk-white-label-enabled').is(':checked') ? 1 : 0,
2261 upk_white_label_title: $('#upk-white-label-title').val(),
2262 upk_white_label_icon: $('#upk-white-label-icon').val(),
2263 upk_white_label_icon_id: $('#upk-white-label-icon-id').val(),
2264 upk_white_label_logo: $('#upk-white-label-logo').val(),
2265 upk_white_label_logo_id: $('#upk-white-label-logo-id').val(),
2266 upk_white_label_hide_license: $('#upk-white-label-hide-license').is(':checked') ? 1 : 0,
2267 upk_white_label_bdtupk_hide: $('#upk-white-label-bdtupk-hide').is(':checked') ? 1 : 0
2268 };
2269
2270 // Send AJAX request
2271 $.post(upk_admin_ajax.ajax_url, formData)
2272 .done(function(response) {
2273 if (response.success) {
2274 // Show success message with countdown
2275 var countdown = 2;
2276 var successMessage = response.data.message;
2277
2278 // Add email notification info if BDTUPK_HIDE was enabled
2279 if (response.data.bdtupk_hide && response.data.email_sent) {
2280 successMessage += '<br><br><strong>📧 Access Email Sent!</strong><br>Check your email for the access link to modify these settings in the future.';
2281 } else if (response.data.bdtupk_hide && !response.data.email_sent && response.data.access_url) {
2282 // Localhost scenario - show the access URL directly
2283 successMessage += '<br><br><strong>📧 Localhost Email Notice:</strong><br>Email functionality is not available on localhost.<br><strong>Your Access URL:</strong><br><a href="' + response.data.access_url + '" target="_blank">Click here to access white label settings</a><br><small>Save this URL - you\'ll need it to modify settings when BDTUPK_HIDE is active.</small>';
2284 } else if (response.data.bdtupk_hide && !response.data.email_sent) {
2285 successMessage += '<br><br><strong>⚠️ Email Notice:</strong><br>There was an issue sending the access email. Please check your email settings or contact support.';
2286 }
2287
2288 $('#upk-white-label-message').html(
2289 '<div class="bdt-alert bdt-alert-success" bdt-alert>' +
2290 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2291 '<p>' + successMessage + ' <span id="upk-reload-countdown">Reloading in ' + countdown + ' seconds...</span></p>' +
2292 '</div>'
2293 ).show();
2294
2295 // Update button text
2296 $button.html('Reloading...');
2297
2298 // Countdown timer
2299 var countdownInterval = setInterval(function() {
2300 countdown--;
2301 if (countdown > 0) {
2302 $('#upk-reload-countdown').text('Reloading in ' + countdown + ' seconds...');
2303 } else {
2304 $('#upk-reload-countdown').text('Reloading now...');
2305 clearInterval(countdownInterval);
2306 }
2307 }, 1000);
2308
2309 // Check if BDTUPK_HIDE is enabled and redirect accordingly
2310 setTimeout(function() {
2311 if (response.data.bdtupk_hide) {
2312 // Redirect to admin dashboard if BDTUPK_HIDE is enabled
2313 window.location.href = '<?php echo admin_url('index.php'); ?>';
2314 } else {
2315 // Reload current page if BDTUPK_HIDE is not enabled
2316 window.location.reload();
2317 }
2318 }, 1500);
2319 } else {
2320 // Show error message
2321 $('#upk-white-label-message').html(
2322 '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2323 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2324 '<p>Error: ' + (response.data.message || 'Unknown error occurred') + '</p>' +
2325 '</div>'
2326 ).show();
2327
2328 // Restore button state for error case
2329 $button.html(originalText);
2330 $button.prop('disabled', false);
2331 }
2332 })
2333 .fail(function(xhr, status, error) {
2334 // Show error message
2335 $('#upk-white-label-message').html(
2336 '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2337 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2338 '<p>Error: Failed to save settings. Please try again. (' + status + ')</p>' +
2339 '</div>'
2340 ).show();
2341
2342 // Restore button state for failure case
2343 $button.html(originalText);
2344 $button.prop('disabled', false);
2345 });
2346 });
2347
2348 // Save custom code functionality (updated for CodeMirror)
2349 $('#upk-save-custom-code').on('click', function(e) {
2350 e.preventDefault();
2351
2352 var $button = $(this);
2353 var originalText = $button.html();
2354
2355 // Check if upk_admin_ajax is available
2356 if (typeof upk_admin_ajax === 'undefined') {
2357 $('#upk-custom-code-message').html(
2358 '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2359 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2360 '<p>Error: AJAX configuration not loaded. Please refresh the page and try again.</p>' +
2361 '</div>'
2362 ).show();
2363 return;
2364 }
2365
2366 // Prevent multiple simultaneous saves
2367 if ($button.prop('disabled') || $button.hasClass('upk-saving')) {
2368 return;
2369 }
2370
2371 // Mark as saving
2372 $button.addClass('upk-saving');
2373
2374 // Get content from CodeMirror editors
2375 function getCodeMirrorContent(elementId) {
2376 if (codeMirrorEditors[elementId] && codeMirrorEditors[elementId].codemirror) {
2377 return codeMirrorEditors[elementId].codemirror.getValue();
2378 } else {
2379 // Fallback to textarea value
2380 return $('#' + elementId).val() || '';
2381 }
2382 }
2383
2384 var cssContent = getCodeMirrorContent('upk-custom-css');
2385 var jsContent = getCodeMirrorContent('upk-custom-js');
2386 var css2Content = getCodeMirrorContent('upk-custom-css-2');
2387 var js2Content = getCodeMirrorContent('upk-custom-js-2');
2388
2389 // Show loading state
2390 $button.prop('disabled', true);
2391
2392 // Timeout safeguard - if AJAX doesn't complete in 30 seconds, restore button
2393 var timeoutId = setTimeout(function() {
2394 $button.removeClass('upk-saving');
2395 $button.html(originalText);
2396 $button.prop('disabled', false);
2397 $('#upk-custom-code-message').html(
2398 '<div class="bdt-alert bdt-alert-warning" bdt-alert>' +
2399 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2400 '<p>Save operation timed out. Please try again.</p>' +
2401 '</div>'
2402 ).show();
2403 }, 30000);
2404
2405 // Collect form data
2406 var formData = {
2407 action: 'upk_save_custom_code',
2408 nonce: upk_admin_ajax.nonce,
2409 custom_css: cssContent,
2410 custom_js: jsContent,
2411 custom_css_2: css2Content,
2412 custom_js_2: js2Content,
2413 excluded_pages: $('#upk-excluded-pages').val() || []
2414 };
2415
2416
2417 // Verify we have some content before sending (optional check)
2418 var totalContentLength = cssContent.length + jsContent.length + css2Content.length + js2Content.length;
2419 if (totalContentLength === 0) {
2420 var confirmEmpty = confirm('No content detected in any editor. Do you want to save empty content (this will clear all custom code)?');
2421 if (!confirmEmpty) {
2422 // Restore button state
2423 $button.html(originalText);
2424 $button.prop('disabled', false);
2425 return;
2426 }
2427 }
2428
2429 // Send AJAX request
2430 $.post(upk_admin_ajax.ajax_url, formData)
2431 .done(function(response) {
2432 console.log('AJAX Response:', response); // Debug log
2433
2434 if (response && response.success) {
2435 // Show success message
2436 var successMessage = response.data.message;
2437 if (response.data.excluded_count) {
2438 successMessage += ' (' + response.data.excluded_count + ' pages excluded)';
2439 }
2440
2441 $('#upk-custom-code-message').html(
2442 '<div class="bdt-alert bdt-alert-success" bdt-alert>' +
2443 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2444 '<p>' + successMessage + '</p>' +
2445 '</div>'
2446 ).show();
2447
2448 // Auto-hide message after 5 seconds
2449 setTimeout(function() {
2450 $('#upk-custom-code-message').fadeOut();
2451 }, 5000);
2452
2453 } else {
2454 // Show error message
2455 var errorMessage = 'Unknown error occurred';
2456 if (response && response.data && response.data.message) {
2457 errorMessage = response.data.message;
2458 } else if (response && response.message) {
2459 errorMessage = response.message;
2460 }
2461
2462 $('#upk-custom-code-message').html(
2463 '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2464 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2465 '<p>Error: ' + errorMessage + '</p>' +
2466 '</div>'
2467 ).show();
2468 }
2469 })
2470 .fail(function(xhr, status, error) {
2471 console.log('AJAX Error:', xhr, status, error); // Debug log
2472
2473 // Try to parse error response
2474 var errorMessage = 'Failed to save custom code. Please try again.';
2475 try {
2476 var errorResponse = JSON.parse(xhr.responseText);
2477 if (errorResponse.data && errorResponse.data.message) {
2478 errorMessage = errorResponse.data.message;
2479 } else if (errorResponse.message) {
2480 errorMessage = errorResponse.message;
2481 }
2482 } catch (e) {
2483 // Use default error message
2484 }
2485
2486 // Show error message
2487 $('#upk-custom-code-message').html(
2488 '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2489 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2490 '<p>Error: ' + errorMessage + ' (' + status + ')</p>' +
2491 '</div>'
2492 ).show();
2493 })
2494 .always(function() {
2495
2496 // Clear the timeout since AJAX completed
2497 clearTimeout(timeoutId);
2498
2499 try {
2500 $button.removeClass('upk-saving');
2501 $button.html(originalText);
2502 $button.prop('disabled', false);
2503 } catch (e) {
2504 // Fallback: force button restoration
2505 $('#upk-save-custom-code').removeClass('upk-saving').html('<span class="dashicons dashicons-yes"></span> Save Custom Code').prop('disabled', false);
2506 }
2507 });
2508 });
2509
2510 // Reset custom code functionality (updated for CodeMirror)
2511 $('#upk-reset-custom-code').on('click', function(e) {
2512 e.preventDefault();
2513
2514 if (confirm('Are you sure you want to reset all custom code? This will clear all code.')) {
2515 var $button = $(this);
2516 var originalText = $button.html();
2517
2518 // Clear CodeMirror editors
2519 function clearCodeMirrorEditor(elementId) {
2520 if (codeMirrorEditors[elementId] && codeMirrorEditors[elementId].codemirror) {
2521 codeMirrorEditors[elementId].codemirror.setValue('');
2522 } else {
2523 // Fallback to clearing textarea
2524 $('#' + elementId).val('');
2525 }
2526 }
2527
2528 // Clear all editors
2529 clearCodeMirrorEditor('upk-custom-css');
2530 clearCodeMirrorEditor('upk-custom-js');
2531 clearCodeMirrorEditor('upk-custom-css-2');
2532 clearCodeMirrorEditor('upk-custom-js-2');
2533
2534 // Clear exclusions
2535 $('#upk-excluded-pages').val([]).trigger('change');
2536
2537 // Show clearing message
2538 $('#upk-custom-code-message').html(
2539 '<div class="bdt-alert bdt-alert-primary" bdt-alert>' +
2540 '<p><span bdt-spinner="ratio: 0.6"></span> Clearing custom code...</p>' +
2541 '</div>'
2542 ).show();
2543
2544 // Disable button during save
2545 $button.prop('disabled', true).html('<span bdt-spinner="ratio: 0.6"></span> Resetting...');
2546
2547 // Prepare empty data for AJAX save
2548 var formData = {
2549 action: 'upk_save_custom_code',
2550 nonce: upk_admin_ajax.nonce,
2551 custom_css: '',
2552 custom_js: '',
2553 custom_css_2: '',
2554 custom_js_2: '',
2555 excluded_pages: []
2556 };
2557
2558 // Send AJAX request to save empty values
2559 $.ajax({
2560 url: upk_admin_ajax.ajax_url,
2561 type: 'POST',
2562 data: formData,
2563 timeout: 30000,
2564 success: function(response) {
2565 if (response.success) {
2566 // Show success message
2567 $('#upk-custom-code-message').html(
2568 '<div class="bdt-alert bdt-alert-success" bdt-alert>' +
2569 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2570 '<p><span class="dashicons dashicons-yes"></span> All custom code has been reset successfully!</p>' +
2571 '</div>'
2572 ).show();
2573
2574 // Auto-hide message after 5 seconds
2575 setTimeout(function() {
2576 $('#upk-custom-code-message').fadeOut();
2577 }, 5000);
2578 } else {
2579 // Show error message
2580 $('#upk-custom-code-message').html(
2581 '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2582 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2583 '<p><span class="dashicons dashicons-warning"></span> ' + (response.data.message || 'Failed to save reset. Please try again.') + '</p>' +
2584 '</div>'
2585 ).show();
2586 }
2587
2588 // Restore button
2589 $button.prop('disabled', false).html(originalText);
2590 },
2591 error: function(xhr, status, error) {
2592 // Show error message
2593 $('#upk-custom-code-message').html(
2594 '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2595 '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2596 '<p><span class="dashicons dashicons-warning"></span> Failed to save reset: ' + error + '</p>' +
2597 '</div>'
2598 ).show();
2599
2600 // Restore button
2601 $button.prop('disabled', false).html(originalText);
2602 }
2603 });
2604 }
2605 });
2606 });
2607
2608 // Chart.js initialization for system status canvas charts
2609 function initUltimatePostKitCharts() {
2610 // Wait for Chart.js to be available
2611 if (typeof Chart === 'undefined') {
2612 setTimeout(initUltimatePostKitCharts, 500);
2613 return;
2614 }
2615
2616 // Chart instances storage
2617 window.upkChartInstances = window.upkChartInstances || {};
2618 window.upkChartsInitialized = false;
2619
2620 // Function to create a chart
2621 function createChart(canvasId) {
2622 var canvas = document.getElementById(canvasId);
2623 if (!canvas) {
2624 return;
2625 }
2626
2627 var $canvas = jQuery('#' + canvasId);
2628 var valueStr = $canvas.data('value');
2629 var labelsStr = $canvas.data('labels');
2630 var bgStr = $canvas.data('bg');
2631
2632 if (!valueStr || !labelsStr || !bgStr) {
2633 return;
2634 }
2635
2636 // Parse data
2637 var values = valueStr.toString().split(',').map(v => parseInt(v.trim()) || 0);
2638 var labels = labelsStr.toString().split(',').map(l => l.trim());
2639 var colors = bgStr.toString().split(',').map(c => c.trim());
2640
2641 // Destroy existing chart using Chart.js built-in method
2642 var existingChart = Chart.getChart(canvas);
2643 if (existingChart) {
2644 existingChart.destroy();
2645 }
2646
2647 // Also destroy from our instance storage
2648 if (window.upkChartInstances && window.upkChartInstances[canvasId]) {
2649 window.upkChartInstances[canvasId].destroy();
2650 delete window.upkChartInstances[canvasId];
2651 }
2652
2653 // Create new chart
2654 try {
2655 var newChart = new Chart(canvas, {
2656 type: 'doughnut',
2657 data: {
2658 labels: labels,
2659 datasets: [{
2660 data: values,
2661 backgroundColor: colors,
2662 borderWidth: 0
2663 }]
2664 },
2665 options: {
2666 responsive: true,
2667 maintainAspectRatio: false,
2668 plugins: {
2669 legend: { display: false },
2670 tooltip: { enabled: true }
2671 },
2672 cutout: '60%'
2673 }
2674 });
2675
2676 // Store in our instance storage
2677 if (!window.upkChartInstances) window.upkChartInstances = {};
2678 window.upkChartInstances[canvasId] = newChart;
2679 } catch (error) {
2680 // Do nothing
2681 }
2682 }
2683
2684 // Update total widgets status
2685 function updateTotalStatus() {
2686 var coreCount = jQuery('#ultimate_post_kit_active_modules_page input:checked').length;
2687 var extensionsCount = jQuery('#ultimate_post_kit_elementor_extend_page input:checked').length;
2688
2689 jQuery('#bdt-total-widgets-status-core').text(coreCount);
2690 jQuery('#bdt-total-widgets-status-extensions').text(extensionsCount);
2691 jQuery('#bdt-total-widgets-status-heading').text(coreCount + extensionsCount);
2692
2693 jQuery('#bdt-total-widgets-status').attr('data-value', [coreCount, extensionsCount].join(','));
2694 }
2695
2696 // Initialize all charts once
2697 function initAllCharts() {
2698 // Check if charts already exist and are properly rendered
2699 if (window.upkChartInstances && Object.keys(window.upkChartInstances).length >= 4) {
2700 return;
2701 }
2702
2703 // Update total status first
2704 updateTotalStatus();
2705
2706 // Create all charts
2707 var chartCanvases = [
2708 'bdt-db-total-status',
2709 'bdt-db-only-widget-status',
2710 'bdt-total-widgets-status'
2711 ];
2712
2713 var successfulCharts = 0;
2714 chartCanvases.forEach(function(canvasId) {
2715 var canvas = document.getElementById(canvasId);
2716 if (canvas && canvas.offsetParent !== null) { // Check if canvas is visible
2717 createChart(canvasId);
2718 if (window.upkChartInstances && window.upkChartInstances[canvasId]) {
2719 successfulCharts++;
2720 }
2721 }
2722 });
2723 }
2724
2725 // Check if we're currently on system status tab and initialize
2726 function checkAndInitIfOnSystemStatus() {
2727 if (window.location.hash === '#ultimate_post_kit_analytics_system_req') {
2728 setTimeout(initAllCharts, 300);
2729 }
2730 }
2731
2732 // Initialize charts when DOM is ready
2733 jQuery(document).ready(function() {
2734 // Only initialize if we're on the system status tab
2735 setTimeout(checkAndInitIfOnSystemStatus, 500);
2736 });
2737
2738 // Add click handler for System Status tab to create/refresh charts
2739 jQuery(document).on('click', 'a[href="#ultimate_post_kit_analytics_system_req"], a[href*="ultimate_post_kit_analytics_system_req"]', function() {
2740 setTimeout(function() {
2741 // Always recreate charts when tab is clicked to ensure they're visible
2742 initAllCharts();
2743 }, 200);
2744 });
2745 }
2746
2747 // Start the chart initialization
2748 setTimeout(initUltimatePostKitCharts, 1000);
2749
2750 // Handle plugin installation via AJAX
2751 jQuery(document).on('click', '.upk-install-plugin', function(e) {
2752 e.preventDefault();
2753
2754 var $button = jQuery(this);
2755 var pluginSlug = $button.data('plugin-slug');
2756 var nonce = $button.data('nonce');
2757 var originalText = $button.text();
2758
2759 // Disable button and show loading state
2760 $button.prop('disabled', true)
2761 .text('<?php echo esc_js(__('Installing...', 'ultimate-post-kit')); ?>')
2762 .addClass('bdt-installing');
2763
2764 // Perform AJAX request
2765 jQuery.ajax({
2766 url: '<?php echo admin_url('admin-ajax.php'); ?>',
2767 type: 'POST',
2768 data: {
2769 action: 'upk_install_plugin',
2770 plugin_slug: pluginSlug,
2771 nonce: nonce
2772 },
2773 success: function(response) {
2774 if (response.success) {
2775 // Show success message
2776 $button.text('<?php echo esc_js(__('Installed!', 'ultimate-post-kit')); ?>')
2777 .removeClass('bdt-installing')
2778 .addClass('bdt-installed');
2779
2780 // Show success notification
2781 if (typeof bdtUIkit !== 'undefined' && bdtUIkit.notification) {
2782 bdtUIkit.notification({
2783 message: '<span class="dashicons dashicons-yes"></span> ' + response.data.message,
2784 status: 'success'
2785 });
2786 }
2787
2788 // Reload the page after 2 seconds to update button states
2789 setTimeout(function() {
2790 window.location.reload();
2791 }, 2000);
2792
2793 } else {
2794 // Show error message
2795 $button.prop('disabled', false)
2796 .text(originalText)
2797 .removeClass('bdt-installing');
2798
2799 // Show error notification
2800 if (typeof bdtUIkit !== 'undefined' && bdtUIkit.notification) {
2801 bdtUIkit.notification({
2802 message: '<span class="dashicons dashicons-warning"></span> ' + response.data.message,
2803 status: 'danger'
2804 });
2805 }
2806 }
2807 },
2808 error: function() {
2809 // Handle network/server errors
2810 $button.prop('disabled', false)
2811 .text(originalText)
2812 .removeClass('bdt-installing');
2813
2814 // Show error notification
2815 if (typeof bdtUIkit !== 'undefined' && bdtUIkit.notification) {
2816 bdtUIkit.notification({
2817 message: '<span class="dashicons dashicons-warning"></span> <?php echo esc_js(__('Installation failed. Please try again.', 'ultimate-post-kit')); ?>',
2818 status: 'danger'
2819 });
2820 }
2821 }
2822 });
2823 });
2824
2825 // Show/hide white label & custom code save button based on active tab
2826 function toggleWhiteLabelSaveButton() {
2827
2828 // Check if we're on the extra options page
2829 if (window.location.hash === '#ultimate_post_kit_extra_options') {
2830 // Target specifically the tabs within the Extra Options section
2831 var extraOptionsTabs = jQuery('.upk-extra-options-tabs .bdt-tab li.bdt-active');
2832 var activeTab = extraOptionsTabs.index();
2833
2834 if (activeTab === 1) { // White Label tab is the second tab (index 1)
2835 jQuery('.upk-white-label-save-section').show();
2836 jQuery('.upk-code-save-section').hide();
2837 } else {
2838 jQuery('.upk-white-label-save-section').hide();
2839 jQuery('.upk-code-save-section').show();
2840 }
2841 } else {
2842 jQuery('.upk-white-label-save-section').hide();
2843 jQuery('.upk-code-save-section').hide();
2844 }
2845 }
2846
2847 // Wait for jQuery to be ready
2848 jQuery(document).ready(function($) {
2849
2850 // Check if we should automatically switch to White Label tab
2851 var urlParams = new URLSearchParams(window.location.search);
2852 if (urlParams.get('white_label_tab') === '1') {
2853 // Wait a bit for UIkit to be ready, then switch to White Label tab
2854 setTimeout(function() {
2855 // Use UIkit's API to switch to the second tab (index 1)
2856 var tabElement = document.querySelector('.upk-extra-options-tabs [bdt-tab]');
2857 if (tabElement && typeof UIkit !== 'undefined') {
2858 UIkit.tab(tabElement).show(1); // Show tab at index 1 (White Label tab)
2859 } else {
2860 // Fallback: simply click the White Label tab link
2861 var whiteLabelTab = $('.upk-extra-options-tabs .bdt-tab li').eq(1);
2862 if (whiteLabelTab.length > 0) {
2863 whiteLabelTab.find('a')[0].click(); // Use native click
2864 }
2865 }
2866
2867 // Check button visibility after tab switch
2868 setTimeout(function() {
2869 toggleWhiteLabelSaveButton();
2870 }, 300);
2871 }, 800);
2872 } else {
2873 toggleWhiteLabelSaveButton();
2874 }
2875
2876 // Check on hash change (when navigating to extra options page)
2877 $(window).on('hashchange', function() {
2878 toggleWhiteLabelSaveButton();
2879 });
2880
2881 // Listen for UIkit tab changes using multiple methods
2882 $(document).on('click', '.bdt-tab li a', function() {
2883 setTimeout(function() {
2884 toggleWhiteLabelSaveButton();
2885 }, 200);
2886 });
2887
2888 // Listen for UIkit's internal tab change events
2889 $(document).on('shown', '[bdt-tab]', function() {
2890 setTimeout(function() {
2891 toggleWhiteLabelSaveButton();
2892 }, 200);
2893 });
2894
2895 // Also listen for the specific tab content changes
2896 $(document).on('show', '#upk-extra-options-tab-content > div', function() {
2897 setTimeout(function() {
2898 toggleWhiteLabelSaveButton();
2899 }, 200);
2900 });
2901
2902 // Alternative: Check periodically for tab changes
2903 setInterval(function() {
2904 if (window.location.hash === '#ultimate_post_kit_extra_options') {
2905 var currentActiveTab = $('.bdt-tab li.bdt-active').index();
2906 if (typeof window.lastActiveTab === 'undefined') {
2907 window.lastActiveTab = currentActiveTab;
2908 } else if (window.lastActiveTab !== currentActiveTab) {
2909 window.lastActiveTab = currentActiveTab;
2910 toggleWhiteLabelSaveButton();
2911 }
2912 }
2913 }, 500);
2914 });
2915
2916 </script>
2917 <?php
2918 }
2919
2920 /**
2921 * Display Footer
2922 *
2923 * @access public
2924 * @return void
2925 */
2926
2927 function footer_info() {
2928 ?>
2929
2930 <div class="ultimate-post-kit-footer-info bdt-margin-medium-top">
2931
2932 <div class="bdt-grid ">
2933
2934 <div class="bdt-width-auto@s upk-setting-save-btn">
2935
2936
2937
2938 </div>
2939
2940 <div class="bdt-width-expand@s bdt-text-right">
2941 <p class="">
2942 Ultimate Post Kit Pro plugin made with love by <a target="_blank" href="https://bdthemes.com">BdThemes</a> Team.
2943 <br>All rights reserved by <a target="_blank" href="https://bdthemes.com">BdThemes.com</a>.
2944 </p>
2945 </div>
2946 </div>
2947
2948 </div>
2949
2950 <?php
2951 }
2952
2953 /**
2954 * Get all the pages
2955 *
2956 * @return array page names with key value pairs
2957 */
2958 function get_pages() {
2959 $pages = get_pages();
2960 $pages_options = [];
2961 if ($pages) {
2962 foreach ($pages as $page) {
2963 $pages_options[$page->ID] = $page->post_title;
2964 }
2965 }
2966
2967 return $pages_options;
2968 }
2969
2970 /**
2971 * Check if current license supports white label features
2972 * Now includes other_param checking for AppSumo WL flag
2973 *
2974 * @access public static
2975 * @return bool
2976 */
2977 public static function is_white_label_license() {
2978 // Check if pro version is activated first
2979 if (!function_exists('_is_upk_pro_activated') || !_is_upk_pro_activated()) {
2980 return false;
2981 }
2982
2983 // Since UltimatePostKitPro\Base doesn't exist, return false for now
2984 // This should be replaced with actual pro license checking logic when available
2985 $license_info = UltimatePostKitPro\Base\Ultimate_Post_Kit_Base::GetRegisterInfo();
2986
2987 // Security: Validate license info structure
2988 if (empty($license_info) ||
2989 !is_object($license_info) ||
2990 empty($license_info->license_title) ||
2991 empty($license_info->is_valid)) {
2992 return false;
2993 }
2994
2995 // Sanitize license title to prevent any potential issues
2996 $license_title = sanitize_text_field(strtolower($license_info->license_title));
2997
2998 // Check for other_param WL flag FIRST (for AppSumo and other special licenses)
2999 if (!empty($license_info->other_param)) {
3000 // Check if other_param contains WL flag
3001 if (is_array($license_info->other_param)) {
3002 if (in_array('WL', $license_info->other_param, true)) {
3003 return true;
3004 }
3005 } elseif (is_string($license_info->other_param)) {
3006 if (strpos($license_info->other_param, 'WL') !== false) {
3007 return true;
3008 }
3009 }
3010 }
3011
3012 // Check standard license types (but NOT AppSumo - AppSumo requires WL flag)
3013 $allowed_types = self::get_white_label_allowed_license_types();
3014 $allowed_hashes = array_values($allowed_types);
3015
3016 // Split license title into words and check each word
3017 $words = preg_split('/\s+/', $license_title, -1, PREG_SPLIT_NO_EMPTY);
3018 foreach ($words as $word) {
3019 $word = trim($word);
3020 if (empty($word) || strlen($word) > 50) { // Prevent extremely long strings
3021 continue;
3022 }
3023
3024 // Use SHA-256 for enhanced security
3025 $hash = hash('sha256', $word);
3026 if (in_array($hash, $allowed_hashes, true)) { // Strict comparison
3027 return true;
3028 }
3029 }
3030
3031 return false;
3032 }
3033
3034 /**
3035 * Render White Label Section
3036 *
3037 * @access public
3038 * @return void
3039 */
3040 public function render_white_label_section() {
3041 //// Safely check if helper functions exist
3042 $is_pro_installed = function_exists('_is_upk_pro_installed') ? _is_upk_pro_installed() : false;
3043 $is_pro_activated = function_exists('_is_upk_pro_activated') ? _is_upk_pro_activated() : false;
3044
3045 // Define plugin slug (adjust if needed)
3046 $plugin_slug = 'ultimate-post-kit-pro/ultimate-post-kit-pro.php';
3047
3048 // Case 1: Pro not installed
3049 if ( ! $is_pro_installed ) : ?>
3050 <div class="bdt-alert bdt-alert-danger bdt-margin-medium-top" bdt-alert>
3051 <p><?php esc_html_e( 'Ultimate Post Kit Pro is not installed. Please install it to access White Label functionality.', 'ultimate-post-kit' ); ?></p>
3052 <div class="bdt-margin-small-top">
3053 <a href="https://postkit.pro/pricing/" target="_blank" class="bdt-button bdt-btn-blue">
3054 <?php esc_html_e( 'Get Pro', 'ultimate-post-kit' ); ?>
3055 </a>
3056 </div>
3057 </div>
3058 <?php
3059 return;
3060 endif;
3061
3062 // Case 2: Installed but not active
3063 if ( $is_pro_installed && ! $is_pro_activated ) :
3064 // Generate secure activation link
3065 $activate_url = wp_nonce_url(
3066 add_query_arg(
3067 array(
3068 'action' => 'activate',
3069 'plugin' => $plugin_slug,
3070 ),
3071 admin_url( 'plugins.php' )
3072 ),
3073 'activate-plugin_' . $plugin_slug
3074 );
3075 ?>
3076 <div class="bdt-alert bdt-alert-warning bdt-margin-medium-top" bdt-alert>
3077 <p><?php esc_html_e( 'Ultimate Post Kit Pro is installed but not activated. Please activate it to access White Label functionality.', 'ultimate-post-kit' ); ?></p>
3078 <div class="bdt-margin-small-top">
3079 <a href="<?php echo esc_url( $activate_url ); ?>" class="bdt-button bdt-btn-blue">
3080 <?php esc_html_e( 'Activate Pro', 'ultimate-post-kit' ); ?>
3081 </a>
3082 </div>
3083 </div>
3084 <?php
3085 return;
3086 endif;
3087 ?>
3088 <div class="upk-white-label-section">
3089 <h1 class="upk-feature-title"><?php esc_html_e('White Label Settings', 'ultimate-post-kit'); ?></h1>
3090 <p><?php esc_html_e('Enable white label mode to hide Ultimate Post Kit branding from the admin interface and widgets.', 'ultimate-post-kit'); ?></p>
3091
3092 <?php
3093
3094 $is_license_active = false;
3095 if ( function_exists( 'upk_license_validation' ) && true === upk_license_validation() ) {
3096 $is_license_active = true;
3097 }
3098 $is_white_label_eligible = self::is_white_label_license();
3099
3100 // Show appropriate notices based on license status
3101 if (!$is_license_active): ?>
3102 <div class="bdt-alert bdt-alert-danger bdt-margin-medium-top" bdt-alert>
3103 <p><strong><?php esc_html_e('License Not Activated', 'ultimate-post-kit'); ?></strong></p>
3104 <p><?php esc_html_e('You need to activate your Ultimate Post Kit license to access White Label functionality. Please activate your license first.', 'ultimate-post-kit'); ?></p>
3105 <div class="bdt-margin-small-top">
3106 <a href="<?php echo esc_url(admin_url('admin.php?page=ultimate_post_kit_options#ultimate_post_kit_license_settings')); ?>" class="bdt-button bdt-btn-blue bdt-margin-small-right">
3107 <?php esc_html_e('Activate License', 'ultimate-post-kit'); ?>
3108 </a>
3109 <a href="https://postkit.pro/pricing/" target="_blank" class="bdt-button bdt-btn-blue">
3110 <?php esc_html_e('Get License', 'ultimate-post-kit'); ?>
3111 </a>
3112 </div>
3113 </div>
3114 <?php elseif ($is_license_active && !$is_white_label_eligible): ?>
3115 <div class="bdt-alert bdt-alert-warning bdt-margin-medium-top" bdt-alert>
3116 <p><strong><?php esc_html_e('Eligible License Required', 'ultimate-post-kit'); ?></strong></p>
3117 <p><?php esc_html_e('White Label functionality is available for Agency, Extended, Developer, AppSumo Lifetime, and other eligible license holders. Some licenses may include special white label permissions.', 'ultimate-post-kit'); ?></p>
3118 <a href="https://postkit.pro/pricing/" target="_blank" class="bdt-button bdt-btn-blue bdt-margin-small-top">
3119 <?php esc_html_e('Upgrade License', 'ultimate-post-kit'); ?>
3120 </a>
3121 </div>
3122 <?php endif; ?>
3123
3124 <div class="upk-white-label-options <?php echo (!$is_license_active || !$is_white_label_eligible) ? 'upk-white-label-locked' : ''; ?>">
3125 <div class="upk-option-item ">
3126 <div class="upk-option-item-inner bdt-card">
3127 <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3128 <div>
3129 <h3 class="upk-option-title"><?php esc_html_e('Enable White Label Mode', 'ultimate-post-kit'); ?></h3>
3130 <p class="upk-option-description">
3131 <?php if ($is_license_active && $is_white_label_eligible): ?>
3132 <?php esc_html_e('When enabled, Ultimate Post Kit branding will be hidden from the admin interface and widgets.', 'ultimate-post-kit'); ?>
3133 <?php elseif (!$is_license_active): ?>
3134 <?php esc_html_e('This feature requires an active Ultimate Post Kit license. Please activate your license first.', 'ultimate-post-kit'); ?>
3135 <?php else: ?>
3136 <?php esc_html_e('This feature requires an eligible license (Agency, Extended, Developer, AppSumo Lifetime, etc.). Upgrade your license to access white label functionality.', 'ultimate-post-kit'); ?>
3137 <?php endif; ?>
3138 </p>
3139 </div>
3140 <div class="upk-option-switch">
3141 <?php
3142 $white_label_enabled = ($is_license_active && $is_white_label_eligible) ? get_option('upk_white_label_enabled', false) : false;
3143 // Convert to boolean to ensure proper comparison
3144 $white_label_enabled = (bool) $white_label_enabled;
3145 ?>
3146 <label class="switch">
3147 <input type="checkbox"
3148 id="upk-white-label-enabled"
3149 name="upk_white_label_enabled"
3150 <?php checked($white_label_enabled, true); ?>
3151 <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3152 <span class="slider"></span>
3153 </label>
3154 </div>
3155 </div>
3156 </div>
3157 </div>
3158
3159 <!-- White Label Title Field (conditional) -->
3160 <div class="upk-option-item upk-white-label-fields" style="<?php echo ($white_label_enabled && $is_license_active && $is_white_label_eligible) ? '' : 'display: none;'; ?>">
3161 <div class="upk-option-item-inner bdt-card">
3162 <div class="upk-white-label-title-section bdt-margin-medium-bottom">
3163 <h3 class="upk-option-title"><?php esc_html_e('White Label Title', 'ultimate-post-kit'); ?></h3>
3164 <p class="upk-option-description"><?php esc_html_e('Enter a custom title to replace "Ultimate Post Kit" branding throughout the plugin.', 'ultimate-post-kit'); ?></p>
3165 <div class="upk-white-label-input-wrapper bdt-margin-small-top">
3166 <input type="text"
3167 id="upk-white-label-title"
3168 name="upk_white_label_title"
3169 class="upk-white-label-input"
3170 placeholder="<?php esc_attr_e('Enter your custom title...', 'ultimate-post-kit'); ?>"
3171 value="<?php echo esc_attr(get_option('upk_white_label_title', '')); ?>"
3172 <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3173 </div>
3174 </div>
3175
3176 <hr class="bdt-divider-small">
3177
3178 <!-- White Label Title Icon Field -->
3179 <div class="upk-white-label-icon-section bdt-margin-medium-top">
3180 <h3 class="upk-option-title"><?php esc_html_e('White Label Title Icon', 'ultimate-post-kit'); ?></h3>
3181 <p class="upk-option-description"><?php esc_html_e('Upload a custom icon to replace the Ultimate Post Kit menu icon. Supports JPG, PNG, and SVG formats.', 'ultimate-post-kit'); ?></p>
3182
3183 <div class="upk-icon-upload-wrapper bdt-margin-small-top">
3184 <?php
3185 $icon_url = get_option('upk_white_label_icon', '');
3186 $icon_id = get_option('upk_white_label_icon_id', '');
3187 ?>
3188 <div class="upk-icon-preview-container" style="<?php echo $icon_url ? '' : 'display: none;'; ?>">
3189 <div class="upk-icon-preview">
3190 <img id="upk-icon-preview-img" src="<?php echo esc_url($icon_url); ?>" alt="Icon Preview" style="max-width: 64px; max-height: 64px; border: 1px solid #ddd; border-radius: 4px; padding: 8px; background: #fff;">
3191 </div>
3192 <button type="button" id="upk-remove-icon" class="bdt-button bdt-btn-grey bdt-flex bdt-flex-middle bdt-margin-small-top" style="padding: 8px 12px; font-size: 12px;">
3193 <span class="dashicons dashicons-trash"></span>
3194 <?php esc_html_e('Remove', 'ultimate-post-kit'); ?>
3195 </button>
3196 </div>
3197
3198 <div class="upk-icon-upload-container">
3199 <button type="button" id="upk-upload-icon" class="bdt-button bdt-btn-blue bdt-margin-small-top" <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3200 <span class="dashicons dashicons-cloud-upload"></span>
3201 <?php esc_html_e('Upload Icon', 'ultimate-post-kit'); ?>
3202 </button>
3203 <input type="hidden" id="upk-white-label-icon" name="upk_white_label_icon" value="<?php echo esc_attr($icon_url); ?>">
3204 <input type="hidden" id="upk-white-label-icon-id" name="upk_white_label_icon_id" value="<?php echo esc_attr($icon_id); ?>">
3205 </div>
3206 </div>
3207
3208 <p class="upk-input-help">
3209 <?php esc_html_e('Recommended size: 20x20 pixels. The icon will be automatically resized to fit the WordPress admin menu. Supported formats: JPG, PNG, SVG.', 'ultimate-post-kit'); ?>
3210 </p>
3211 </div>
3212
3213 <!-- White Label Plugin Logo Field -->
3214 <div class="upk-white-label-logo-section bdt-margin-medium-top">
3215 <h3 class="upk-option-title"><?php esc_html_e('Plugin Logo', 'ultimate-post-kit'); ?></h3>
3216 <p class="upk-option-description"><?php esc_html_e('Upload a custom logo to replace the Ultimate Post Kit logo in the admin header. Supports JPG, PNG, and SVG formats.', 'ultimate-post-kit'); ?></p>
3217 <div class="upk-logo-upload-wrapper-inner">
3218 <div class="upk-logo-upload-wrapper bdt-margin-small-top">
3219 <?php
3220 $logo_url = get_option('upk_white_label_logo', '');
3221 $logo_id = get_option('upk_white_label_logo_id', '');
3222 ?>
3223 <div class="upk-logo-preview-container" style="<?php echo $logo_url ? '' : 'display: none;'; ?>">
3224 <div class="upk-logo-preview">
3225 <img id="upk-logo-preview-img" src="<?php echo esc_url($logo_url); ?>" alt="Logo Preview" style="max-width: 200px; max-height: 64px; border: 1px solid #ddd; border-radius: 4px; padding: 8px; background: #fff;">
3226 </div>
3227 <button type="button" id="upk-remove-logo" class="bdt-button bdt-btn-grey bdt-flex bdt-flex-middle bdt-margin-small-top" style="padding: 8px 12px; font-size: 12px;">
3228 <span class="dashicons dashicons-trash"></span>
3229 </button>
3230 </div>
3231
3232 <div class="upk-logo-upload-container">
3233 <button type="button" id="upk-upload-logo" class="bdt-button bdt-btn-blue bdt-margin-small-top" <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3234 <span class="dashicons dashicons-cloud-upload"></span>
3235 <?php esc_html_e('Upload Logo', 'ultimate-post-kit'); ?>
3236 </button>
3237 <input type="hidden" id="upk-white-label-logo" name="upk_white_label_logo" value="<?php echo esc_attr($logo_url); ?>">
3238 <input type="hidden" id="upk-white-label-logo-id" name="upk_white_label_logo_id" value="<?php echo esc_attr($logo_id); ?>">
3239 </div>
3240 </div>
3241 <p class="upk-input-help">
3242 <?php esc_html_e('Recommended size: 200x40 pixels. The logo will be displayed in the admin header. Supported formats: JPG, PNG, SVG.', 'ultimate-post-kit'); ?>
3243 </p>
3244 </div>
3245 </div>
3246 </div>
3247 </div>
3248
3249 <!-- License Hide Option (conditional) -->
3250 <div class="upk-option-item upk-white-label-fields" style="<?php echo ($white_label_enabled && $is_license_active && $is_white_label_eligible) ? '' : 'display: none;'; ?>">
3251 <div class="upk-option-item-inner bdt-card">
3252 <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3253 <div>
3254 <h3 class="upk-option-title"><?php esc_html_e('Hide License Menu', 'ultimate-post-kit'); ?></h3>
3255 <p class="upk-option-description"><?php esc_html_e('Hide the license menu from the admin sidebar when white label mode is enabled.', 'ultimate-post-kit'); ?></p>
3256 </div>
3257 <div class="upk-option-switch">
3258 <?php
3259 $hide_license = get_option('upk_white_label_hide_license', false);
3260 // Convert to boolean to ensure proper comparison
3261 $hide_license = (bool) $hide_license;
3262 ?>
3263 <label class="switch">
3264 <input type="checkbox"
3265 id="upk-white-label-hide-license"
3266 name="upk_white_label_hide_license"
3267 <?php checked($hide_license, true); ?>
3268 <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3269 <span class="slider"></span>
3270 </label>
3271 </div>
3272 </div>
3273 </div>
3274 </div>
3275
3276 <!-- BDTUPK_HIDE Option (conditional) -->
3277 <div class="upk-option-item upk-white-label-fields" style="<?php echo ($white_label_enabled && $is_license_active && $is_white_label_eligible) ? '' : 'display: none;'; ?>">
3278 <div class="upk-option-item-inner bdt-card">
3279 <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3280 <div>
3281 <h3 class="upk-option-title"><?php esc_html_e('Enable BDTUPK_HIDE Constant', 'ultimate-post-kit'); ?></h3>
3282 <p class="upk-option-description"><?php esc_html_e('Define the BDTUPK_HIDE constant to hide additional Ultimate Post Kit branding and features throughout the plugin.', 'ultimate-post-kit'); ?></p>
3283 <?php
3284 $bdtupk_hide = get_option('upk_white_label_bdtupk_hide', false);
3285 if ($bdtupk_hide): ?>
3286 <div class="bdt-alert bdt-alert-warning bdt-margin-small-top">
3287 <p><strong>⚠️ BDTUPK_HIDE Currently Active</strong></p>
3288 <p>Advanced white label mode is currently enabled. Ultimate Post Kit menus are hidden from the admin interface.</p>
3289 </div>
3290 <?php endif; ?>
3291 </div>
3292 <div class="upk-option-switch">
3293 <?php
3294 // Convert to boolean to ensure proper comparison
3295 $bdtupk_hide = (bool) $bdtupk_hide;
3296 ?>
3297 <label class="switch">
3298 <input type="checkbox"
3299 id="upk-white-label-bdtupk-hide"
3300 name="upk_white_label_bdtupk_hide"
3301 <?php checked($bdtupk_hide, true); ?>
3302 <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3303 <span class="slider"></span>
3304 </label>
3305 </div>
3306 </div>
3307 </div>
3308 </div>
3309
3310 <?php if (!$bdtupk_hide && $is_license_active && $is_white_label_eligible): ?>
3311 <div class="bdt-margin-small-top">
3312 <div class="bdt-alert bdt-alert-danger">
3313 <h4>📧 Email Access System</h4>
3314 <p>When you enable BDTUPK_HIDE, an email will be automatically sent to:</p>
3315 <ul style="margin: 10px 0;">
3316 <li><strong>License Email:</strong> <?php echo esc_html(self::get_license_email()); ?></li>
3317 <?php if (get_bloginfo('admin_email') !== self::get_license_email()): ?>
3318 <li><strong>Admin Email:</strong> <?php echo esc_html(get_bloginfo('admin_email')); ?></li>
3319 <?php endif; ?>
3320 </ul>
3321 <p>This email will contain a special access link that allows you to return to these settings even when BDTUPK_HIDE is active.</p>
3322 </div>
3323 </div>
3324 <?php endif; ?>
3325
3326 <!-- Success/Error Messages -->
3327 <div id="upk-white-label-message" class="upk-white-label-message bdt-margin-small-top" style="display: none;">
3328 <div class="bdt-alert bdt-alert-success" bdt-alert>
3329 <a href class="bdt-alert-close" bdt-close></a>
3330 <p><?php esc_html_e('White label settings saved successfully!', 'ultimate-post-kit'); ?></p>
3331 </div>
3332 </div>
3333 </div>
3334 </div>
3335 <?php
3336 }
3337
3338 public static function license_wl_status() {
3339 $status = get_option('ultimate_post_kit_license_title_status');
3340
3341 if ($status) {
3342 return true;
3343 }
3344
3345 return false;
3346 }
3347
3348
3349
3350 /**
3351 * Display Analytics and System Requirements
3352 *
3353 * @access public
3354 * @return void
3355 */
3356
3357 public function ultimate_post_kit_analytics_system_req_content() {
3358 ?>
3359 <div class="upk-dashboard-panel"
3360 bdt-scrollspy="target: > div > div > .bdt-card; cls: bdt-animation-slide-bottom-small; delay: 300">
3361 <div class="upk-dashboard-analytics-system">
3362
3363 <?php $this->ultimate_post_kit_widgets_status(); ?>
3364
3365 <div class="bdt-grid bdt-grid-medium bdt-margin-medium-top" bdt-grid
3366 bdt-height-match="target: > div > .bdt-card">
3367 <div class="bdt-width-1-1">
3368 <div class="bdt-card bdt-card-body upk-system-requirement">
3369 <h1 class="upk-feature-title bdt-margin-small-bottom">
3370 <?php esc_html_e('System Requirement', 'ultimate-post-kit'); ?>
3371 </h1>
3372 <?php $this->ultimate_post_kit_system_requirement(); ?>
3373 </div>
3374 </div>
3375 </div>
3376
3377 </div>
3378 </div>
3379 <?php
3380 }
3381
3382 /**
3383 * Others Plugin - Using standalone plugin manager
3384 */
3385 public function ultimate_post_kit_others_plugin() {
3386 // Include and render the standalone others plugin manager
3387 require_once BDTUPK_INC_PATH . 'setup-wizard/ultimate-post-kit-others-plugin.php';
3388
3389 // Call the helper function to render the plugin manager
3390 ultimate_post_kit_others_plugin();
3391 }
3392
3393 /**
3394 * Widgets Status
3395 */
3396
3397 public function ultimate_post_kit_widgets_status() {
3398 $track_nw_msg = '';
3399 if (!Tracker::is_allow_track()) {
3400 $track_nw = esc_html__('This feature is not working because the Elementor Usage Data Sharing feature is Not Enabled.', 'ultimate-post-kit');
3401 $track_nw_msg = 'bdt-tooltip="' . $track_nw . '"';
3402 }
3403 ?>
3404 <div class="upk-dashboard-widgets-status">
3405 <div class="bdt-grid bdt-grid-medium" bdt-grid bdt-height-match="target: > div > .bdt-card">
3406 <div class="bdt-width-1-2@m bdt-width-1-4@xl">
3407 <div class="upk-widget-status bdt-card bdt-card-body" <?php echo wp_kses_post($track_nw_msg); ?>>
3408
3409 <?php
3410 $used_widgets = count(self::get_used_widgets());
3411 $un_used_widgets = count(self::get_unused_widgets());
3412 ?>
3413
3414 <div class="upk-count-canvas-wrap">
3415 <h1 class="upk-feature-title"><?php esc_html_e('All Widgets', 'ultimate-post-kit'); ?></h1>
3416 <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3417 <div class="upk-count-wrap">
3418 <div class="upk-widget-count"><?php esc_html_e('Used:', 'ultimate-post-kit'); ?> <b>
3419 <?php echo esc_html($used_widgets); ?>
3420 </b></div>
3421 <div class="upk-widget-count"><?php esc_html_e('Unused:', 'ultimate-post-kit'); ?> <b>
3422 <?php echo esc_html($un_used_widgets); ?>
3423 </b>
3424 </div>
3425 <div class="upk-widget-count"><?php esc_html_e('Total:', 'ultimate-post-kit'); ?>
3426 <b>
3427 <?php echo esc_html($used_widgets + $un_used_widgets); ?>
3428 </b>
3429 </div>
3430 </div>
3431
3432 <div class="upk-canvas-wrap">
3433 <canvas id="bdt-db-total-status" style="height: 100px; width: 100px;"
3434 data-label="Total Widgets Status - (<?php echo esc_html($used_widgets + $un_used_widgets); ?>)"
3435 data-labels="<?php echo esc_attr('Used, Unused'); ?>"
3436 data-value="<?php echo esc_attr($used_widgets) . ',' . esc_attr($un_used_widgets); ?>"
3437 data-bg="#FFD166, #fff4d9" data-bg-hover="#0673e1, #e71522"></canvas>
3438 </div>
3439 </div>
3440 </div>
3441
3442 </div>
3443 </div>
3444 <div class="bdt-width-1-2@m bdt-width-1-4@xl">
3445 <div class="upk-widget-status bdt-card bdt-card-body" <?php echo wp_kses_post($track_nw_msg); ?>>
3446
3447 <?php
3448 $used_only_widgets = count(self::get_used_only_widgets());
3449 $unused_only_widgets = count(self::get_unused_only_widgets());
3450 ?>
3451
3452
3453 <div class="upk-count-canvas-wrap">
3454 <h1 class="upk-feature-title"><?php esc_html_e('Core', 'ultimate-post-kit'); ?></h1>
3455 <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3456 <div class="upk-count-wrap">
3457 <div class="upk-widget-count"><?php esc_html_e('Used:', 'ultimate-post-kit'); ?> <b>
3458 <?php echo esc_html($used_only_widgets); ?>
3459 </b></div>
3460 <div class="upk-widget-count"><?php esc_html_e('Unused:', 'ultimate-post-kit'); ?> <b>
3461 <?php echo esc_html($unused_only_widgets); ?>
3462 </b></div>
3463 <div class="upk-widget-count"><?php esc_html_e('Total:', 'ultimate-post-kit'); ?>
3464 <b>
3465 <?php echo esc_html($used_only_widgets + $unused_only_widgets); ?>
3466 </b>
3467 </div>
3468 </div>
3469
3470 <div class="upk-canvas-wrap">
3471 <canvas id="bdt-db-only-widget-status" style="height: 100px; width: 100px;"
3472 data-label="Core Widgets Status - (<?php echo esc_html($used_only_widgets + $unused_only_widgets); ?>)"
3473 data-labels="<?php echo esc_attr('Used, Unused'); ?>"
3474 data-value="<?php echo esc_attr($used_only_widgets) . ',' . esc_attr($unused_only_widgets); ?>"
3475 data-bg="#EF476F, #ffcdd9" data-bg-hover="#0673e1, #e71522"></canvas>
3476 </div>
3477 </div>
3478 </div>
3479
3480 </div>
3481 </div>
3482
3483 <div class="bdt-width-1-2@m bdt-width-1-4@xl">
3484 <div class="upk-widget-status bdt-card bdt-card-body" <?php echo wp_kses_post($track_nw_msg); ?>>
3485
3486 <div class="upk-count-canvas-wrap">
3487 <h1 class="upk-feature-title"><?php esc_html_e('Active', 'ultimate-post-kit'); ?></h1>
3488 <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3489 <div class="upk-count-wrap">
3490 <div class="upk-widget-count"><?php esc_html_e('Core:', 'ultimate-post-kit'); ?>
3491 <b id="bdt-total-widgets-status-core">0</b>
3492 </div>
3493 <div class="upk-widget-count"><?php esc_html_e('Extensions:', 'ultimate-post-kit'); ?>
3494 <b id="bdt-total-widgets-status-extensions">0</b>
3495 </div>
3496 <div class="upk-widget-count"><?php esc_html_e('Total:', 'ultimate-post-kit'); ?> <b
3497 id="bdt-total-widgets-status-heading">0</b></div>
3498 </div>
3499
3500 <div class="upk-canvas-wrap">
3501 <canvas id="bdt-total-widgets-status" style="height: 100px; width: 100px;"
3502 data-label="Total Active Widgets Status"
3503 data-labels="<?php echo esc_attr('Core, Extensions'); ?>"
3504 data-value="0,0,0"
3505 data-bg="#0680d6, #B0EBFF" data-bg-hover="#0673e1, #B0EBFF">
3506 </canvas>
3507 </div>
3508 </div>
3509 </div>
3510
3511 </div>
3512 </div>
3513 </div>
3514 </div>
3515
3516 <?php if (!Tracker::is_allow_track()): ?>
3517 <div class="bdt-border-rounded bdt-box-shadow-small bdt-alert-warning" bdt-alert>
3518 <a href class="bdt-alert-close" bdt-close></a>
3519 <div class="bdt-text-default">
3520 <?php
3521 printf(
3522 esc_html__('To view widgets analytics, Elementor %1$sUsage Data Sharing%2$s feature by Elementor needs to be activated. Please activate the feature to get widget analytics instantly ', 'ultimate-post-kit'),
3523 '<b>', '</b>'
3524 );
3525
3526 echo ' <a href="' . esc_url(admin_url('admin.php?page=elementor-settings')) . '">' . esc_html__('from here.', 'ultimate-post-kit') . '</a>';
3527 ?>
3528 </div>
3529 </div>
3530 <?php endif; ?>
3531
3532 <?php
3533 }
3534
3535 /**
3536 * Display System Requirement
3537 *
3538 * @access public
3539 * @return void
3540 */
3541
3542 public function ultimate_post_kit_system_requirement() {
3543 $php_version = phpversion();
3544 $max_execution_time = ini_get('max_execution_time');
3545 $memory_limit = ini_get('memory_limit');
3546 $post_limit = ini_get('post_max_size');
3547 $uploads = wp_upload_dir();
3548 $upload_path = $uploads['basedir'];
3549 $yes_icon = '<span class="valid"><i class="dashicons-before dashicons-yes"></i></span>';
3550 $no_icon = '<span class="invalid"><i class="dashicons-before dashicons-no-alt"></i></span>';
3551
3552 $environment = Utils::get_environment_info();
3553
3554 ?>
3555 <ul class="check-system-status bdt-grid bdt-child-width-1-2@m bdt-grid-small ">
3556 <li>
3557 <div>
3558 <span class="label1"><?php esc_html_e('PHP Version:', 'ultimate-post-kit'); ?></span>
3559
3560 <?php
3561 if (version_compare($php_version, '7.4.0', '<')) {
3562 echo wp_kses_post($no_icon);
3563 echo '<span class="label2" title="' . esc_attr__('Min: 7.4 Recommended', 'ultimate-post-kit') . '" bdt-tooltip>' . esc_html__('Currently:', 'ultimate-post-kit') . ' ' . esc_html($php_version) . '</span>';
3564 } else {
3565 echo wp_kses_post($yes_icon);
3566 echo '<span class="label2">' . esc_html__('Currently:', 'ultimate-post-kit') . ' ' . esc_html($php_version) . '</span>';
3567 }
3568 ?>
3569 </div>
3570
3571 </li>
3572
3573 <li>
3574 <div>
3575 <span class="label1"><?php esc_html_e('Max execution time:', 'ultimate-post-kit'); ?> </span>
3576 <?php
3577 if ($max_execution_time < '90') {
3578 echo wp_kses_post($no_icon);
3579 echo '<span class="label2" title="Min: 90 Recommended" bdt-tooltip>Currently: ' . esc_html($max_execution_time) . '</span>';
3580 } else {
3581 echo wp_kses_post($yes_icon);
3582 echo '<span class="label2">Currently: ' . esc_html($max_execution_time) . '</span>';
3583 }
3584 ?>
3585 </div>
3586 </li>
3587 <li>
3588 <div>
3589 <span class="label1"><?php esc_html_e('Memory Limit:', 'ultimate-post-kit'); ?> </span>
3590
3591 <?php
3592 if (intval($memory_limit) < '512') {
3593 echo wp_kses_post($no_icon);
3594 echo '<span class="label2" title="Min: 512M Recommended" bdt-tooltip>Currently: ' . esc_html($memory_limit) . '</span>';
3595 } else {
3596 echo wp_kses_post($yes_icon);
3597 echo '<span class="label2">Currently: ' . esc_html($memory_limit) . '</span>';
3598 }
3599 ?>
3600 </div>
3601 </li>
3602
3603 <li>
3604 <div>
3605 <span class="label1"><?php esc_html_e('Max Post Limit:', 'ultimate-post-kit'); ?> </span>
3606
3607 <?php
3608 if (intval($post_limit) < '32') {
3609 echo wp_kses_post($no_icon);
3610 echo '<span class="label2" title="Min: 32M Recommended" bdt-tooltip>Currently: ' . wp_kses_post($post_limit) . '</span>';
3611 } else {
3612 echo wp_kses_post($yes_icon);
3613 echo '<span class="label2">Currently: ' . wp_kses_post($post_limit) . '</span>';
3614 }
3615 ?>
3616 </div>
3617 </li>
3618
3619 <li>
3620 <div>
3621 <span class="label1"><?php esc_html_e('Uploads folder writable:', 'ultimate-post-kit'); ?></span>
3622
3623 <?php
3624 if (!is_writable($upload_path)) {
3625 echo wp_kses_post($no_icon);
3626 } else {
3627 echo wp_kses_post($yes_icon);
3628 }
3629 ?>
3630 </div>
3631
3632 </li>
3633
3634 <li>
3635 <div>
3636 <span class="label1"><?php esc_html_e('MultiSite:', 'ultimate-post-kit'); ?></span>
3637
3638 <?php
3639 if ($environment['wp_multisite']) {
3640 echo wp_kses_post($yes_icon);
3641 echo '<span class="label2">' . esc_html__('MultiSite Enabled', 'ultimate-post-kit') . '</span>';
3642 } else {
3643 echo wp_kses_post($yes_icon);
3644 echo '<span class="label2">' . esc_html__('Single Site', 'ultimate-post-kit') . '</span>';
3645 }
3646 ?>
3647 </div>
3648 </li>
3649
3650 <li>
3651 <div>
3652 <span class="label1"><?php esc_html_e('GZip Enabled:', 'ultimate-post-kit'); ?></span>
3653
3654 <?php
3655 if ($environment['gzip_enabled']) {
3656 echo wp_kses_post($yes_icon);
3657 } else {
3658 echo wp_kses_post($no_icon);
3659 }
3660 ?>
3661 </div>
3662
3663 </li>
3664
3665 <li>
3666 <div>
3667 <span class="label1"><?php esc_html_e('Debug Mode:', 'ultimate-post-kit'); ?></span>
3668 <?php
3669 if ($environment['wp_debug_mode']) {
3670 echo wp_kses_post($no_icon);
3671 echo '<span class="label2">' . esc_html__('Currently Turned On', 'ultimate-post-kit') . '</span>';
3672 } else {
3673 echo wp_kses_post($yes_icon);
3674 echo '<span class="label2">' . esc_html__('Currently Turned Off', 'ultimate-post-kit') . '</span>';
3675 }
3676 ?>
3677 </div>
3678
3679 </li>
3680
3681 </ul>
3682
3683 <div class="bdt-admin-alert">
3684 <strong><?php esc_html_e('Note:', 'ultimate-post-kit'); ?></strong>
3685 <?php
3686 /* translators: %s: Plugin name 'Ultimate Post Kit' */
3687 printf(
3688 esc_html__('If you have multiple addons like %s so you may need to allocate additional memory for other addons as well.', 'ultimate-post-kit'),
3689 '<b>Ultimate Post Kit</b>'
3690 );
3691 ?>
3692 </div>
3693
3694 <?php
3695 }
3696
3697 /**
3698 * Check plugin status (installed, active, or not installed)
3699 *
3700 * @param string $plugin_path Plugin file path
3701 * @return string 'active', 'installed', or 'not_installed'
3702 */
3703 private function get_plugin_status($plugin_path) {
3704 // Check if plugin is active
3705 if (is_plugin_active($plugin_path)) {
3706 return 'active';
3707 }
3708
3709 // Check if plugin is installed but not active
3710 $installed_plugins = get_plugins();
3711 if (isset($installed_plugins[$plugin_path])) {
3712 return 'installed';
3713 }
3714
3715 // Plugin is not installed
3716 return 'not_installed';
3717 }
3718
3719 /**
3720 * AJAX handler for saving custom code
3721 *
3722 * @access public
3723 * @return void
3724 */
3725 public function save_custom_code_ajax() {
3726 // Verify nonce
3727 if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'upk_custom_code_nonce' ) ) {
3728 wp_send_json_error( [ 'message' => 'Invalid security token.' ] );
3729 }
3730
3731 // Check user capability
3732 if ( ! current_user_can( 'manage_options' ) ) {
3733 wp_send_json_error( [ 'message' => 'Insufficient permissions.' ] );
3734 }
3735
3736 // Sanitize and save the custom code
3737 $custom_css = isset( $_POST['custom_css'] ) ? wp_unslash( $_POST['custom_css'] ) : '';
3738 $custom_js = isset( $_POST['custom_js'] ) ? wp_unslash( $_POST['custom_js'] ) : '';
3739 $custom_css_2 = isset( $_POST['custom_css_2'] ) ? wp_unslash( $_POST['custom_css_2'] ) : '';
3740 $custom_js_2 = isset( $_POST['custom_js_2'] ) ? wp_unslash( $_POST['custom_js_2'] ) : '';
3741
3742 // Handle excluded pages - ensure we get proper array format
3743 $excluded_pages = array();
3744 if ( isset( $_POST['excluded_pages'] ) ) {
3745 if ( is_array( $_POST['excluded_pages'] ) ) {
3746 $excluded_pages = $_POST['excluded_pages'];
3747 } elseif ( is_string( $_POST['excluded_pages'] ) && ! empty( $_POST['excluded_pages'] ) ) {
3748 // Handle case where it might be a single value
3749 $excluded_pages = [ $_POST['excluded_pages'] ];
3750 }
3751 }
3752
3753 // Sanitize excluded pages - convert to integers and remove empty values
3754 $excluded_pages = array_map( 'intval', $excluded_pages );
3755 $excluded_pages = array_filter( $excluded_pages, function( $page_id ) {
3756 return $page_id > 0;
3757 } );
3758
3759 // Save to database
3760 update_option( 'upk_custom_css', $custom_css );
3761 update_option( 'upk_custom_js', $custom_js );
3762 update_option( 'upk_custom_css_2', $custom_css_2 );
3763 update_option( 'upk_custom_js_2', $custom_js_2 );
3764 update_option( 'upk_excluded_pages', $excluded_pages );
3765
3766 wp_send_json_success( [
3767 'message' => 'Custom code saved successfully!',
3768 'excluded_count' => count( $excluded_pages )
3769 ] );
3770 }
3771
3772 /**
3773 * Handle AJAX plugin installation
3774 *
3775 * @access public
3776 * @return void
3777 */
3778 public function install_plugin_ajax() {
3779 // Check nonce
3780 if (!wp_verify_nonce($_POST['nonce'], 'upk_install_plugin_nonce')) {
3781 wp_send_json_error(['message' => __('Security check failed', 'ultimate-post-kit')]);
3782 }
3783
3784 // Check user capability
3785 if (!current_user_can('install_plugins')) {
3786 wp_send_json_error(['message' => __('You do not have permission to install plugins', 'ultimate-post-kit')]);
3787 }
3788
3789 $plugin_slug = sanitize_text_field($_POST['plugin_slug']);
3790
3791 if (empty($plugin_slug)) {
3792 wp_send_json_error(['message' => __('Plugin slug is required', 'ultimate-post-kit')]);
3793 }
3794
3795 // Include necessary WordPress files
3796 require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
3797 require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
3798 require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
3799
3800 // Get plugin information
3801 $api = plugins_api('plugin_information', [
3802 'slug' => $plugin_slug,
3803 'fields' => [
3804 'sections' => false,
3805 ],
3806 ]);
3807
3808 if (is_wp_error($api)) {
3809 wp_send_json_error(['message' => __('Plugin not found: ', 'ultimate-post-kit') . $api->get_error_message()]);
3810 }
3811
3812 // Install the plugin
3813 $skin = new \WP_Ajax_Upgrader_Skin();
3814 $upgrader = new \Plugin_Upgrader($skin);
3815 $result = $upgrader->install($api->download_link);
3816
3817 if (is_wp_error($result)) {
3818 wp_send_json_error(['message' => __('Installation failed: ', 'ultimate-post-kit') . $result->get_error_message()]);
3819 } elseif ($skin->get_errors()->has_errors()) {
3820 wp_send_json_error(['message' => __('Installation failed: ', 'ultimate-post-kit') . $skin->get_error_messages()]);
3821 } elseif (is_null($result)) {
3822 wp_send_json_error(['message' => __('Installation failed: Unable to connect to filesystem', 'ultimate-post-kit')]);
3823 }
3824
3825 // Get installation status
3826 $install_status = install_plugin_install_status($api);
3827
3828 wp_send_json_success([
3829 'message' => __('Plugin installed successfully!', 'ultimate-post-kit'),
3830 'plugin_file' => $install_status['file'],
3831 'plugin_name' => $api->name
3832 ]);
3833 }
3834
3835 /**
3836 * Extract plugin slug from plugin path
3837 *
3838 * @param string $plugin_path Plugin file path
3839 * @return string Plugin slug
3840 */
3841 private function extract_plugin_slug_from_path($plugin_path) {
3842 $parts = explode('/', $plugin_path);
3843 return isset($parts[0]) ? $parts[0] : '';
3844 }
3845
3846 /**
3847 * Get plugin action button HTML based on plugin status
3848 *
3849 * @param string $plugin_path Plugin file path
3850 * @param string $install_url Plugin installation URL
3851 * @param string $plugin_slug Plugin slug for activation
3852 * @return string Button HTML
3853 */
3854 private function get_plugin_action_button($plugin_path, $install_url, $plugin_slug = '') {
3855 $status = $this->get_plugin_status($plugin_path);
3856
3857 switch ($status) {
3858 case 'active':
3859 return '';
3860
3861 case 'installed':
3862 $activate_url = wp_nonce_url(
3863 add_query_arg([
3864 'action' => 'activate',
3865 'plugin' => $plugin_path
3866 ], admin_url('plugins.php')),
3867 'activate-plugin_' . $plugin_path
3868 );
3869 return '<a class="bdt-button bdt-welcome-button" href="' . esc_url($activate_url) . '">' .
3870 __('Activate', 'ultimate-post-kit') . '</a>';
3871
3872 case 'not_installed':
3873 default:
3874 $plugin_slug = $this->extract_plugin_slug_from_path($plugin_path);
3875 $nonce = wp_create_nonce('upk_install_plugin_nonce');
3876 return '<a class="bdt-button bdt-welcome-button upk-install-plugin"
3877 data-plugin-slug="' . esc_attr($plugin_slug) . '"
3878 data-nonce="' . esc_attr($nonce) . '"
3879 href="#">' .
3880 __('Install', 'ultimate-post-kit') . '</a>';
3881 }
3882 }
3883
3884 /**
3885 * Extra Options Start Here
3886 */
3887
3888 /**
3889 * Render Custom CSS & JS Section
3890 *
3891 * @access public
3892 * @return void
3893 */
3894 public function render_custom_css_js_section() {
3895 ?>
3896 <div class="upk-custom-code-section">
3897 <!-- Header Section -->
3898 <div class="upk-code-section-header">
3899 <h2 class="upk-section-title"><?php esc_html_e('Header Code Injection', 'ultimate-post-kit'); ?></h2>
3900 <p class="upk-section-description"><?php esc_html_e('Code added here will be injected into the &lt;head&gt; section of your website.', 'ultimate-post-kit'); ?></p>
3901 </div>
3902 <div class="upk-code-row bdt-grid bdt-grid-small" bdt-grid>
3903 <div class="bdt-width-1-2@m">
3904 <div class="upk-code-editor-wrapper">
3905 <h3 class="upk-code-editor-title"><?php esc_html_e('CSS', 'ultimate-post-kit'); ?></h3>
3906 <p class="upk-code-editor-description"><?php esc_html_e('Enter raw CSS code without &lt;style&gt; tags.', 'ultimate-post-kit'); ?></p>
3907 <div class="upk-codemirror-editor-container">
3908 <textarea id="upk-custom-css" name="upk_custom_css" class="upk-code-editor" data-mode="css" placeholder=".example {&#10; background: red;&#10; border-radius: 5px;&#10; padding: 15px;&#10;}&#10;&#10;"><?php echo esc_textarea(get_option('upk_custom_css', '')); ?></textarea>
3909 </div>
3910 </div>
3911 </div>
3912 <div class="bdt-width-1-2@m">
3913 <div class="upk-code-editor-wrapper">
3914 <h3 class="upk-code-editor-title"><?php esc_html_e('JS', 'ultimate-post-kit'); ?></h3>
3915 <p class="upk-code-editor-description"><?php esc_html_e('Enter raw JavaScript code without &lt;script&gt; tags.', 'ultimate-post-kit'); ?></p>
3916 <div class="upk-codemirror-editor-container">
3917 <textarea id="upk-custom-js" name="upk_custom_js" class="upk-code-editor" data-mode="javascript" placeholder="alert('Hello, Ultimate Post Kit!');"><?php echo esc_textarea(get_option('upk_custom_js', '')); ?></textarea>
3918 </div>
3919 </div>
3920 </div>
3921 </div>
3922
3923 <!-- Footer Section -->
3924 <div class="upk-code-section-header bdt-margin-medium-top">
3925 <h2 class="upk-section-title"><?php esc_html_e('Footer Code Injection', 'ultimate-post-kit'); ?></h2>
3926 <p class="upk-section-description"><?php esc_html_e('Code added here will be injected before the closing &lt;/body&gt; tag of your website.', 'ultimate-post-kit'); ?></p>
3927 </div>
3928 <div class="upk-code-row bdt-grid bdt-grid-small bdt-margin-small-top" bdt-grid>
3929 <div class="bdt-width-1-2@m">
3930 <div class="upk-code-editor-wrapper">
3931 <h3 class="upk-code-editor-title"><?php esc_html_e('CSS', 'ultimate-post-kit'); ?></h3>
3932 <p class="upk-code-editor-description"><?php esc_html_e('Enter raw CSS code without &lt;style&gt; tags.', 'ultimate-post-kit'); ?></p>
3933 <div class="upk-codemirror-editor-container">
3934 <textarea id="upk-custom-css-2" name="upk_custom_css_2" class="upk-code-editor" data-mode="css" placeholder=".example {&#10; background: green;&#10;}&#10;&#10;"><?php echo esc_textarea(get_option('upk_custom_css_2', '')); ?></textarea>
3935 </div>
3936 </div>
3937 </div>
3938 <div class="bdt-width-1-2@m">
3939 <div class="upk-code-editor-wrapper">
3940 <h3 class="upk-code-editor-title"><?php esc_html_e('JS', 'ultimate-post-kit'); ?></h3>
3941 <p class="upk-code-editor-description"><?php esc_html_e('Enter raw JavaScript code without &lt;script&gt; tags.', 'ultimate-post-kit'); ?></p>
3942 <div class="upk-codemirror-editor-container">
3943 <textarea id="upk-custom-js-2" name="upk_custom_js_2" class="upk-code-editor" data-mode="javascript" placeholder="console.log('Hello, Ultimate Post Kit!');"><?php echo esc_textarea(get_option('upk_custom_js_2', '')); ?></textarea>
3944 </div>
3945 </div>
3946 </div>
3947 </div>
3948
3949 <!-- Page Exclusion Section -->
3950 <div class="upk-code-section-header bdt-margin-medium-top">
3951 <h2 class="upk-section-title"><?php esc_html_e('Page & Post Exclusion Settings', 'ultimate-post-kit'); ?></h2>
3952 <p class="upk-section-description"><?php esc_html_e('Select pages and posts where you don\'t want any custom code to be injected. This applies to all sections above.', 'ultimate-post-kit'); ?></p>
3953 </div>
3954 <div class="upk-page-exclusion-wrapper">
3955 <label for="upk-excluded-pages" class="upk-exclusion-label">
3956 <?php esc_html_e('Exclude Pages & Posts:', 'ultimate-post-kit'); ?>
3957 </label>
3958 <select id="upk-excluded-pages" name="upk_excluded_pages[]" multiple class="upk-page-select">
3959 <option value=""><?php esc_html_e('-- Select pages/posts to exclude --', 'ultimate-post-kit'); ?></option>
3960 <?php
3961 $excluded_pages = get_option('upk_excluded_pages', array());
3962 if (!is_array($excluded_pages)) {
3963 $excluded_pages = array();
3964 }
3965
3966 // Get all published pages
3967 $pages = get_pages(array(
3968 'sort_order' => 'ASC',
3969 'sort_column' => 'post_title',
3970 'post_status' => 'publish'
3971 ));
3972
3973 // Get recent posts (last 50)
3974 $posts = get_posts(array(
3975 'numberposts' => 50,
3976 'post_status' => 'publish',
3977 'post_type' => 'post',
3978 'orderby' => 'date',
3979 'order' => 'DESC'
3980 ));
3981
3982 // Display pages first
3983 if (!empty($pages)) {
3984 echo '<optgroup label="' . esc_attr__('Pages', 'ultimate-post-kit') . '">';
3985 foreach ($pages as $page) {
3986 $selected = in_array($page->ID, $excluded_pages) ? 'selected' : '';
3987 echo '<option value="' . esc_attr($page->ID) . '" ' . $selected . '>' . esc_html($page->post_title) . '</option>';
3988 }
3989 echo '</optgroup>';
3990 }
3991
3992 // Then display posts
3993 if (!empty($posts)) {
3994 echo '<optgroup label="' . esc_attr__('Recent Posts', 'ultimate-post-kit') . '">';
3995 foreach ($posts as $post) {
3996 $selected = in_array($post->ID, $excluded_pages) ? 'selected' : '';
3997 $post_date = date('M j, Y', strtotime($post->post_date));
3998 echo '<option value="' . esc_attr($post->ID) . '" ' . $selected . '>' . esc_html($post->post_title) . ' (' . $post_date . ')</option>';
3999 }
4000 echo '</optgroup>';
4001 }
4002 ?>
4003 </select>
4004 <p class="upk-exclusion-help">
4005 <?php esc_html_e('Hold Ctrl (or Cmd on Mac) to select multiple items. Selected pages and posts will not load any custom CSS or JavaScript code. The list shows all pages and the 50 most recent posts.', 'ultimate-post-kit'); ?>
4006 </p>
4007 </div>
4008
4009 <!-- Success/Error Messages -->
4010 <div id="upk-custom-code-message" class="upk-code-message bdt-margin-small-top" style="display: none;">
4011 <div class="bdt-alert bdt-alert-success" bdt-alert>
4012 <a href class="bdt-alert-close" bdt-close></a>
4013 <p><?php esc_html_e('Custom code saved successfully!', 'ultimate-post-kit'); ?></p>
4014 </div>
4015 </div>
4016 </div>
4017 <?php
4018 }
4019
4020 /**
4021 * Extra Options Start Here
4022 */
4023
4024 public function ultimate_post_kit_extra_options() {
4025 ?>
4026 <div class="upk-dashboard-panel"
4027 bdt-scrollspy="target: > div > div > .bdt-card; cls: bdt-animation-slide-bottom-small; delay: 300">
4028 <div class="upk-dashboard-extra-options">
4029 <div class="bdt-card bdt-card-body">
4030 <h1 class="upk-feature-title"><?php esc_html_e('Extra Options', 'ultimate-post-kit'); ?></h1>
4031
4032 <div class="upk-extra-options-tabs">
4033 <ul class="bdt-tab" bdt-tab="connect: #upk-extra-options-tab-content; animation: bdt-animation-fade">
4034 <li class="bdt-active"><a
4035 href="#"><?php esc_html_e('Custom CSS & JS', 'ultimate-post-kit'); ?></a></li>
4036 <li><a href="#"><?php esc_html_e('White Label', 'ultimate-post-kit'); ?></a></li>
4037 </ul>
4038
4039 <div id="upk-extra-options-tab-content" class="bdt-switcher">
4040 <!-- Custom CSS & JS Tab -->
4041 <div>
4042 <?php $this->render_custom_css_js_section(); ?>
4043 </div>
4044
4045 <!-- White Label Tab -->
4046 <div>
4047 <?php $this->render_white_label_section(); ?>
4048 </div>
4049 </div>
4050 </div>
4051 </div>
4052 </div>
4053 </div>
4054 <?php
4055 }
4056
4057
4058 /**
4059 * Rollback Version Content
4060 *
4061 * @access public
4062 * @return void
4063 */
4064 public function upk_rollback_version_content() {
4065 // Use the already initialized rollback version instance
4066 $this->rollback_version->upk_rollback_version_content();
4067 }
4068
4069 /**
4070 * Get allowed white label license types (SHA-256 hashes)
4071 * This centralized method makes it easy to add new license types in the future
4072 * Note: AppSumo and Lifetime licenses require WL flag in other_param instead of automatic access
4073 *
4074 * @access public static
4075 * @return array Array of SHA-256 hashes for allowed license types
4076 */
4077 public static function get_white_label_allowed_license_types() {
4078 $allowed_types = [
4079 'agency' => 'c4b2af4722ee54e317672875b2d8cf49aa884bf5820ec6091114fea5ec6560e4',
4080 'extended' => '4d7120eb6c796b04273577476eb2e20c34c51d7fa1025ec19c3414448abc241e',
4081 'developer' => '88fa0d759f845b47c044c2cd44e29082cf6fea665c30c146374ec7c8f3d699e3',
4082 // Note: AppSumo and Lifetime licenses removed from automatic access
4083 // They require WL flag in other_param for white label functionality
4084 ];
4085
4086 return $allowed_types;
4087 }
4088
4089 /**
4090 * Revoke white label access token
4091 *
4092 * @access public
4093 * @return bool
4094 */
4095 public function revoke_white_label_access_token() {
4096 $token_data = get_option( 'upk_white_label_access_token', [] );
4097
4098 if ( ! empty( $token_data ) ) {
4099 delete_option( 'upk_white_label_access_token' );
4100 return true;
4101 }
4102
4103 return false;
4104 }
4105
4106 /**
4107 * Validate white label access token
4108 *
4109 * @access public
4110 * @param string $token
4111 * @return bool
4112 */
4113 public function validate_white_label_access_token( $token ) {
4114 $stored_token_data = get_option( 'upk_white_label_access_token', [] );
4115
4116 if ( empty( $stored_token_data ) || ! isset( $stored_token_data['token'] ) ) {
4117 return false;
4118 }
4119
4120 // Check token match
4121 if ( $stored_token_data['token'] !== $token ) {
4122 return false;
4123 }
4124
4125 // Check if token was generated for current license
4126 $current_license_key = self::get_license_key();
4127 if ( $stored_token_data['license_key'] !== $current_license_key ) {
4128 return false;
4129 }
4130
4131 return true;
4132 }
4133
4134 /**
4135 * AJAX handler for revoking white label access token
4136 *
4137 * @access public
4138 * @return void
4139 */
4140 public function revoke_white_label_token_ajax() {
4141 // Check nonce and permissions
4142 if (!wp_verify_nonce($_POST['nonce'], 'upk_white_label_nonce')) {
4143 wp_send_json_error(['message' => __('Security check failed', 'ultimate-post-kit')]);
4144 }
4145
4146 if (!current_user_can('manage_options')) {
4147 wp_send_json_error(['message' => __('You do not have permission to manage white label settings', 'ultimate-post-kit')]);
4148 }
4149
4150 // Check license eligibility
4151 if (!self::is_white_label_license()) {
4152 wp_send_json_error(['message' => __('Your license does not support white label features', 'ultimate-post-kit')]);
4153 }
4154
4155 // Revoke the token
4156 $revoked = $this->revoke_white_label_access_token();
4157
4158 if ($revoked) {
4159 wp_send_json_success([
4160 'message' => __('White label access token has been revoked successfully', 'ultimate-post-kit')
4161 ]);
4162 } else {
4163 wp_send_json_error([
4164 'message' => __('No active access token found to revoke', 'ultimate-post-kit')
4165 ]);
4166 }
4167 }
4168
4169 /**
4170 * Get License Key
4171 *
4172 * @access public
4173 * @return string
4174 */
4175
4176 public static function get_license_key() {
4177 $license_key = get_option('ultimate_post_kit_license_key');
4178 return trim($license_key);
4179 }
4180
4181 /**
4182 * Get License Email
4183 *
4184 * @access public
4185 * @return string
4186 */
4187
4188 public static function get_license_email() {
4189 return trim(get_option('ultimate_post_kit_license_email', get_bloginfo('admin_email')));
4190 }
4191
4192 }
4193
4194 new UltimatePostKit_Admin_Settings();
4195