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

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