PluginProbe
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets / 4.1.2
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets v4.1.2
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.2, at admin/admin-settings.php

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