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

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