PluginProbe
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets / 4.5.6
Ultimate Post Kit – Elementor Post Grid, Post Carousel, Post Slider & Blog Layout Widgets v4.5.6
4.5.6 4.5.5 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 All 148 releases
← All changes | admin/admin-settings.php +141 -2292 4.0.9 → 4.5.6 View file →
@@ -5,16 +5,17 @@
5 5 use UltimatePostKit\Admin\ModuleService;
6 6 use Elementor\Modules\Usage\Module;
7 7 use Elementor\Tracker;
8 8
9 +if (!defined('ABSPATH')) {
10 + exit; // Exit if accessed directly.
11 +}
9 12
13 +
10 14 /**
11 15 * Ultimate Post Kit Admin Settings Class
12 16 */
13 17
14 - // Include rollback version functionality
15 -require_once BDTUPK_ADMIN_PATH . 'class-rollback-version.php';
16 -
17 18 class UltimatePostKit_Admin_Settings {
18 19
19 20 public static $modules_list = null;
20 21 public static $modules_names = null;
@@ -36,9 +37,9 @@
36 37
37 38 /**
38 39 * Rollback version instance
39 40 *
40 - * @var UltimatePostKit_Rollback_Version
41 + * @var Rollback_Version
41 42 */
42 43 public $rollback_version;
43 44
44 45 function __construct() {
@@ -47,437 +48,27 @@
47 48 if (!defined('BDTUPK_HIDE')) {
48 49 add_action('admin_init', [$this, 'admin_init']);
49 50 add_action('admin_menu', [$this, 'admin_menu'], 201);
50 51 }
51 -
52 - // Handle white label access link
53 - $this->handle_white_label_access();
54 -
55 - // Add custom CSS/JS functionality
56 - $this->init_custom_code_functionality();
57 -
58 - // White label settings (admin only)
59 - add_action( 'wp_ajax_upk_save_white_label', [ $this, 'save_white_label_ajax' ] );
60 - add_action( 'wp_ajax_upk_revoke_white_label_token', [ $this, 'revoke_white_label_token_ajax' ] );
61 - add_action( 'admin_head', [ $this, 'inject_white_label_icon_css' ] );
62 -
52 +
63 53 // Plugin installation (admin only)
64 54 add_action('wp_ajax_upk_install_plugin', [$this, 'install_plugin_ajax']);
65 -
66 - // Initialize rollback version functionality
67 - $this->rollback_version = new UltimatePostKit\Admin\UltimatePostKit_Rollback_Version();
68 -
69 - }
70 -
71 -
72 - /**
73 - * Initialize Custom Code Functionality
74 - *
75 - * @access public
76 - * @return void
77 - */
78 - public function init_custom_code_functionality() {
79 - // AJAX handler for saving custom code (admin only)
80 - add_action( 'wp_ajax_upk_save_custom_code', [ $this, 'save_custom_code_ajax' ] );
81 55
82 56
83 - // Admin scripts (admin only)
84 - add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_custom_code_scripts' ] );
85 -
86 - // Frontend injection is now handled by global functions in the main plugin file
87 - self::init_frontend_injection();
88 - }
89 57
90 - /**
91 - * Initialize frontend injection hooks (works on both admin and frontend)
92 - *
93 - * @access public static
94 - * @return void
95 - */
96 - public static function init_frontend_injection() {
97 - // Frontend hooks are now registered in the main plugin file
98 - // This method is kept for backwards compatibility but does nothing
99 - }
100 -
101 - /**
102 - * Enqueue scripts for custom code editor
103 - *
104 - * @access public
105 - * @return void
106 - */
107 - public function enqueue_custom_code_scripts( $hook ) {
108 - if ( $hook !== 'toplevel_page_ultimate_post_kit_options' ) {
109 - return;
58 + if (_is_upk_pro_activated()) {
59 + // Initialize rollback version functionality
60 + add_action('admin_init', [$this, 'rollback_init']);
110 61 }
111 62
112 - // Enqueue WordPress built-in CodeMirror
113 - wp_enqueue_code_editor( array( 'type' => 'text/css' ) );
114 - wp_enqueue_code_editor( array( 'type' => 'application/javascript' ) );
115 -
116 - // Enqueue WordPress media library scripts
117 - wp_enqueue_media();
118 -
119 - // Enqueue the admin script if it exists
120 - $admin_script_path = BDTUPK_ASSETS_PATH . 'js/upk-admin.js';
121 - if ( file_exists( $admin_script_path ) ) {
122 - wp_enqueue_script(
123 - 'upk-admin-script',
124 - BDTUPK_ASSETS_URL . 'js/upk-admin.js',
125 - [ 'jquery', 'media-upload', 'media-views', 'code-editor' ],
126 - BDTUPK_VER,
127 - true
128 - );
129 -
130 - // Localize script with AJAX data
131 - wp_localize_script( 'upk-admin-script', 'upk_admin_ajax', [
132 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
133 - 'nonce' => wp_create_nonce( 'upk_custom_code_nonce' ),
134 - 'white_label_nonce' => wp_create_nonce( 'upk_white_label_nonce' )
135 - ] );
136 - } else {
137 - // Fallback: localize to jquery if the admin script doesn't exist
138 - wp_localize_script( 'jquery', 'upk_admin_ajax', [
139 - 'ajax_url' => admin_url( 'admin-ajax.php' ),
140 - 'nonce' => wp_create_nonce( 'upk_custom_code_nonce' ),
141 - 'white_label_nonce' => wp_create_nonce( 'upk_white_label_nonce' )
142 - ] );
143 - }
144 - }
63 + }
145 64
146 - /**
147 - * AJAX handler for saving white label settings
148 - *
149 - * @access public
150 - * @return void
151 - */
152 - public function save_white_label_ajax() {
153 -
154 - // Check nonce and permissions
155 - if (!wp_verify_nonce($_POST['nonce'], 'upk_white_label_nonce')) {
156 - wp_send_json_error(['message' => __('Security check failed', 'ultimate-post-kit')]);
65 + public function rollback_init() {
66 + if ( class_exists('\UltimatePostKitPro\Rollback_Version') ) {
67 + $this->rollback_version = new \UltimatePostKitPro\Rollback_Version();
157 68 }
158 -
159 - if (!current_user_can('manage_options')) {
160 - wp_send_json_error(['message' => __('You do not have permission to manage white label settings', 'ultimate-post-kit')]);
161 - }
162 -
163 - // Check license eligibility
164 - if (!self::is_white_label_license()) {
165 - wp_send_json_error(['message' => __('Your license does not support white label features', 'ultimate-post-kit')]);
166 - }
167 -
168 - // Get white label settings
169 - $white_label_enabled = isset($_POST['upk_white_label_enabled']) ? (bool) $_POST['upk_white_label_enabled'] : false;
170 - $hide_license = isset($_POST['upk_white_label_hide_license']) ? (bool) $_POST['upk_white_label_hide_license'] : false;
171 - $bdtupk_hide = isset($_POST['upk_white_label_bdtupk_hide']) ? (bool) $_POST['upk_white_label_bdtupk_hide'] : false;
172 - $white_label_title = isset($_POST['upk_white_label_title']) ? sanitize_text_field($_POST['upk_white_label_title']) : '';
173 - $white_label_icon = isset($_POST['upk_white_label_icon']) ? esc_url_raw($_POST['upk_white_label_icon']) : '';
174 - $white_label_icon_id = isset($_POST['upk_white_label_icon_id']) ? absint($_POST['upk_white_label_icon_id']) : 0;
175 - $white_label_logo = isset($_POST['upk_white_label_logo']) ? esc_url_raw($_POST['upk_white_label_logo']) : '';
176 - $upk_white_label_logo_id = isset($_POST['upk_white_label_logo_id']) ? absint($_POST['upk_white_label_logo_id']) : 0;
177 -
178 - // Save settings
179 - update_option('upk_white_label_enabled', $white_label_enabled);
180 - update_option('upk_white_label_hide_license', $hide_license);
181 - update_option('upk_white_label_bdtupk_hide', $bdtupk_hide);
182 - update_option('upk_white_label_title', $white_label_title);
183 - update_option('upk_white_label_icon', $white_label_icon);
184 - update_option('upk_white_label_icon_id', $white_label_icon_id);
185 - update_option('upk_white_label_logo', $white_label_logo);
186 - update_option('upk_white_label_logo_id', $upk_white_label_logo_id);
187 -
188 - // Set license title status
189 - if ($white_label_enabled) {
190 - update_option('ultimate_post_kit_license_title_status', true);
191 - } else {
192 - delete_option('ultimate_post_kit_license_title_status');
193 - }
194 -
195 - // Only send access email if both white label mode AND BDTUPK_HIDE are enabled
196 - if ($white_label_enabled && $bdtupk_hide) {
197 - $email_sent = $this->send_white_label_access_email();
198 - }
199 -
200 - wp_send_json_success([
201 - 'message' => __('White label settings saved successfully', 'ultimate-post-kit'),
202 - 'bdtupk_hide' => $bdtupk_hide,
203 - 'email_sent' => isset($email_sent) ? $email_sent : false
204 - ]);
205 69 }
206 70
207 - /**
208 - * Send white label access email with special link
209 - *
210 - * @access private
211 - * @return bool
212 - */
213 - private function send_white_label_access_email() {
214 -
215 - $license_email = self::get_license_email();
216 - $admin_email = get_bloginfo( 'admin_email' );
217 - $license_key = self::get_license_key();
218 - $site_name = get_bloginfo( 'name' );
219 - $site_url = get_bloginfo( 'url' );
220 -
221 - // Generate secure access token with additional entropy
222 - $access_token = wp_hash( $license_key . time() . wp_salt() . wp_generate_password( 32, false ) );
223 -
224 - // Store access token in database with no expiration
225 - $token_data = [
226 - 'token' => $access_token,
227 - 'license_key' => $license_key,
228 - 'created_at' => current_time( 'timestamp' ),
229 - 'user_id' => get_current_user_id()
230 - ];
231 -
232 - update_option( 'upk_white_label_access_token', $token_data );
233 -
234 - // Generate access URL using token instead of license key for security
235 - // Add white_label_tab=1 parameter to automatically switch to White Label tab
236 - $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' );
237 -
238 - // Email subject
239 - $subject = sprintf( '[%s] Ultimate Post Kit White Label Access Instructions', $site_name );
240 -
241 - // Email message
242 - $message = $this->get_white_label_email_template( $site_name, $site_url, $access_url, $license_key );
243 -
244 - // Email headers
245 - $headers = [
246 - 'Content-Type: text/html; charset=UTF-8',
247 - 'From: ' . $site_name . ' <' . $admin_email . '>'
248 - ];
249 -
250 - $email_sent = false;
251 -
252 - // Send to license email
253 - if ( ! empty( $license_email ) && is_email( $license_email ) ) {
254 - $email_sent = wp_mail( $license_email, $subject, $message, $headers );
255 -
256 - // If on localhost or email failed, save email content for manual access
257 - if ( ! $email_sent || $this->is_localhost() ) {
258 - $this->save_email_content_for_localhost( $access_url, $message, $license_email );
259 - }
260 - }
261 -
262 - return $email_sent;
263 - }
264 -
265 - /**
266 - * Check if running on localhost
267 - *
268 - * @access private
269 - * @return bool
270 - */
271 - private function is_localhost() {
272 - $server_name = $_SERVER['SERVER_NAME'] ?? '';
273 - $server_addr = $_SERVER['SERVER_ADDR'] ?? '';
274 -
275 - $localhost_indicators = [
276 - 'localhost',
277 - '127.0.0.1',
278 - '::1',
279 - '.local',
280 - '.test',
281 - '.dev'
282 - ];
283 -
284 - foreach ( $localhost_indicators as $indicator ) {
285 - if ( strpos( $server_name, $indicator ) !== false ||
286 - strpos( $server_addr, $indicator ) !== false ) {
287 - return true;
288 - }
289 - }
290 -
291 - return false;
292 - }
293 -
294 - /**
295 - * Save email content for localhost testing
296 - *
297 - * @access private
298 - * @param string $access_url
299 - * @param string $email_content
300 - * @param string $recipient_email
301 - * @return void
302 - */
303 - private function save_email_content_for_localhost( $access_url, $email_content, $recipient_email ) {
304 - $email_data = [
305 - 'access_url' => $access_url,
306 - 'email_content' => $email_content,
307 - 'recipient_email' => $recipient_email,
308 - 'message' => 'Email functionality not available on localhost. Use the access URL below:'
309 - ];
310 -
311 - // Save for admin notice display
312 - update_option( 'upk_localhost_email_data', $email_data );
313 - }
314 -
315 - /**
316 - * Get white label email template
317 - *
318 - * @access private
319 - * @param string $site_name
320 - * @param string $site_url
321 - * @param string $access_url
322 - * @param string $license_key
323 - * @return string
324 - */
325 - private function get_white_label_email_template( $site_name, $site_url, $access_url, $license_key ) {
326 - $masked_license = substr( $license_key, 0, 8 ) . '****-****-****-' . substr( $license_key, -4 );
327 -
328 - ob_start();
329 - ?>
330 - <!DOCTYPE html>
331 - <html>
332 - <head>
333 - <meta charset="UTF-8">
334 - <title>Ultimate Post Kit White Label Access</title>
335 - <style>
336 - body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
337 - .container { max-width: 600px; margin: 0 auto; padding: 20px; }
338 - .header { background: #2196F3; color: white; padding: 20px; text-align: center; border-radius: 8px 8px 0 0; }
339 - .content { background: #f9f9f9; padding: 30px; border-radius: 0 0 8px 8px; }
340 - .access-link { background: #2196F3; color: white; padding: 15px 25px; text-decoration: none; border-radius: 5px; display: inline-block; margin: 20px 0; }
341 - .warning { background: #fff3cd; border: 1px solid #ffeaa7; padding: 15px; border-radius: 5px; margin: 20px 0; }
342 - .footer { margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd; font-size: 12px; color: #666; }
343 - </style>
344 - </head>
345 - <body>
346 - <div class="container">
347 - <div class="header">
348 - <h1>🔒 Ultimate Post Kit White Label Access</h1>
349 - </div>
350 - <div class="content">
351 - <h2>Important: Save This Email!</h2>
352 -
353 - <p>Hello,</p>
354 -
355 - <p>You have successfully enabled <strong>BDTUPK_HIDE mode</strong> for Ultimate Post Kit Pro on <strong><?php echo esc_html( $site_name ); ?></strong>.</p>
356 -
357 - <div class="warning">
358 - <h3>⚠️ IMPORTANT</h3>
359 - <p>The plugin interface is hidden from your WordPress admin. Use below link to modify white label settings.</p>
360 -
361 - <p style="text-align: center;">
362 - <a href="<?php echo esc_url( $access_url ); ?>" class="access-link">Access White Label Settings</a>
363 - </p>
364 - </div>
365 -
366 - <p><strong>Direct Link:</strong><br>
367 - <a href="<?php echo esc_url( $access_url ); ?>"><?php echo esc_html( $access_url ); ?></a></p>
368 -
369 -
370 - <h3>🔧 What You Can Do</h3>
371 - <p>Using the access link above, you can:</p>
372 - <ul>
373 - <li>Disable BDTUPK_HIDE mode</li>
374 - <li>Modify white label settings</li>
375 - </ul>
376 -
377 - <p>Need help? <a href="https://bdthemes.com/support/" target="_blank">Contact support</a> with your license key.</p>
378 -
379 - </div>
380 - </div>
381 - </body>
382 - </html>
383 - <?php
384 - return ob_get_clean();
385 - }
386 -
387 - /**
388 - * Handle white label access link
389 - *
390 - * @access private
391 - * @return void
392 - */
393 - private function handle_white_label_access() {
394 - // Check if this is a white label access request
395 - if ( ! isset( $_GET['upk_wl'] ) || ! isset( $_GET['token'] ) ) {
396 - return;
397 - }
398 -
399 - // Check user capability
400 - if ( ! current_user_can( 'manage_options' ) ) {
401 - wp_die( 'You do not have sufficient permissions to access this page.' );
402 - }
403 -
404 - $upk_wl = sanitize_text_field( $_GET['upk_wl'] );
405 - $access_token = sanitize_text_field( $_GET['token'] );
406 -
407 - // Check if upk_wl is set to 1
408 - if ( $upk_wl !== '1' ) {
409 - $this->show_access_error( 'Invalid access parameter. Please use the correct link from your email.' );
410 - return;
411 - }
412 -
413 - // Validate the access token
414 - if ( ! $this->validate_white_label_access_token( $access_token ) ) {
415 - $this->show_access_error( 'Invalid or expired access token. Please use the correct access link from your email.' );
416 - return;
417 - }
418 -
419 - // Valid access - temporarily allow access by setting a flag
420 - add_action('admin_init', [$this, 'admin_init']);
421 - add_action('admin_menu', [$this, 'admin_menu'], 201);
422 -
423 - // Add success notice
424 - add_action( 'admin_notices', function() {
425 - echo '<div class="notice notice-success is-dismissible">';
426 - echo '<p><strong>✅ White Label Access Granted!</strong> You can now modify white label settings.</p>';
427 - echo '</div>';
428 - } );
429 - }
430 -
431 - /**
432 - * Show access error page
433 - *
434 - * @access private
435 - * @param string $message
436 - * @return void
437 - */
438 - private function show_access_error( $message ) {
439 - wp_die(
440 - '<h1>🔒 Ultimate Post Kit White Label Access</h1>' .
441 - '<p><strong>Access Denied:</strong> ' . esc_html( $message ) . '</p>' .
442 - '<p>If you need assistance, please contact support with your license information.</p>' .
443 - '<p><a href="' . admin_url() . '" class="button button-primary">← Return to Dashboard</a></p>',
444 - 'Access Denied',
445 - [ 'response' => 403 ]
446 - );
447 - }
448 -
449 - /**
450 - * Inject white label icon CSS
451 - *
452 - * @access public
453 - * @return void
454 - */
455 - public function inject_white_label_icon_css() {
456 - $white_label_enabled = get_option('upk_white_label_enabled', false);
457 - $white_label_icon = get_option('upk_white_label_icon', '');
458 -
459 - // Only inject CSS when white label is enabled AND a custom icon is set
460 - if ( $white_label_enabled && ! empty( $white_label_icon ) ) {
461 - echo '<style type="text/css">';
462 - echo '#toplevel_page_ultimate_post_kit_options .wp-menu-image {';
463 - echo 'background-image: url(' . esc_url( $white_label_icon ) . ') !important;';
464 - echo 'background-size: 20px 20px !important;';
465 - echo 'background-repeat: no-repeat !important;';
466 - echo 'background-position: center !important;';
467 - echo '}';
468 - echo '#toplevel_page_ultimate_post_kit_options .wp-menu-image:before {';
469 - echo 'display: none !important;';
470 - echo '}';
471 - echo '#toplevel_page_ultimate_post_kit_options .wp-menu-image img {';
472 - echo 'display: none !important;';
473 - echo '}';
474 - echo '</style>';
475 - }
476 - // When white label is disabled or no icon is set, don't inject any CSS
477 - // This allows WordPress's original icon to display naturally
478 - }
479 -
480 71 /**
481 72 * Get used widgets.
482 73 *
483 74 * @access public
@@ -492,12 +83,9 @@
492 83 if (class_exists('Elementor\Modules\Usage\Module')) {
493 84
494 85 $module = Module::instance();
495 86
496 - $old_error_level = error_reporting();
497 - error_reporting(E_ALL & ~E_WARNING); // Suppress warnings
498 87 $elements = $module->get_formatted_usage('raw');
499 - error_reporting($old_error_level); // Restore
500 88
501 89 $upk_widgets = self::get_upk_widgets_names();
502 90
503 91 if (is_array($elements) || is_object($elements)) {
@@ -535,12 +123,9 @@
535 123 if (class_exists('Elementor\Modules\Usage\Module')) {
536 124
537 125 $module = Module::instance();
538 126
539 - $old_error_level = error_reporting();
540 - error_reporting(E_ALL & ~E_WARNING); // Suppress warnings
541 127 $elements = $module->get_formatted_usage('raw');
542 - error_reporting($old_error_level); // Restore
543 128
544 129 $upk_widgets = self::get_upk_only_widgets();
545 130
546 131 if (is_array($elements) || is_object($elements)) {
@@ -722,10 +307,12 @@
722 307 */
723 308
724 309 // Redirect to Ultimate Post Kit Pro pricing page
725 310 public function upk_redirect_to_get_pro() {
311 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check of the current admin page slug for display routing, no form data processed.
726 312 if (isset($_GET['page']) && $_GET['page'] === self::PAGE_ID . '_get_pro') {
727 - wp_redirect('https://bdthemes.com/deals/?utm_source=WordPress_org&utm_medium=bfcm_cta&utm_campaign=ultimate_post_kit');
313 + // 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.
314 + wp_redirect('https://postkit.pro/pricing/');
728 315 exit;
729 316 }
730 317 }
731 318
@@ -735,9 +322,11 @@
735 322 * @access public
736 323 *
737 324 */
738 325 public function bdt_redirect_to_renew_link() {
326 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only check of the current admin page slug for display routing, no form data processed.
739 327 if (isset($_GET['page']) && $_GET['page'] === self::PAGE_ID . '_license_renew') {
328 + // 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.
740 329 wp_redirect('https://account.bdthemes.com/');
741 330 exit;
742 331 }
743 332 }
@@ -798,17 +387,8 @@
798 387
799 388 add_submenu_page(
800 389 self::PAGE_ID,
801 390 BDTUPK_TITLE,
802 - esc_html__('Extra Options', 'ultimate-post-kit'),
803 - 'manage_options',
804 - self::PAGE_ID . '#ultimate_post_kit_extra_options',
805 - [$this, 'plugin_page']
806 - );
807 -
808 - add_submenu_page(
809 - self::PAGE_ID,
810 - BDTUPK_TITLE,
811 391 esc_html__('System Status', 'ultimate-post-kit'),
812 392 'manage_options',
813 393 self::PAGE_ID . '#ultimate_post_kit_analytics_system_req',
814 394 [$this, 'plugin_page']
@@ -831,18 +411,18 @@
831 411 // self::PAGE_ID . '#ultimate_post_kit_affiliate',
832 412 // [$this, 'plugin_page']
833 413 // );
834 414
835 - add_submenu_page(
836 - self::PAGE_ID,
837 - BDTUPK_TITLE,
838 - esc_html__('Rollback Version', 'ultimate-post-kit'),
839 - 'manage_options',
840 - self::PAGE_ID . '#ultimate_post_kit_rollback_version',
841 - [$this, 'plugin_page']
842 - );
415 + if (true == _is_upk_pro_activated()) {
416 + add_submenu_page(
417 + self::PAGE_ID,
418 + BDTUPK_TITLE,
419 + esc_html__('Rollback Version', 'ultimate-post-kit'),
420 + 'manage_options',
421 + self::PAGE_ID . '#ultimate_post_kit_rollback_version',
422 + [$this, 'plugin_page']
423 + );
843 424
844 - if (true == _is_upk_pro_activated()) {
845 425 add_submenu_page(
846 426 self::PAGE_ID,
847 427 BDTUPK_TITLE,
848 428 esc_html__('Template Builder', 'ultimate-post-kit'),
@@ -850,19 +430,8 @@
850 430 'edit.php?post_type=upk-template-builder',
851 431 );
852 432 }
853 433
854 - if (true !== _is_upk_pro_activated()) {
855 - add_submenu_page(
856 - self::PAGE_ID,
857 - BDTUPK_TITLE,
858 - esc_html__('Black Friday Limited Offer Up To 87%', 'ultimate-post-kit'),
859 - 'manage_options',
860 - self::PAGE_ID . '_get_pro',
861 - [$this, 'display_page']
862 - );
863 - }
864 -
865 434 }
866 435
867 436 /**
868 437 * Get SVG Icons of Ultimate Post Kit
@@ -950,15 +519,17 @@
950 519 </h1>
951 520 <p class="upk-dashboard-welcome-desc">
952 521 <?php esc_html_e('Empower your web creation with powerful widgets, advanced extensions, ready templates and more.', 'ultimate-post-kit'); ?>
953 522 </p>
954 - <a href="<?php echo admin_url('?upk_setup_wizard=show'); ?>"
523 + <a href="<?php echo esc_url( admin_url( '?upk_setup_wizard=show' ) ); ?>"
955 524 class="bdt-button bdt-welcome-button bdt-margin-small-top"
956 525 target="_blank"><?php esc_html_e('Setup Ultimate Post Kit', 'ultimate-post-kit'); ?></a>
957 526
958 527 <div class="upk-dashboard-compare-section">
959 528 <h4 class="upk-feature-sub-title">
960 - <?php printf(esc_html__('Unlock %sPremium Features%s', 'ultimate-post-kit'), '<strong class="upk-highlight-text">', '</strong>'); ?>
529 + <?php
530 + /* translators: 1: opening strong tag, 2: closing strong tag */
531 + printf(esc_html__('Unlock %1$sPremium Features%2$s', 'ultimate-post-kit'), '<strong class="upk-highlight-text">', '</strong>'); ?>
961 532 </h4>
962 533 <h1 class="upk-feature-title upk-dashboard-compare-title">
963 534 <?php esc_html_e('Create Your Sleek Website with Ultimate Post Kit Pro!', 'ultimate-post-kit'); ?>
964 535 </h1>
@@ -984,10 +555,10 @@
984 555 </div>
985 556
986 557 <div class="upk-dashboard-item upk-dashboard-template-quick-access bdt-card bdt-card-body">
987 558 <div class="upk-dashboard-template-section">
988 - <img src="<?php echo BDTUPK_ADMIN_URL . 'assets/images/template.jpg'; ?>"
989 - alt="Ultimate Post Kit Dashboard Template">
559 + <img src="<?php echo esc_url( BDTUPK_ADMIN_URL . 'assets/images/template.jpg' ); ?>"
560 + alt="<?php echo esc_attr__( 'Ultimate Post Kit Dashboard Template', 'ultimate-post-kit' ); ?>">
990 561 <h1 class="upk-feature-title ">
991 562 <?php esc_html_e('Faster Web Creation with Sleek and Ready-to-Use Templates!', 'ultimate-post-kit'); ?>
992 563 </h1>
993 564 <p><?php esc_html_e('Build your wordpress websites of any niche—not from scratch and in a single click.', 'ultimate-post-kit'); ?>
@@ -997,10 +568,10 @@
997 568 target="_blank"><?php esc_html_e('View Templates', 'ultimate-post-kit'); ?></a>
998 569 </div>
999 570
1000 571 <div class="upk-dashboard-quick-access bdt-margin-medium-top">
1001 - <img src="<?php echo BDTUPK_ADMIN_URL . 'assets/images/support.jpg'; ?>"
1002 - alt="Ultimate Post Kit Dashboard Template">
572 + <img src="<?php echo esc_url( BDTUPK_ADMIN_URL . 'assets/images/support.jpg' ); ?>"
573 + alt="<?php echo esc_attr__( 'Ultimate Post Kit Dashboard Template', 'ultimate-post-kit' ); ?>">
1003 574 <h1 class="upk-feature-title">
1004 575 <?php esc_html_e('Getting Started with Quick Access', 'ultimate-post-kit'); ?>
1005 576 </h1>
1006 577 <ul>
@@ -1044,9 +615,9 @@
1044 615 <h1 class="upk-feature-title"><?php esc_html_e('Watch Video Tutorials', 'ultimate-post-kit'); ?></h1>
1045 616 <p><?php esc_html_e('An invaluable resource for mastering WordPress, Elementor, and Web Creation', 'ultimate-post-kit'); ?>
1046 617 </p>
1047 618 </a>
1048 - <a href="https://bdthemes.com/all-knowledge-base-of-ultimate-post-kit/" target="_blank"
619 + <a href="https://bdthemes.com/knowledge-base/ultimate-post-kit/" target="_blank"
1049 620 class="upk-dashboard-item upk-dashboard-footer-item upk-dashboard-documentation bdt-card bdt-card-body bdt-card-small">
1050 621 <span class="upk-dashboard-footer-item-icon">
1051 622 <i class="dashicons dashicons-admin-tools"></i>
1052 623 </span>
@@ -1103,9 +674,9 @@
1103 674
1104 675 </div>
1105 676 <?php if (true !== _is_upk_pro_activated()) : ?>
1106 677 <div class="upk-purchase-button">
1107 - <a href="https://postkit.pro/#a851ca7" target="_blank">
678 + <a href="https://postkit.pro/pricing/" target="_blank">
1108 679 <?php echo esc_html_x('Purchase Now', 'Frontend', 'ultimate-post-kit'); ?>
1109 680 </a>
1110 681 </div>
1111 682 <?php endif; ?>
@@ -1338,9 +909,9 @@
1338 909 <!-- <div class="upk-dashboard-divider"></div> -->
1339 910
1340 911 <?php if (true !== _is_upk_pro_activated()) : ?>
1341 912 <div class="upk-purchase-button bdt-margin-medium-top">
1342 - <a href="https://postkit.pro/#a851ca7" target="_blank">
913 + <a href="https://postkit.pro/pricing/" target="_blank">
1343 914 <?php echo esc_html_x('Purchase Now', 'Frontend', 'ultimate-post-kit'); ?>
1344 915 </a>
1345 916 </div>
1346 917 <?php endif; ?>
@@ -1383,20 +954,10 @@
1383 954 <span class="upk-header-element upk-header-wave"></span>
1384 955 </div>
1385 956
1386 957 <div class="upk-logo">
1387 - <?php
1388 - $white_label_enabled = get_option( 'upk_white_label_enabled', false );
1389 - $white_label_logo = get_option( 'upk_white_label_logo', '' );
1390 - $white_label_title = get_option( 'upk_white_label_title', '' );
1391 -
1392 - if ($white_label_enabled && !empty($white_label_logo)) {
1393 -
1394 - $alt_text = !empty($white_label_title) ? $white_label_title . ' Logo' : 'Custom Logo';
1395 - echo '<img src="' . esc_url($white_label_logo) . '" alt="' . esc_attr($alt_text) . '" style="max-height: 40px;">';
1396 - } else {
1397 - echo '<img src="' . BDTUPK_URL . 'assets/images/logo-with-text.svg" alt="Ultimate Post Kit Logo">';
1398 - }
958 + <?php
959 + echo '<img src="' . esc_url( BDTUPK_URL . 'assets/images/logo-with-text.svg' ) . '" alt="' . esc_attr__( 'Ultimate Post Kit Logo', 'ultimate-post-kit' ) . '">';
1399 960 ?>
1400 961 </div>
1401 962 </div>
1402 963
@@ -1409,29 +970,9 @@
1409 970 <?php esc_html_e('Save Settings', 'ultimate-post-kit'); ?>
1410 971 </button>
1411 972 </div>
1412 973
1413 - <!-- Custom Code Save Button Section -->
1414 - <div class="upk-code-save-section" style="display: none;">
1415 - <button type="button" id="upk-save-custom-code" class="bdt-button bdt-button-primary ultimate-post-kit-custom-code-save-btn">
1416 - <?php esc_html_e('Save Custom Code', 'ultimate-post-kit'); ?>
1417 - </button>
1418 - <button type="button" id="upk-reset-custom-code" class="bdt-button bdt-button-primary ultimate-post-kit-custom-code-reset-btn">
1419 - <?php esc_html_e('Reset Code', 'ultimate-post-kit'); ?>
1420 - </button>
1421 - </div>
1422 974
1423 - <!-- White Label Save Button Section -->
1424 - <?php if (self::is_white_label_license()): ?>
1425 - <div class="upk-white-label-save-section" style="display: none;">
1426 - <button type="button"
1427 - id="upk-save-white-label"
1428 - class="bdt-button bdt-button-primary ultimate-post-kit-white-label-save-btn">
1429 - <?php esc_html_e('Save White Label Settings', 'ultimate-post-kit'); ?>
1430 - </button>
1431 - </div>
1432 - <?php endif; ?>
1433 -
1434 975 <div class="upk-dashboard-new-page">
1435 976 <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>
1436 977 <?php echo esc_html__('Create New Page', 'ultimate-post-kit') ?>
1437 978 </a>
@@ -1465,12 +1006,8 @@
1465 1006 </div>
1466 1007
1467 1008 <?php $this->settings_api->show_forms(); ?>
1468 1009
1469 - <div id="ultimate_post_kit_extra_options_page" class="upk-option-page group">
1470 - <?php $this->ultimate_post_kit_extra_options(); ?>
1471 - </div>
1472 -
1473 1010 <div id="ultimate_post_kit_analytics_system_req_page" class="upk-option-page group">
1474 1011 <?php $this->ultimate_post_kit_analytics_system_req_content(); ?>
1475 1012 </div>
1476 1013
@@ -1481,11 +1018,13 @@
1481 1018 <!-- <div id="ultimate_post_kit_affiliate_page" class="upk-option-page group">
1482 1019 <?php //$this->ultimate_post_kit_affiliate_content(); ?>
1483 1020 </div> -->
1484 1021
1485 - <div id="ultimate_post_kit_rollback_version_page" class="upk-option-page group">
1486 - <?php $this->ultimate_post_kit_rollback_version_content(); ?>
1487 - </div>
1022 + <?php if (true == _is_upk_pro_activated()) : ?>
1023 + <div id="ultimate_post_kit_rollback_version_page" class="upk-option-page group">
1024 + <?php $this->upk_rollback_version_content(); ?>
1025 + </div>
1026 + <?php endif; ?>
1488 1027
1489 1028 <?php if (_is_upk_pro_activated() !== true) : ?>
1490 1029 <div id="ultimate_post_kit_get_pro" class="upk-option-page group">
1491 1030 <?php $this->ultimate_post_kit_get_pro(); ?>
@@ -1491,12 +1030,29 @@
1491 1030 <?php $this->ultimate_post_kit_get_pro(); ?>
1492 1031 </div>
1493 1032 <?php endif; ?>
1494 1033
1034 + <?php
1035 + // Render tab bodies for any add-on-registered dashboard tabs.
1036 + // The core plugin provides only this extension point; the tab
1037 + // ids/order match the nav items built in show_navigation().
1038 + foreach ($this->settings_api->get_extra_dashboard_tabs() as $upk_extra_tab) {
1039 + if (empty($upk_extra_tab['id'])) {
1040 + continue;
1041 + }
1042 + echo '<div id="' . esc_attr($upk_extra_tab['id']) . '_page" class="upk-option-page group">';
1043 + if (isset($upk_extra_tab['callback']) && is_callable($upk_extra_tab['callback'])) {
1044 + call_user_func($upk_extra_tab['callback']);
1045 + }
1046 + echo '</div>';
1047 + }
1048 + ?>
1049 +
1495 1050 <div id="ultimate_post_kit_license_settings_page" class="upk-option-page group">
1496 1051
1497 1052 <?php
1498 1053 if (_is_upk_pro_activated() == true) {
1054 + // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- established hook name relied on across the plugin family; renaming would break integration.
1499 1055 apply_filters('upk_license_page', '');
1500 1056 }
1501 1057
1502 1058 ?>
@@ -1526,29 +1082,48 @@
1526 1082 *
1527 1083 * This code uses localstorage for displaying active tabs
1528 1084 */
1529 1085 function script() {
1530 - ?>
1086 + ?>
1531 1087 <script>
1532 1088 jQuery(document).ready(function() {
1533 1089 jQuery('.upk-no-result').removeClass('bdt-animation-shake');
1534 1090 });
1535 1091
1092 + // Selector of the filter controls that are currently active (Free is active by default).
1093 + function activeFilterSelector($parent) {
1094 + return $parent.find('.upk-widget-filter li.bdt-active')
1095 + .map(function() {
1096 + var control = jQuery(this).attr('bdt-filter-control') || '';
1097 + var matched = control.match(/filter:\s*([^;]+)/);
1098 + return matched ? jQuery.trim(matched[1]) : null;
1099 + })
1100 + .get()
1101 + .join('');
1102 + }
1103 +
1536 1104 function filterSearch(e) {
1537 1105 var parentID = '#' + jQuery(e).data('id');
1538 - var search = jQuery(parentID).find('.bdt-search-input').val().toLowerCase();
1106 + var $parent = jQuery(parentID);
1107 + var search = $parent.find('.bdt-search-input').val().toLowerCase();
1539 1108
1540 - jQuery(".upk-options .upk-option-item").filter(function() {
1541 - jQuery(this).toggle(jQuery(this).attr('data-widget-name').toLowerCase().indexOf(search) > -1)
1109 + // Search runs on top of the active filter and only inside its own tab, so clearing
1110 + // the search never falls back to showing every widget.
1111 + var filterSelector = activeFilterSelector($parent);
1112 +
1113 + $parent.find('.upk-options .upk-option-item').each(function() {
1114 + var name = (jQuery(this).attr('data-widget-name') || '').toLowerCase();
1115 + var matchesSearch = name.indexOf(search) > -1;
1116 + var matchesFilter = !filterSelector || jQuery(this).is(filterSelector);
1117 +
1118 + jQuery(this).toggle(matchesSearch && matchesFilter);
1542 1119 });
1543 1120
1544 1121 if (!search) {
1545 - jQuery(parentID).find('.bdt-search-input').attr('bdt-filter-control', "");
1546 - jQuery(parentID).find('.upk-widget-all').trigger('click');
1122 + $parent.find('.bdt-search-input').attr('bdt-filter-control', "");
1547 1123 } else {
1548 - jQuery(parentID).find('.bdt-search-input').attr('bdt-filter-control', "filter: [data-widget-name*='" + search + "']");
1549 - jQuery(parentID).find('.bdt-search-input').removeClass('bdt-active'); // Thanks to Bar-Rabbas
1550 - jQuery(parentID).find('.bdt-search-input').trigger('click');
1124 + $parent.find('.bdt-search-input').attr('bdt-filter-control', "filter: [data-widget-name*='" + search + "']");
1125 + $parent.find('.bdt-search-input').removeClass('bdt-active'); // Thanks to Bar-Rabbas
1551 1126 }
1552 1127 }
1553 1128
1554 1129 jQuery('.upk-options-parent').each(function(e, item) {
@@ -1890,719 +1465,8 @@
1890 1465 });
1891 1466 }
1892 1467 });
1893 1468
1894 - //White Label Settings Functionality
1895 - //Check if upk_admin_ajax is available
1896 - if (typeof upk_admin_ajax === 'undefined') {
1897 - window.upk_admin_ajax = {
1898 - ajax_url: '<?php echo admin_url('admin-ajax.php'); ?>',
1899 - white_label_nonce: '<?php echo wp_create_nonce('upk_white_label_nonce'); ?>'
1900 - };
1901 - }
1902 -
1903 - // Initialize CodeMirror editors for custom code
1904 - var codeMirrorEditors = {};
1905 -
1906 - function initializeCodeMirrorEditors() {
1907 - // CSS Editor 1
1908 - if (document.getElementById('upk-custom-css')) {
1909 - codeMirrorEditors['upk-custom-css'] = wp.codeEditor.initialize('upk-custom-css', {
1910 - type: 'text/css',
1911 - codemirror: {
1912 - lineNumbers: true,
1913 - mode: 'css',
1914 - theme: 'default',
1915 - lineWrapping: true,
1916 - autoCloseBrackets: true,
1917 - matchBrackets: true,
1918 - lint: false
1919 - }
1920 - });
1921 - }
1922 -
1923 - // JavaScript Editor 1
1924 - if (document.getElementById('upk-custom-js')) {
1925 - codeMirrorEditors['upk-custom-js'] = wp.codeEditor.initialize('upk-custom-js', {
1926 - type: 'application/javascript',
1927 - codemirror: {
1928 - lineNumbers: true,
1929 - mode: 'javascript',
1930 - theme: 'default',
1931 - lineWrapping: true,
1932 - autoCloseBrackets: true,
1933 - matchBrackets: true,
1934 - lint: false
1935 - }
1936 - });
1937 - }
1938 -
1939 - // CSS Editor 2
1940 - if (document.getElementById('upk-custom-css-2')) {
1941 - codeMirrorEditors['upk-custom-css-2'] = wp.codeEditor.initialize('upk-custom-css-2', {
1942 - type: 'text/css',
1943 - codemirror: {
1944 - lineNumbers: true,
1945 - mode: 'css',
1946 - theme: 'default',
1947 - lineWrapping: true,
1948 - autoCloseBrackets: true,
1949 - matchBrackets: true,
1950 - lint: false
1951 - }
1952 - });
1953 - }
1954 -
1955 - // JavaScript Editor 2
1956 - if (document.getElementById('upk-custom-js-2')) {
1957 - codeMirrorEditors['upk-custom-js-2'] = wp.codeEditor.initialize('upk-custom-js-2', {
1958 - type: 'application/javascript',
1959 - codemirror: {
1960 - lineNumbers: true,
1961 - mode: 'javascript',
1962 - theme: 'default',
1963 - lineWrapping: true,
1964 - autoCloseBrackets: true,
1965 - matchBrackets: true,
1966 - lint: false
1967 - }
1968 - });
1969 - }
1970 -
1971 - // Refresh all editors after a short delay to ensure proper rendering
1972 - setTimeout(function() {
1973 - refreshAllCodeMirrorEditors();
1974 - }, 100);
1975 - }
1976 -
1977 - // Function to refresh all CodeMirror editors
1978 - function refreshAllCodeMirrorEditors() {
1979 - Object.keys(codeMirrorEditors).forEach(function(editorKey) {
1980 - if (codeMirrorEditors[editorKey] && codeMirrorEditors[editorKey].codemirror) {
1981 - codeMirrorEditors[editorKey].codemirror.refresh();
1982 - }
1983 - });
1984 - }
1985 -
1986 - // Function to refresh editors when tab becomes visible
1987 - function refreshEditorsOnTabShow() {
1988 - // Listen for tab changes (UIkit tab switching)
1989 - if (typeof bdtUIkit !== 'undefined' && bdtUIkit.tab) {
1990 - // When tab becomes active, refresh editors
1991 - bdtUIkit.util.on(document, 'shown', '.bdt-tab', function() {
1992 - setTimeout(function() {
1993 - refreshAllCodeMirrorEditors();
1994 - }, 50);
1995 - });
1996 - }
1997 -
1998 - // Also listen for direct tab clicks
1999 - $('.bdt-tab a').on('click', function() {
2000 - setTimeout(function() {
2001 - refreshAllCodeMirrorEditors();
2002 - }, 100);
2003 - });
2004 -
2005 - // Listen for switcher changes (UIkit switcher)
2006 - if (typeof bdtUIkit !== 'undefined' && bdtUIkit.switcher) {
2007 - bdtUIkit.util.on(document, 'shown', '.bdt-switcher', function() {
2008 - setTimeout(function() {
2009 - refreshAllCodeMirrorEditors();
2010 - }, 50);
2011 - });
2012 - }
2013 - }
2014 -
2015 - // Initialize editors when page loads - with delay for better rendering
2016 - setTimeout(function() {
2017 - initializeCodeMirrorEditors();
2018 - }, 100);
2019 -
2020 - // Setup tab switching handlers
2021 - setTimeout(function() {
2022 - refreshEditorsOnTabShow();
2023 - }, 100);
2024 -
2025 - // Handle window resize events
2026 - $(window).on('resize', function() {
2027 - setTimeout(function() {
2028 - refreshAllCodeMirrorEditors();
2029 - }, 100);
2030 - });
2031 -
2032 - // Handle page visibility changes (when switching browser tabs)
2033 - document.addEventListener('visibilitychange', function() {
2034 - if (!document.hidden) {
2035 - setTimeout(function() {
2036 - refreshAllCodeMirrorEditors();
2037 - }, 200);
2038 - }
2039 - });
2040 -
2041 - // Force refresh when clicking on the Custom CSS & JS tab specifically
2042 - $('a[href="#"]').on('click', function() {
2043 - var tabText = $(this).text().trim();
2044 - if (tabText === 'Custom CSS & JS') {
2045 - setTimeout(function() {
2046 - refreshAllCodeMirrorEditors();
2047 - }, 150);
2048 - }
2049 - });
2050 -
2051 - //Toggle white label fields visibility
2052 - $('#upk-white-label-enabled').on('change', function() {
2053 - if ($(this).is(':checked')) {
2054 - $('.upk-white-label-fields').slideDown(300);
2055 - } else {
2056 - $('.upk-white-label-fields').slideUp(300);
2057 - }
2058 - });
2059 -
2060 - //WordPress Media Library Integration for Icon Upload
2061 - var mediaUploader;
2062 -
2063 - $('#upk-upload-icon').on('click', function(e) {
2064 - e.preventDefault();
2065 -
2066 - // If the uploader object has already been created, reopen the dialog
2067 - if (mediaUploader) {
2068 - mediaUploader.open();
2069 - return;
2070 - }
2071 -
2072 - // Create the media frame
2073 - mediaUploader = wp.media.frames.file_frame = wp.media({
2074 - title: 'Select Icon',
2075 - button: {
2076 - text: 'Use This Icon'
2077 - },
2078 - library: {
2079 - type: ['image/jpeg', 'image/jpg', 'image/png', 'image/svg+xml']
2080 - },
2081 - multiple: false
2082 - });
2083 -
2084 - // When an image is selected, run a callback
2085 - mediaUploader.on('select', function() {
2086 - var attachment = mediaUploader.state().get('selection').first().toJSON();
2087 -
2088 - // Set the hidden inputs
2089 - $('#upk-white-label-icon').val(attachment.url);
2090 - $('#upk-white-label-icon-id').val(attachment.id);
2091 -
2092 - // Update preview
2093 - $('#upk-icon-preview-img').attr('src', attachment.url);
2094 - $('.upk-icon-preview-container').show();
2095 - });
2096 -
2097 - // Open the uploader dialog
2098 - mediaUploader.open();
2099 - });
2100 -
2101 - //Remove icon functionality
2102 - $('#upk-remove-icon').on('click', function(e) {
2103 - e.preventDefault();
2104 -
2105 - // Clear the hidden inputs
2106 - $('#upk-white-label-icon').val('');
2107 - $('#upk-white-label-icon-id').val('');
2108 -
2109 - // Hide preview
2110 - $('.upk-icon-preview-container').hide();
2111 - $('#upk-icon-preview-img').attr('src', '');
2112 - });
2113 -
2114 - // WordPress Media Library Integration for Logo Upload
2115 - var logoUploader;
2116 -
2117 - $('#upk-upload-logo').on('click', function(e) {
2118 - e.preventDefault();
2119 -
2120 - // If the uploader object has already been created, reopen the dialog
2121 - if (logoUploader) {
2122 - logoUploader.open();
2123 - return;
2124 - }
2125 -
2126 - // Create the media frame
2127 - logoUploader = wp.media.frames.file_frame = wp.media({
2128 - title: 'Select Logo',
2129 - button: {
2130 - text: 'Use This Logo'
2131 - },
2132 - library: {
2133 - type: ['image/jpeg', 'image/jpg', 'image/png', 'image/svg+xml']
2134 - },
2135 - multiple: false
2136 - });
2137 -
2138 - // When an image is selected, run a callback
2139 - logoUploader.on('select', function() {
2140 - var attachment = logoUploader.state().get('selection').first().toJSON();
2141 -
2142 - // Set the hidden inputs
2143 - $('#upk-white-label-logo').val(attachment.url);
2144 - $('#upk-white-label-logo-id').val(attachment.id);
2145 -
2146 - // Update preview
2147 - $('#upk-logo-preview-img').attr('src', attachment.url);
2148 - $('.upk-logo-preview-container').show();
2149 - });
2150 -
2151 - // Open the uploader dialog
2152 - logoUploader.open();
2153 - });
2154 -
2155 - // Remove logo functionality
2156 - $('#upk-remove-logo').on('click', function(e) {
2157 - e.preventDefault();
2158 -
2159 - // Clear the hidden inputs
2160 - $('#upk-white-label-logo').val('');
2161 - $('#upk-white-label-logo-id').val('');
2162 -
2163 - // Hide preview
2164 - $('.upk-logo-preview-container').hide();
2165 - $('#upk-logo-preview-img').attr('src', '');
2166 - });
2167 -
2168 - //BDTUPK_HIDE Warning when checkbox is enabled
2169 - $('#upk-white-label-bdtupk-hide').on('change', function() {
2170 - if ($(this).is(':checked')) {
2171 - // Show warning modal/alert
2172 - var warningMessage = '⚠️ WARNING: ADVANCED FEATURE\n\n' +
2173 - 'Enabling BDTUPK_HIDE will activate advanced white label mode that:\n\n' +
2174 - '• Hides ALL Element Pack branding and menus\n' +
2175 - '• Makes these settings difficult to access later\n' +
2176 - '• Requires the special access link to return\n' +
2177 - '• Is intended for client/agency use only\n\n' +
2178 - 'An email with access instructions will be sent if you proceed.\n\n' +
2179 - 'Are you sure you want to enable this advanced mode?';
2180 -
2181 - if (!confirm(warningMessage)) {
2182 - // User cancelled, uncheck the box
2183 - $(this).prop('checked', false);
2184 - return false;
2185 - }
2186 -
2187 - // Show additional info message
2188 - if ($('#upk-bdtupk-hide-info').length === 0) {
2189 - $(this).closest('.upk-option-item').after(
2190 - '<div id="upk-bdtupk-hide-info" class="bdt-alert bdt-alert-warning bdt-margin-small-top">' +
2191 - '<p><strong>BDTUPK_HIDE Mode Enabled</strong></p>' +
2192 - '<p>When you save these settings, an email will be sent with instructions to access white label settings in the future.</p>' +
2193 - '</div>'
2194 - );
2195 - }
2196 - } else {
2197 - // Remove info message when unchecked
2198 - $('#upk-bdtupk-hide-info').remove();
2199 - }
2200 - });
2201 -
2202 - // Save white label settings with confirmation
2203 - $('#upk-save-white-label').on('click', function(e) {
2204 - e.preventDefault();
2205 -
2206 - // Check if button is disabled (no license or no white label eligible license)
2207 - if ($(this).prop('disabled')) {
2208 - var buttonText = $(this).text().trim();
2209 - var alertMessage = '';
2210 -
2211 - if (buttonText.includes('License Not Activated')) {
2212 - alertMessage = '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2213 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2214 - '<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>' +
2215 - '</div>';
2216 - } else {
2217 - alertMessage = '<div class="bdt-alert bdt-alert-warning" bdt-alert>' +
2218 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2219 - '<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>' +
2220 - '</div>';
2221 - }
2222 -
2223 - $('#upk-white-label-message').html(alertMessage).show();
2224 - return false;
2225 - }
2226 -
2227 - // Check if white label mode is being enabled
2228 - var whiteLabelEnabled = $('#upk-white-label-enabled').is(':checked');
2229 - var bdtupkHideEnabled = $('#upk-white-label-bdtupk-hide').is(':checked');
2230 -
2231 - // Only show confirmation dialog if white label is enabled AND BDTUPK_HIDE is enabled
2232 - if (whiteLabelEnabled && bdtupkHideEnabled) {
2233 - var confirmMessage = '🔒 FINAL CONFIRMATION\n\n' +
2234 - 'You are about to save settings with BDTUPK_HIDE enabled.\n\n' +
2235 - 'This will:\n' +
2236 - '• Hide Ultimate Post Kit from WordPress admin immediately\n' +
2237 - '• Send access instructions to your email addresses\n' +
2238 - '• Require the special link to modify these settings\n\n' +
2239 - 'Email will be sent to:\n' +
2240 - '• License email: <?php echo esc_js(self::get_license_email()); ?>\n' +
2241 - 'Are you absolutely sure you want to proceed?';
2242 -
2243 - if (!confirm(confirmMessage)) {
2244 - return false;
2245 - }
2246 - }
2247 -
2248 - var $button = $(this);
2249 - var originalText = $button.html();
2250 -
2251 - // Show loading state
2252 - $button.html('Saving...');
2253 - $button.prop('disabled', true);
2254 -
2255 - // Collect form data
2256 - var formData = {
2257 - action: 'upk_save_white_label',
2258 - nonce: upk_admin_ajax.white_label_nonce,
2259 - upk_white_label_enabled: $('#upk-white-label-enabled').is(':checked') ? 1 : 0,
2260 - upk_white_label_title: $('#upk-white-label-title').val(),
2261 - upk_white_label_icon: $('#upk-white-label-icon').val(),
2262 - upk_white_label_icon_id: $('#upk-white-label-icon-id').val(),
2263 - upk_white_label_logo: $('#upk-white-label-logo').val(),
2264 - upk_white_label_logo_id: $('#upk-white-label-logo-id').val(),
2265 - upk_white_label_hide_license: $('#upk-white-label-hide-license').is(':checked') ? 1 : 0,
2266 - upk_white_label_bdtupk_hide: $('#upk-white-label-bdtupk-hide').is(':checked') ? 1 : 0
2267 - };
2268 -
2269 - // Send AJAX request
2270 - $.post(upk_admin_ajax.ajax_url, formData)
2271 - .done(function(response) {
2272 - if (response.success) {
2273 - // Show success message with countdown
2274 - var countdown = 2;
2275 - var successMessage = response.data.message;
2276 -
2277 - // Add email notification info if BDTUPK_HIDE was enabled
2278 - if (response.data.bdtupk_hide && response.data.email_sent) {
2279 - successMessage += '<br><br><strong>📧 Access Email Sent!</strong><br>Check your email for the access link to modify these settings in the future.';
2280 - } else if (response.data.bdtupk_hide && !response.data.email_sent && response.data.access_url) {
2281 - // Localhost scenario - show the access URL directly
2282 - 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>';
2283 - } else if (response.data.bdtupk_hide && !response.data.email_sent) {
2284 - successMessage += '<br><br><strong>⚠️ Email Notice:</strong><br>There was an issue sending the access email. Please check your email settings or contact support.';
2285 - }
2286 -
2287 - $('#upk-white-label-message').html(
2288 - '<div class="bdt-alert bdt-alert-success" bdt-alert>' +
2289 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2290 - '<p>' + successMessage + ' <span id="upk-reload-countdown">Reloading in ' + countdown + ' seconds...</span></p>' +
2291 - '</div>'
2292 - ).show();
2293 -
2294 - // Update button text
2295 - $button.html('Reloading...');
2296 -
2297 - // Countdown timer
2298 - var countdownInterval = setInterval(function() {
2299 - countdown--;
2300 - if (countdown > 0) {
2301 - $('#upk-reload-countdown').text('Reloading in ' + countdown + ' seconds...');
2302 - } else {
2303 - $('#upk-reload-countdown').text('Reloading now...');
2304 - clearInterval(countdownInterval);
2305 - }
2306 - }, 1000);
2307 -
2308 - // Check if BDTUPK_HIDE is enabled and redirect accordingly
2309 - setTimeout(function() {
2310 - if (response.data.bdtupk_hide) {
2311 - // Redirect to admin dashboard if BDTUPK_HIDE is enabled
2312 - window.location.href = '<?php echo admin_url('index.php'); ?>';
2313 - } else {
2314 - // Reload current page if BDTUPK_HIDE is not enabled
2315 - window.location.reload();
2316 - }
2317 - }, 1500);
2318 - } else {
2319 - // Show error message
2320 - $('#upk-white-label-message').html(
2321 - '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2322 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2323 - '<p>Error: ' + (response.data.message || 'Unknown error occurred') + '</p>' +
2324 - '</div>'
2325 - ).show();
2326 -
2327 - // Restore button state for error case
2328 - $button.html(originalText);
2329 - $button.prop('disabled', false);
2330 - }
2331 - })
2332 - .fail(function(xhr, status, error) {
2333 - // Show error message
2334 - $('#upk-white-label-message').html(
2335 - '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2336 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2337 - '<p>Error: Failed to save settings. Please try again. (' + status + ')</p>' +
2338 - '</div>'
2339 - ).show();
2340 -
2341 - // Restore button state for failure case
2342 - $button.html(originalText);
2343 - $button.prop('disabled', false);
2344 - });
2345 - });
2346 -
2347 - // Save custom code functionality (updated for CodeMirror)
2348 - $('#upk-save-custom-code').on('click', function(e) {
2349 - e.preventDefault();
2350 -
2351 - var $button = $(this);
2352 - var originalText = $button.html();
2353 -
2354 - // Check if upk_admin_ajax is available
2355 - if (typeof upk_admin_ajax === 'undefined') {
2356 - $('#upk-custom-code-message').html(
2357 - '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2358 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2359 - '<p>Error: AJAX configuration not loaded. Please refresh the page and try again.</p>' +
2360 - '</div>'
2361 - ).show();
2362 - return;
2363 - }
2364 -
2365 - // Prevent multiple simultaneous saves
2366 - if ($button.prop('disabled') || $button.hasClass('upk-saving')) {
2367 - return;
2368 - }
2369 -
2370 - // Mark as saving
2371 - $button.addClass('upk-saving');
2372 -
2373 - // Get content from CodeMirror editors
2374 - function getCodeMirrorContent(elementId) {
2375 - if (codeMirrorEditors[elementId] && codeMirrorEditors[elementId].codemirror) {
2376 - return codeMirrorEditors[elementId].codemirror.getValue();
2377 - } else {
2378 - // Fallback to textarea value
2379 - return $('#' + elementId).val() || '';
2380 - }
2381 - }
2382 -
2383 - var cssContent = getCodeMirrorContent('upk-custom-css');
2384 - var jsContent = getCodeMirrorContent('upk-custom-js');
2385 - var css2Content = getCodeMirrorContent('upk-custom-css-2');
2386 - var js2Content = getCodeMirrorContent('upk-custom-js-2');
2387 -
2388 - // Show loading state
2389 - $button.prop('disabled', true);
2390 -
2391 - // Timeout safeguard - if AJAX doesn't complete in 30 seconds, restore button
2392 - var timeoutId = setTimeout(function() {
2393 - $button.removeClass('upk-saving');
2394 - $button.html(originalText);
2395 - $button.prop('disabled', false);
2396 - $('#upk-custom-code-message').html(
2397 - '<div class="bdt-alert bdt-alert-warning" bdt-alert>' +
2398 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2399 - '<p>Save operation timed out. Please try again.</p>' +
2400 - '</div>'
2401 - ).show();
2402 - }, 30000);
2403 -
2404 - // Collect form data
2405 - var formData = {
2406 - action: 'upk_save_custom_code',
2407 - nonce: upk_admin_ajax.nonce,
2408 - custom_css: cssContent,
2409 - custom_js: jsContent,
2410 - custom_css_2: css2Content,
2411 - custom_js_2: js2Content,
2412 - excluded_pages: $('#upk-excluded-pages').val() || []
2413 - };
2414 -
2415 -
2416 - // Verify we have some content before sending (optional check)
2417 - var totalContentLength = cssContent.length + jsContent.length + css2Content.length + js2Content.length;
2418 - if (totalContentLength === 0) {
2419 - var confirmEmpty = confirm('No content detected in any editor. Do you want to save empty content (this will clear all custom code)?');
2420 - if (!confirmEmpty) {
2421 - // Restore button state
2422 - $button.html(originalText);
2423 - $button.prop('disabled', false);
2424 - return;
2425 - }
2426 - }
2427 -
2428 - // Send AJAX request
2429 - $.post(upk_admin_ajax.ajax_url, formData)
2430 - .done(function(response) {
2431 - console.log('AJAX Response:', response); // Debug log
2432 -
2433 - if (response && response.success) {
2434 - // Show success message
2435 - var successMessage = response.data.message;
2436 - if (response.data.excluded_count) {
2437 - successMessage += ' (' + response.data.excluded_count + ' pages excluded)';
2438 - }
2439 -
2440 - $('#upk-custom-code-message').html(
2441 - '<div class="bdt-alert bdt-alert-success" bdt-alert>' +
2442 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2443 - '<p>' + successMessage + '</p>' +
2444 - '</div>'
2445 - ).show();
2446 -
2447 - // Auto-hide message after 5 seconds
2448 - setTimeout(function() {
2449 - $('#upk-custom-code-message').fadeOut();
2450 - }, 5000);
2451 -
2452 - } else {
2453 - // Show error message
2454 - var errorMessage = 'Unknown error occurred';
2455 - if (response && response.data && response.data.message) {
2456 - errorMessage = response.data.message;
2457 - } else if (response && response.message) {
2458 - errorMessage = response.message;
2459 - }
2460 -
2461 - $('#upk-custom-code-message').html(
2462 - '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2463 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2464 - '<p>Error: ' + errorMessage + '</p>' +
2465 - '</div>'
2466 - ).show();
2467 - }
2468 - })
2469 - .fail(function(xhr, status, error) {
2470 - console.log('AJAX Error:', xhr, status, error); // Debug log
2471 -
2472 - // Try to parse error response
2473 - var errorMessage = 'Failed to save custom code. Please try again.';
2474 - try {
2475 - var errorResponse = JSON.parse(xhr.responseText);
2476 - if (errorResponse.data && errorResponse.data.message) {
2477 - errorMessage = errorResponse.data.message;
2478 - } else if (errorResponse.message) {
2479 - errorMessage = errorResponse.message;
2480 - }
2481 - } catch (e) {
2482 - // Use default error message
2483 - }
2484 -
2485 - // Show error message
2486 - $('#upk-custom-code-message').html(
2487 - '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2488 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2489 - '<p>Error: ' + errorMessage + ' (' + status + ')</p>' +
2490 - '</div>'
2491 - ).show();
2492 - })
2493 - .always(function() {
2494 -
2495 - // Clear the timeout since AJAX completed
2496 - clearTimeout(timeoutId);
2497 -
2498 - try {
2499 - $button.removeClass('upk-saving');
2500 - $button.html(originalText);
2501 - $button.prop('disabled', false);
2502 - } catch (e) {
2503 - // Fallback: force button restoration
2504 - $('#upk-save-custom-code').removeClass('upk-saving').html('<span class="dashicons dashicons-yes"></span> Save Custom Code').prop('disabled', false);
2505 - }
2506 - });
2507 - });
2508 -
2509 - // Reset custom code functionality (updated for CodeMirror)
2510 - $('#upk-reset-custom-code').on('click', function(e) {
2511 - e.preventDefault();
2512 -
2513 - if (confirm('Are you sure you want to reset all custom code? This will clear all code.')) {
2514 - var $button = $(this);
2515 - var originalText = $button.html();
2516 -
2517 - // Clear CodeMirror editors
2518 - function clearCodeMirrorEditor(elementId) {
2519 - if (codeMirrorEditors[elementId] && codeMirrorEditors[elementId].codemirror) {
2520 - codeMirrorEditors[elementId].codemirror.setValue('');
2521 - } else {
2522 - // Fallback to clearing textarea
2523 - $('#' + elementId).val('');
2524 - }
2525 - }
2526 -
2527 - // Clear all editors
2528 - clearCodeMirrorEditor('upk-custom-css');
2529 - clearCodeMirrorEditor('upk-custom-js');
2530 - clearCodeMirrorEditor('upk-custom-css-2');
2531 - clearCodeMirrorEditor('upk-custom-js-2');
2532 -
2533 - // Clear exclusions
2534 - $('#upk-excluded-pages').val([]).trigger('change');
2535 -
2536 - // Show clearing message
2537 - $('#upk-custom-code-message').html(
2538 - '<div class="bdt-alert bdt-alert-primary" bdt-alert>' +
2539 - '<p><span bdt-spinner="ratio: 0.6"></span> Clearing custom code...</p>' +
2540 - '</div>'
2541 - ).show();
2542 -
2543 - // Disable button during save
2544 - $button.prop('disabled', true).html('<span bdt-spinner="ratio: 0.6"></span> Resetting...');
2545 -
2546 - // Prepare empty data for AJAX save
2547 - var formData = {
2548 - action: 'upk_save_custom_code',
2549 - nonce: upk_admin_ajax.nonce,
2550 - custom_css: '',
2551 - custom_js: '',
2552 - custom_css_2: '',
2553 - custom_js_2: '',
2554 - excluded_pages: []
2555 - };
2556 -
2557 - // Send AJAX request to save empty values
2558 - $.ajax({
2559 - url: upk_admin_ajax.ajax_url,
2560 - type: 'POST',
2561 - data: formData,
2562 - timeout: 30000,
2563 - success: function(response) {
2564 - if (response.success) {
2565 - // Show success message
2566 - $('#upk-custom-code-message').html(
2567 - '<div class="bdt-alert bdt-alert-success" bdt-alert>' +
2568 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2569 - '<p><span class="dashicons dashicons-yes"></span> All custom code has been reset successfully!</p>' +
2570 - '</div>'
2571 - ).show();
2572 -
2573 - // Auto-hide message after 5 seconds
2574 - setTimeout(function() {
2575 - $('#upk-custom-code-message').fadeOut();
2576 - }, 5000);
2577 - } else {
2578 - // Show error message
2579 - $('#upk-custom-code-message').html(
2580 - '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2581 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2582 - '<p><span class="dashicons dashicons-warning"></span> ' + (response.data.message || 'Failed to save reset. Please try again.') + '</p>' +
2583 - '</div>'
2584 - ).show();
2585 - }
2586 -
2587 - // Restore button
2588 - $button.prop('disabled', false).html(originalText);
2589 - },
2590 - error: function(xhr, status, error) {
2591 - // Show error message
2592 - $('#upk-custom-code-message').html(
2593 - '<div class="bdt-alert bdt-alert-danger" bdt-alert>' +
2594 - '<a href="#" class="bdt-alert-close" onclick="$(this).parent().parent().hide(); return false;">&times;</a>' +
2595 - '<p><span class="dashicons dashicons-warning"></span> Failed to save reset: ' + error + '</p>' +
2596 - '</div>'
2597 - ).show();
2598 -
2599 - // Restore button
2600 - $button.prop('disabled', false).html(originalText);
2601 - }
2602 - });
2603 - }
2604 - });
2605 1469 });
2606 1470
2607 1471 // Chart.js initialization for system status canvas charts
2608 1472 function initUltimatePostKitCharts() {
@@ -2761,9 +1625,9 @@
2761 1625 .addClass('bdt-installing');
2762 1626
2763 1627 // Perform AJAX request
2764 1628 jQuery.ajax({
2765 - url: '<?php echo admin_url('admin-ajax.php'); ?>',
1629 + url: '<?php echo esc_url(admin_url('admin-ajax.php')); ?>',
2766 1630 type: 'POST',
2767 1631 data: {
2768 1632 action: 'upk_install_plugin',
2769 1633 plugin_slug: pluginSlug,
@@ -2820,101 +1684,11 @@
2820 1684 }
2821 1685 });
2822 1686 });
2823 1687
2824 - // Show/hide white label & custom code save button based on active tab
2825 - function toggleWhiteLabelSaveButton() {
2826 -
2827 - // Check if we're on the extra options page
2828 - if (window.location.hash === '#ultimate_post_kit_extra_options') {
2829 - // Target specifically the tabs within the Extra Options section
2830 - var extraOptionsTabs = jQuery('.upk-extra-options-tabs .bdt-tab li.bdt-active');
2831 - var activeTab = extraOptionsTabs.index();
2832 -
2833 - if (activeTab === 1) { // White Label tab is the second tab (index 1)
2834 - jQuery('.upk-white-label-save-section').show();
2835 - jQuery('.upk-code-save-section').hide();
2836 - } else {
2837 - jQuery('.upk-white-label-save-section').hide();
2838 - jQuery('.upk-code-save-section').show();
2839 - }
2840 - } else {
2841 - jQuery('.upk-white-label-save-section').hide();
2842 - jQuery('.upk-code-save-section').hide();
2843 - }
2844 - }
2845 -
2846 - // Wait for jQuery to be ready
2847 - jQuery(document).ready(function($) {
2848 -
2849 - // Check if we should automatically switch to White Label tab
2850 - var urlParams = new URLSearchParams(window.location.search);
2851 - if (urlParams.get('white_label_tab') === '1') {
2852 - // Wait a bit for UIkit to be ready, then switch to White Label tab
2853 - setTimeout(function() {
2854 - // Use UIkit's API to switch to the second tab (index 1)
2855 - var tabElement = document.querySelector('.upk-extra-options-tabs [bdt-tab]');
2856 - if (tabElement && typeof UIkit !== 'undefined') {
2857 - UIkit.tab(tabElement).show(1); // Show tab at index 1 (White Label tab)
2858 - } else {
2859 - // Fallback: simply click the White Label tab link
2860 - var whiteLabelTab = $('.upk-extra-options-tabs .bdt-tab li').eq(1);
2861 - if (whiteLabelTab.length > 0) {
2862 - whiteLabelTab.find('a')[0].click(); // Use native click
2863 - }
2864 - }
2865 -
2866 - // Check button visibility after tab switch
2867 - setTimeout(function() {
2868 - toggleWhiteLabelSaveButton();
2869 - }, 300);
2870 - }, 800);
2871 - } else {
2872 - toggleWhiteLabelSaveButton();
2873 - }
2874 -
2875 - // Check on hash change (when navigating to extra options page)
2876 - $(window).on('hashchange', function() {
2877 - toggleWhiteLabelSaveButton();
2878 - });
2879 -
2880 - // Listen for UIkit tab changes using multiple methods
2881 - $(document).on('click', '.bdt-tab li a', function() {
2882 - setTimeout(function() {
2883 - toggleWhiteLabelSaveButton();
2884 - }, 200);
2885 - });
2886 -
2887 - // Listen for UIkit's internal tab change events
2888 - $(document).on('shown', '[bdt-tab]', function() {
2889 - setTimeout(function() {
2890 - toggleWhiteLabelSaveButton();
2891 - }, 200);
2892 - });
2893 -
2894 - // Also listen for the specific tab content changes
2895 - $(document).on('show', '#upk-extra-options-tab-content > div', function() {
2896 - setTimeout(function() {
2897 - toggleWhiteLabelSaveButton();
2898 - }, 200);
2899 - });
2900 -
2901 - // Alternative: Check periodically for tab changes
2902 - setInterval(function() {
2903 - if (window.location.hash === '#ultimate_post_kit_extra_options') {
2904 - var currentActiveTab = $('.bdt-tab li.bdt-active').index();
2905 - if (typeof window.lastActiveTab === 'undefined') {
2906 - window.lastActiveTab = currentActiveTab;
2907 - } else if (window.lastActiveTab !== currentActiveTab) {
2908 - window.lastActiveTab = currentActiveTab;
2909 - toggleWhiteLabelSaveButton();
2910 - }
2911 - }
2912 - }, 500);
2913 - });
2914 1688
2915 1689 </script>
2916 - <?php
1690 + <?php
2917 1691 }
2918 1692
2919 1693 /**
2920 1694 * Display Footer
@@ -2937,10 +1711,22 @@
2937 1711 </div>
2938 1712
2939 1713 <div class="bdt-width-expand@s bdt-text-right">
2940 1714 <p class="">
2941 - Ultimate Post Kit Pro plugin made with love by <a target="_blank" href="https://bdthemes.com">BdThemes</a> Team.
2942 - <br>All rights reserved by <a target="_blank" href="https://bdthemes.com">BdThemes.com</a>.
1715 + <?php
1716 + printf(
1717 + /* translators: %s: link to the BdThemes website. */
1718 + esc_html__('Ultimate Post Kit Pro plugin made with love by %s Team.', 'ultimate-post-kit'),
1719 + '<a target="_blank" href="' . esc_url('https://bdthemes.com') . '">BdThemes</a>'
1720 + );
1721 + ?>
1722 + <br><?php
1723 + printf(
1724 + /* translators: %s: link to the BdThemes website. */
1725 + esc_html__('All rights reserved by %s.', 'ultimate-post-kit'),
1726 + '<a target="_blank" href="' . esc_url('https://bdthemes.com') . '">BdThemes.com</a>'
1727 + );
1728 + ?>
2943 1729 </p>
2944 1730 </div>
2945 1731 </div>
2946 1732
@@ -2965,376 +1751,9 @@
2965 1751
2966 1752 return $pages_options;
2967 1753 }
2968 1754
2969 - /**
2970 - * Check if current license supports white label features
2971 - * Now includes other_param checking for AppSumo WL flag
2972 - *
2973 - * @access public static
2974 - * @return bool
2975 - */
2976 - public static function is_white_label_license() {
2977 - // Check if pro version is activated first
2978 - if (!function_exists('_is_upk_pro_activated') || !_is_upk_pro_activated()) {
2979 - return false;
2980 - }
2981 -
2982 - // Since UltimatePostKitPro\Base doesn't exist, return false for now
2983 - // This should be replaced with actual pro license checking logic when available
2984 - $license_info = UltimatePostKitPro\Base\Ultimate_Post_Kit_Base::GetRegisterInfo();
2985 -
2986 - // Security: Validate license info structure
2987 - if (empty($license_info) ||
2988 - !is_object($license_info) ||
2989 - empty($license_info->license_title) ||
2990 - empty($license_info->is_valid)) {
2991 - return false;
2992 - }
2993 -
2994 - // Sanitize license title to prevent any potential issues
2995 - $license_title = sanitize_text_field(strtolower($license_info->license_title));
2996 -
2997 - // Check for other_param WL flag FIRST (for AppSumo and other special licenses)
2998 - if (!empty($license_info->other_param)) {
2999 - // Check if other_param contains WL flag
3000 - if (is_array($license_info->other_param)) {
3001 - if (in_array('WL', $license_info->other_param, true)) {
3002 - return true;
3003 - }
3004 - } elseif (is_string($license_info->other_param)) {
3005 - if (strpos($license_info->other_param, 'WL') !== false) {
3006 - return true;
3007 - }
3008 - }
3009 - }
3010 -
3011 - // Check standard license types (but NOT AppSumo - AppSumo requires WL flag)
3012 - $allowed_types = self::get_white_label_allowed_license_types();
3013 - $allowed_hashes = array_values($allowed_types);
3014 -
3015 - // Split license title into words and check each word
3016 - $words = preg_split('/\s+/', $license_title, -1, PREG_SPLIT_NO_EMPTY);
3017 - foreach ($words as $word) {
3018 - $word = trim($word);
3019 - if (empty($word) || strlen($word) > 50) { // Prevent extremely long strings
3020 - continue;
3021 - }
3022 -
3023 - // Use SHA-256 for enhanced security
3024 - $hash = hash('sha256', $word);
3025 - if (in_array($hash, $allowed_hashes, true)) { // Strict comparison
3026 - return true;
3027 - }
3028 - }
3029 -
3030 - return false;
3031 - }
3032 1755
3033 - /**
3034 - * Render White Label Section
3035 - *
3036 - * @access public
3037 - * @return void
3038 - */
3039 - public function render_white_label_section() {
3040 - //// Safely check if helper functions exist
3041 - $is_pro_installed = function_exists('_is_upk_pro_installed') ? _is_upk_pro_installed() : false;
3042 - $is_pro_activated = function_exists('_is_upk_pro_activated') ? _is_upk_pro_activated() : false;
3043 -
3044 - // Define plugin slug (adjust if needed)
3045 - $plugin_slug = 'ultimate-post-kit-pro/ultimate-post-kit-pro.php';
3046 -
3047 - // Case 1: Pro not installed
3048 - if ( ! $is_pro_installed ) : ?>
3049 - <div class="bdt-alert bdt-alert-danger bdt-margin-medium-top" bdt-alert>
3050 - <p><?php esc_html_e( 'Ultimate Post Kit Pro is not installed. Please install it to access White Label functionality.', 'ultimate-post-kit' ); ?></p>
3051 - <div class="bdt-margin-small-top">
3052 - <a href="https://postkit.pro/pricing/" target="_blank" class="bdt-button bdt-btn-blue">
3053 - <?php esc_html_e( 'Get Pro', 'ultimate-post-kit' ); ?>
3054 - </a>
3055 - </div>
3056 - </div>
3057 - <?php
3058 - return;
3059 - endif;
3060 -
3061 - // Case 2: Installed but not active
3062 - if ( $is_pro_installed && ! $is_pro_activated ) :
3063 - // Generate secure activation link
3064 - $activate_url = wp_nonce_url(
3065 - add_query_arg(
3066 - array(
3067 - 'action' => 'activate',
3068 - 'plugin' => $plugin_slug,
3069 - ),
3070 - admin_url( 'plugins.php' )
3071 - ),
3072 - 'activate-plugin_' . $plugin_slug
3073 - );
3074 - ?>
3075 - <div class="bdt-alert bdt-alert-warning bdt-margin-medium-top" bdt-alert>
3076 - <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>
3077 - <div class="bdt-margin-small-top">
3078 - <a href="<?php echo esc_url( $activate_url ); ?>" class="bdt-button bdt-btn-blue">
3079 - <?php esc_html_e( 'Activate Pro', 'ultimate-post-kit' ); ?>
3080 - </a>
3081 - </div>
3082 - </div>
3083 - <?php
3084 - return;
3085 - endif;
3086 - ?>
3087 - <div class="upk-white-label-section">
3088 - <h1 class="upk-feature-title"><?php esc_html_e('White Label Settings', 'ultimate-post-kit'); ?></h1>
3089 - <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>
3090 -
3091 - <?php
3092 -
3093 - $is_license_active = false;
3094 - if ( function_exists( 'upk_license_validation' ) && true === upk_license_validation() ) {
3095 - $is_license_active = true;
3096 - }
3097 - $is_white_label_eligible = self::is_white_label_license();
3098 -
3099 - // Show appropriate notices based on license status
3100 - if (!$is_license_active): ?>
3101 - <div class="bdt-alert bdt-alert-danger bdt-margin-medium-top" bdt-alert>
3102 - <p><strong><?php esc_html_e('License Not Activated', 'ultimate-post-kit'); ?></strong></p>
3103 - <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>
3104 - <div class="bdt-margin-small-top">
3105 - <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">
3106 - <?php esc_html_e('Activate License', 'ultimate-post-kit'); ?>
3107 - </a>
3108 - <a href="https://postkit.pro/pricing/" target="_blank" class="bdt-button bdt-btn-blue">
3109 - <?php esc_html_e('Get License', 'ultimate-post-kit'); ?>
3110 - </a>
3111 - </div>
3112 - </div>
3113 - <?php elseif ($is_license_active && !$is_white_label_eligible): ?>
3114 - <div class="bdt-alert bdt-alert-warning bdt-margin-medium-top" bdt-alert>
3115 - <p><strong><?php esc_html_e('Eligible License Required', 'ultimate-post-kit'); ?></strong></p>
3116 - <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>
3117 - <a href="https://postkit.pro/pricing/" target="_blank" class="bdt-button bdt-btn-blue bdt-margin-small-top">
3118 - <?php esc_html_e('Upgrade License', 'ultimate-post-kit'); ?>
3119 - </a>
3120 - </div>
3121 - <?php endif; ?>
3122 -
3123 - <div class="upk-white-label-options <?php echo (!$is_license_active || !$is_white_label_eligible) ? 'upk-white-label-locked' : ''; ?>">
3124 - <div class="upk-option-item ">
3125 - <div class="upk-option-item-inner bdt-card">
3126 - <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3127 - <div>
3128 - <h3 class="upk-option-title"><?php esc_html_e('Enable White Label Mode', 'ultimate-post-kit'); ?></h3>
3129 - <p class="upk-option-description">
3130 - <?php if ($is_license_active && $is_white_label_eligible): ?>
3131 - <?php esc_html_e('When enabled, Ultimate Post Kit branding will be hidden from the admin interface and widgets.', 'ultimate-post-kit'); ?>
3132 - <?php elseif (!$is_license_active): ?>
3133 - <?php esc_html_e('This feature requires an active Ultimate Post Kit license. Please activate your license first.', 'ultimate-post-kit'); ?>
3134 - <?php else: ?>
3135 - <?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'); ?>
3136 - <?php endif; ?>
3137 - </p>
3138 - </div>
3139 - <div class="upk-option-switch">
3140 - <?php
3141 - $white_label_enabled = ($is_license_active && $is_white_label_eligible) ? get_option('upk_white_label_enabled', false) : false;
3142 - // Convert to boolean to ensure proper comparison
3143 - $white_label_enabled = (bool) $white_label_enabled;
3144 - ?>
3145 - <label class="switch">
3146 - <input type="checkbox"
3147 - id="upk-white-label-enabled"
3148 - name="upk_white_label_enabled"
3149 - <?php checked($white_label_enabled, true); ?>
3150 - <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3151 - <span class="slider"></span>
3152 - </label>
3153 - </div>
3154 - </div>
3155 - </div>
3156 - </div>
3157 -
3158 - <!-- White Label Title Field (conditional) -->
3159 - <div class="upk-option-item upk-white-label-fields" style="<?php echo ($white_label_enabled && $is_license_active && $is_white_label_eligible) ? '' : 'display: none;'; ?>">
3160 - <div class="upk-option-item-inner bdt-card">
3161 - <div class="upk-white-label-title-section bdt-margin-medium-bottom">
3162 - <h3 class="upk-option-title"><?php esc_html_e('White Label Title', 'ultimate-post-kit'); ?></h3>
3163 - <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>
3164 - <div class="upk-white-label-input-wrapper bdt-margin-small-top">
3165 - <input type="text"
3166 - id="upk-white-label-title"
3167 - name="upk_white_label_title"
3168 - class="upk-white-label-input"
3169 - placeholder="<?php esc_attr_e('Enter your custom title...', 'ultimate-post-kit'); ?>"
3170 - value="<?php echo esc_attr(get_option('upk_white_label_title', '')); ?>"
3171 - <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3172 - </div>
3173 - </div>
3174 -
3175 - <hr class="bdt-divider-small">
3176 -
3177 - <!-- White Label Title Icon Field -->
3178 - <div class="upk-white-label-icon-section bdt-margin-medium-top">
3179 - <h3 class="upk-option-title"><?php esc_html_e('White Label Title Icon', 'ultimate-post-kit'); ?></h3>
3180 - <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>
3181 -
3182 - <div class="upk-icon-upload-wrapper bdt-margin-small-top">
3183 - <?php
3184 - $icon_url = get_option('upk_white_label_icon', '');
3185 - $icon_id = get_option('upk_white_label_icon_id', '');
3186 - ?>
3187 - <div class="upk-icon-preview-container" style="<?php echo $icon_url ? '' : 'display: none;'; ?>">
3188 - <div class="upk-icon-preview">
3189 - <img id="upk-icon-preview-img" src="<?php echo esc_url($icon_url); ?>" alt="Icon Preview" style="max-width: 64px; max-height: 64px; border: 1px solid #ddd; border-radius: 4px; padding: 8px; background: #fff;">
3190 - </div>
3191 - <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;">
3192 - <span class="dashicons dashicons-trash"></span>
3193 - <?php esc_html_e('Remove', 'ultimate-post-kit'); ?>
3194 - </button>
3195 - </div>
3196 -
3197 - <div class="upk-icon-upload-container">
3198 - <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); ?>>
3199 - <span class="dashicons dashicons-cloud-upload"></span>
3200 - <?php esc_html_e('Upload Icon', 'ultimate-post-kit'); ?>
3201 - </button>
3202 - <input type="hidden" id="upk-white-label-icon" name="upk_white_label_icon" value="<?php echo esc_attr($icon_url); ?>">
3203 - <input type="hidden" id="upk-white-label-icon-id" name="upk_white_label_icon_id" value="<?php echo esc_attr($icon_id); ?>">
3204 - </div>
3205 - </div>
3206 -
3207 - <p class="upk-input-help">
3208 - <?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'); ?>
3209 - </p>
3210 - </div>
3211 -
3212 - <!-- White Label Plugin Logo Field -->
3213 - <div class="upk-white-label-logo-section bdt-margin-medium-top">
3214 - <h3 class="upk-option-title"><?php esc_html_e('Plugin Logo', 'ultimate-post-kit'); ?></h3>
3215 - <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>
3216 - <div class="upk-logo-upload-wrapper-inner">
3217 - <div class="upk-logo-upload-wrapper bdt-margin-small-top">
3218 - <?php
3219 - $logo_url = get_option('upk_white_label_logo', '');
3220 - $logo_id = get_option('upk_white_label_logo_id', '');
3221 - ?>
3222 - <div class="upk-logo-preview-container" style="<?php echo $logo_url ? '' : 'display: none;'; ?>">
3223 - <div class="upk-logo-preview">
3224 - <img id="upk-logo-preview-img" src="<?php echo esc_url($logo_url); ?>" alt="Logo Preview" style="max-width: 200px; max-height: 64px; border: 1px solid #ddd; border-radius: 4px; padding: 8px; background: #fff;">
3225 - </div>
3226 - <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;">
3227 - <span class="dashicons dashicons-trash"></span>
3228 - </button>
3229 - </div>
3230 -
3231 - <div class="upk-logo-upload-container">
3232 - <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); ?>>
3233 - <span class="dashicons dashicons-cloud-upload"></span>
3234 - <?php esc_html_e('Upload Logo', 'ultimate-post-kit'); ?>
3235 - </button>
3236 - <input type="hidden" id="upk-white-label-logo" name="upk_white_label_logo" value="<?php echo esc_attr($logo_url); ?>">
3237 - <input type="hidden" id="upk-white-label-logo-id" name="upk_white_label_logo_id" value="<?php echo esc_attr($logo_id); ?>">
3238 - </div>
3239 - </div>
3240 - <p class="upk-input-help">
3241 - <?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'); ?>
3242 - </p>
3243 - </div>
3244 - </div>
3245 - </div>
3246 - </div>
3247 -
3248 - <!-- License Hide Option (conditional) -->
3249 - <div class="upk-option-item upk-white-label-fields" style="<?php echo ($white_label_enabled && $is_license_active && $is_white_label_eligible) ? '' : 'display: none;'; ?>">
3250 - <div class="upk-option-item-inner bdt-card">
3251 - <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3252 - <div>
3253 - <h3 class="upk-option-title"><?php esc_html_e('Hide License Menu', 'ultimate-post-kit'); ?></h3>
3254 - <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>
3255 - </div>
3256 - <div class="upk-option-switch">
3257 - <?php
3258 - $hide_license = get_option('upk_white_label_hide_license', false);
3259 - // Convert to boolean to ensure proper comparison
3260 - $hide_license = (bool) $hide_license;
3261 - ?>
3262 - <label class="switch">
3263 - <input type="checkbox"
3264 - id="upk-white-label-hide-license"
3265 - name="upk_white_label_hide_license"
3266 - <?php checked($hide_license, true); ?>
3267 - <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3268 - <span class="slider"></span>
3269 - </label>
3270 - </div>
3271 - </div>
3272 - </div>
3273 - </div>
3274 -
3275 - <!-- BDTUPK_HIDE Option (conditional) -->
3276 - <div class="upk-option-item upk-white-label-fields" style="<?php echo ($white_label_enabled && $is_license_active && $is_white_label_eligible) ? '' : 'display: none;'; ?>">
3277 - <div class="upk-option-item-inner bdt-card">
3278 - <div class="bdt-flex bdt-flex-between bdt-flex-middle">
3279 - <div>
3280 - <h3 class="upk-option-title"><?php esc_html_e('Enable BDTUPK_HIDE Constant', 'ultimate-post-kit'); ?></h3>
3281 - <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>
3282 - <?php
3283 - $bdtupk_hide = get_option('upk_white_label_bdtupk_hide', false);
3284 - if ($bdtupk_hide): ?>
3285 - <div class="bdt-alert bdt-alert-warning bdt-margin-small-top">
3286 - <p><strong>⚠️ BDTUPK_HIDE Currently Active</strong></p>
3287 - <p>Advanced white label mode is currently enabled. Ultimate Post Kit menus are hidden from the admin interface.</p>
3288 - </div>
3289 - <?php endif; ?>
3290 - </div>
3291 - <div class="upk-option-switch">
3292 - <?php
3293 - // Convert to boolean to ensure proper comparison
3294 - $bdtupk_hide = (bool) $bdtupk_hide;
3295 - ?>
3296 - <label class="switch">
3297 - <input type="checkbox"
3298 - id="upk-white-label-bdtupk-hide"
3299 - name="upk_white_label_bdtupk_hide"
3300 - <?php checked($bdtupk_hide, true); ?>
3301 - <?php disabled(!$is_license_active || !$is_white_label_eligible); ?>>
3302 - <span class="slider"></span>
3303 - </label>
3304 - </div>
3305 - </div>
3306 - </div>
3307 - </div>
3308 -
3309 - <?php if (!$bdtupk_hide && $is_license_active && $is_white_label_eligible): ?>
3310 - <div class="bdt-margin-small-top">
3311 - <div class="bdt-alert bdt-alert-danger">
3312 - <h4>📧 Email Access System</h4>
3313 - <p>When you enable BDTUPK_HIDE, an email will be automatically sent to:</p>
3314 - <ul style="margin: 10px 0;">
3315 - <li><strong>License Email:</strong> <?php echo esc_html(self::get_license_email()); ?></li>
3316 - <?php if (get_bloginfo('admin_email') !== self::get_license_email()): ?>
3317 - <li><strong>Admin Email:</strong> <?php echo esc_html(get_bloginfo('admin_email')); ?></li>
3318 - <?php endif; ?>
3319 - </ul>
3320 - <p>This email will contain a special access link that allows you to return to these settings even when BDTUPK_HIDE is active.</p>
3321 - </div>
3322 - </div>
3323 - <?php endif; ?>
3324 -
3325 - <!-- Success/Error Messages -->
3326 - <div id="upk-white-label-message" class="upk-white-label-message bdt-margin-small-top" style="display: none;">
3327 - <div class="bdt-alert bdt-alert-success" bdt-alert>
3328 - <a href class="bdt-alert-close" bdt-close></a>
3329 - <p><?php esc_html_e('White label settings saved successfully!', 'ultimate-post-kit'); ?></p>
3330 - </div>
3331 - </div>
3332 - </div>
3333 - </div>
3334 - <?php
3335 - }
3336 -
3337 1756 public static function license_wl_status() {
3338 1757 $status = get_option('ultimate_post_kit_license_title_status');
3339 1758
3340 1759 if ($status) {
@@ -3377,8 +1796,19 @@
3377 1796 </div>
3378 1797 <?php
3379 1798 }
3380 1799
1800 + /**
1801 + * Others Plugin - Using standalone plugin manager
1802 + */
1803 + public function ultimate_post_kit_others_plugin() {
1804 + // Include and render the standalone others plugin manager
1805 + require_once BDTUPK_INC_PATH . 'setup-wizard/ultimate-post-kit-others-plugin.php';
1806 +
1807 + // Call the helper function to render the plugin manager
1808 + ultimate_post_kit_others_plugin();
1809 + }
1810 +
3381 1811 /**
3382 1812 * Widgets Status
3383 1813 */
3384 1814
@@ -3418,10 +1848,12 @@
3418 1848 </div>
3419 1849
3420 1850 <div class="upk-canvas-wrap">
3421 1851 <canvas id="bdt-db-total-status" style="height: 100px; width: 100px;"
3422 - data-label="Total Widgets Status - (<?php echo esc_html($used_widgets + $un_used_widgets); ?>)"
3423 - data-labels="<?php echo esc_attr('Used, Unused'); ?>"
1852 + data-label="<?php
1853 + /* translators: %s: Total number of widgets */
1854 + echo esc_attr( sprintf( __( 'Total Widgets Status - (%s)', 'ultimate-post-kit' ), $used_widgets + $un_used_widgets ) ); ?>"
1855 + data-labels="<?php echo esc_attr( sprintf( '%1$s, %2$s', __( 'Used', 'ultimate-post-kit' ), __( 'Unused', 'ultimate-post-kit' ) ) ); ?>"
3424 1856 data-value="<?php echo esc_attr($used_widgets) . ',' . esc_attr($un_used_widgets); ?>"
3425 1857 data-bg="#FFD166, #fff4d9" data-bg-hover="#0673e1, #e71522"></canvas>
3426 1858 </div>
3427 1859 </div>
@@ -3456,10 +1888,12 @@
3456 1888 </div>
3457 1889
3458 1890 <div class="upk-canvas-wrap">
3459 1891 <canvas id="bdt-db-only-widget-status" style="height: 100px; width: 100px;"
3460 - data-label="Core Widgets Status - (<?php echo esc_html($used_only_widgets + $unused_only_widgets); ?>)"
3461 - data-labels="<?php echo esc_attr('Used, Unused'); ?>"
1892 + data-label="<?php
1893 + /* translators: %s: Total number of core widgets */
1894 + echo esc_attr( sprintf( __( 'Core Widgets Status - (%s)', 'ultimate-post-kit' ), $used_only_widgets + $unused_only_widgets ) ); ?>"
1895 + data-labels="<?php echo esc_attr( sprintf( '%1$s, %2$s', __( 'Used', 'ultimate-post-kit' ), __( 'Unused', 'ultimate-post-kit' ) ) ); ?>"
3462 1896 data-value="<?php echo esc_attr($used_only_widgets) . ',' . esc_attr($unused_only_widgets); ?>"
3463 1897 data-bg="#EF476F, #ffcdd9" data-bg-hover="#0673e1, #e71522"></canvas>
3464 1898 </div>
3465 1899 </div>
@@ -3486,10 +1920,10 @@
3486 1920 </div>
3487 1921
3488 1922 <div class="upk-canvas-wrap">
3489 1923 <canvas id="bdt-total-widgets-status" style="height: 100px; width: 100px;"
3490 - data-label="Total Active Widgets Status"
3491 - data-labels="<?php echo esc_attr('Core, Extensions'); ?>"
1924 + data-label="<?php echo esc_attr__( 'Total Active Widgets Status', 'ultimate-post-kit' ); ?>"
1925 + data-labels="<?php echo esc_attr( sprintf( '%1$s, %2$s', __( 'Core', 'ultimate-post-kit' ), __( 'Extensions', 'ultimate-post-kit' ) ) ); ?>"
3492 1926 data-value="0,0,0"
3493 1927 data-bg="#0680d6, #B0EBFF" data-bg-hover="#0673e1, #B0EBFF">
3494 1928 </canvas>
3495 1929 </div>
@@ -3506,8 +1940,9 @@
3506 1940 <a href class="bdt-alert-close" bdt-close></a>
3507 1941 <div class="bdt-text-default">
3508 1942 <?php
3509 1943 printf(
1944 + /* translators: 1: opening bold tag, 2: closing bold tag */
3510 1945 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'),
3511 1946 '<b>', '</b>'
3512 1947 );
3513 1948
@@ -3563,12 +1998,12 @@
3563 1998 <span class="label1"><?php esc_html_e('Max execution time:', 'ultimate-post-kit'); ?> </span>
3564 1999 <?php
3565 2000 if ($max_execution_time < '90') {
3566 2001 echo wp_kses_post($no_icon);
3567 - echo '<span class="label2" title="Min: 90 Recommended" bdt-tooltip>Currently: ' . esc_html($max_execution_time) . '</span>';
2002 + 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>';
3568 2003 } else {
3569 2004 echo wp_kses_post($yes_icon);
3570 - echo '<span class="label2">Currently: ' . esc_html($max_execution_time) . '</span>';
2005 + echo '<span class="label2">' . esc_html__( 'Currently:', 'ultimate-post-kit' ) . ' ' . esc_html( $max_execution_time ) . '</span>';
3571 2006 }
3572 2007 ?>
3573 2008 </div>
3574 2009 </li>
@@ -3578,12 +2013,12 @@
3578 2013
3579 2014 <?php
3580 2015 if (intval($memory_limit) < '512') {
3581 2016 echo wp_kses_post($no_icon);
3582 - echo '<span class="label2" title="Min: 512M Recommended" bdt-tooltip>Currently: ' . esc_html($memory_limit) . '</span>';
2017 + 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>';
3583 2018 } else {
3584 2019 echo wp_kses_post($yes_icon);
3585 - echo '<span class="label2">Currently: ' . esc_html($memory_limit) . '</span>';
2020 + echo '<span class="label2">' . esc_html__( 'Currently:', 'ultimate-post-kit' ) . ' ' . esc_html( $memory_limit ) . '</span>';
3586 2021 }
3587 2022 ?>
3588 2023 </div>
3589 2024 </li>
@@ -3594,12 +2029,12 @@
3594 2029
3595 2030 <?php
3596 2031 if (intval($post_limit) < '32') {
3597 2032 echo wp_kses_post($no_icon);
3598 - echo '<span class="label2" title="Min: 32M Recommended" bdt-tooltip>Currently: ' . wp_kses_post($post_limit) . '</span>';
2033 + 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>';
3599 2034 } else {
3600 2035 echo wp_kses_post($yes_icon);
3601 - echo '<span class="label2">Currently: ' . wp_kses_post($post_limit) . '</span>';
2036 + echo '<span class="label2">' . esc_html__( 'Currently:', 'ultimate-post-kit' ) . ' ' . esc_html( $post_limit ) . '</span>';
3602 2037 }
3603 2038 ?>
3604 2039 </div>
3605 2040 </li>
@@ -3608,9 +2043,9 @@
3608 2043 <div>
3609 2044 <span class="label1"><?php esc_html_e('Uploads folder writable:', 'ultimate-post-kit'); ?></span>
3610 2045
3611 2046 <?php
3612 - if (!is_writable($upload_path)) {
2047 + if (!wp_is_writable($upload_path)) {
3613 2048 echo wp_kses_post($no_icon);
3614 2049 } else {
3615 2050 echo wp_kses_post($yes_icon);
3616 2051 }
@@ -3670,10 +2105,10 @@
3670 2105
3671 2106 <div class="bdt-admin-alert">
3672 2107 <strong><?php esc_html_e('Note:', 'ultimate-post-kit'); ?></strong>
3673 2108 <?php
3674 - /* translators: %s: Plugin name 'Ultimate Post Kit' */
3675 2109 printf(
2110 + /* translators: %s: Plugin name 'Ultimate Post Kit' */
3676 2111 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'),
3677 2112 '<b>Ultimate Post Kit</b>'
3678 2113 );
3679 2114 ?>
@@ -3682,249 +2117,8 @@
3682 2117 <?php
3683 2118 }
3684 2119
3685 2120 /**
3686 - * Others Plugin
3687 - */
3688 -
3689 - public function ultimate_post_kit_others_plugin() {
3690 - // Include the Plugin Integration Helper and API Fetcher
3691 - require_once BDTUPK_INC_PATH . 'setup-wizard/class-plugin-api-fetcher.php';
3692 - require_once BDTUPK_INC_PATH . 'setup-wizard/class-plugin-integration-helper.php';
3693 -
3694 - // Define plugin slugs to fetch data for (same as integration view)
3695 - $plugin_slugs = array(
3696 - 'bdthemes-element-pack-lite',
3697 - 'bdthemes-prime-slider-lite',
3698 - 'ultimate-store-kit',
3699 - 'zoloblocks',
3700 - 'pixel-gallery',
3701 - 'live-copy-paste',
3702 - 'spin-wheel',
3703 - 'ai-image',
3704 - 'dark-reader',
3705 - 'ar-viewer',
3706 - 'smart-admin-assistant',
3707 - 'website-accessibility',
3708 - );
3709 -
3710 - // Get plugin data using the helper (same as integration view)
3711 - $upk_plugins = \UltimatePostKit\SetupWizard\Plugin_Integration_Helper::build_plugin_data($plugin_slugs);
3712 -
3713 - // Helper function for time formatting (same as integration view)
3714 - if (!function_exists('format_last_updated')) {
3715 - function format_last_updated($date_string) {
3716 - if (empty($date_string)) {
3717 - return __('Unknown', 'ultimate-post-kit');
3718 - }
3719 -
3720 - $date = strtotime($date_string);
3721 - if (!$date) {
3722 - return __('Unknown', 'ultimate-post-kit');
3723 - }
3724 -
3725 - $diff = current_time('timestamp') - $date;
3726 -
3727 - if ($diff < 60) {
3728 - return __('Just now', 'ultimate-post-kit');
3729 - } elseif ($diff < 3600) {
3730 - $minutes = floor($diff / 60);
3731 - return sprintf(_n('%d minute ago', '%d minutes ago', $minutes, 'ultimate-post-kit'), $minutes);
3732 - } elseif ($diff < 86400) {
3733 - $hours = floor($diff / 3600);
3734 - return sprintf(_n('%d hour ago', '%d hours ago', $hours, 'ultimate-post-kit'), $hours);
3735 - } elseif ($diff < 2592000) { // 30 days
3736 - $days = floor($diff / 86400);
3737 - return sprintf(_n('%d day ago', '%d days ago', $days, 'ultimate-post-kit'), $days);
3738 - } elseif ($diff < 31536000) { // 1 year
3739 - $months = floor($diff / 2592000);
3740 - return sprintf(_n('%d month ago', '%d months ago', $months, 'ultimate-post-kit'), $months);
3741 - } else {
3742 - $years = floor($diff / 31536000);
3743 - return sprintf(_n('%d year ago', '%d years ago', $years, 'ultimate-post-kit'), $years);
3744 - }
3745 - }
3746 - }
3747 -
3748 - // Helper function for fallback URLs (same as integration view)
3749 - if (!function_exists('get_plugin_fallback_urls')) {
3750 - function get_plugin_fallback_urls($plugin_slug) {
3751 - // Handle different plugin slug formats
3752 - if (strpos($plugin_slug, '/') !== false) {
3753 - // If it's a file path like 'plugin-name/plugin-name.php', extract directory
3754 - $plugin_slug_clean = dirname($plugin_slug);
3755 - } else {
3756 - // If it's just the plugin directory name, use it directly
3757 - $plugin_slug_clean = $plugin_slug;
3758 - }
3759 -
3760 - // Custom icon URLs for specific plugins that might not be on WordPress.org
3761 - $custom_icons = [
3762 - 'bdthemes-element-pack-lite' => [
3763 - 'https://ps.w.org/bdthemes-element-pack-lite/assets/icon-256x256.png',
3764 - 'https://ps.w.org/bdthemes-element-pack-lite/assets/icon-128x128.png',
3765 - ],
3766 - 'live-copy-paste' => [
3767 - 'https://ps.w.org/live-copy-paste/assets/icon-256x256.png',
3768 - 'https://ps.w.org/live-copy-paste/assets/icon-128x128.png',
3769 - ],
3770 - 'spin-wheel' => [
3771 - 'https://ps.w.org/spin-wheel/assets/icon-256x256.png',
3772 - 'https://ps.w.org/spin-wheel/assets/icon-128x128.png',
3773 - ],
3774 - 'ai-image' => [
3775 - 'https://ps.w.org/ai-image/assets/icon-256x256.png',
3776 - 'https://ps.w.org/ai-image/assets/icon-128x128.png',
3777 - ],
3778 - 'smart-admin-assistant' => [
3779 - 'https://ps.w.org/smart-admin-assistant/assets/icon-256x256.png',
3780 - 'https://ps.w.org/smart-admin-assistant/assets/icon-128x128.png',
3781 - ],
3782 - 'website-accessibility' => [
3783 - 'https://ps.w.org/website-accessibility/assets/icon-256x256.png',
3784 - 'https://ps.w.org/website-accessibility/assets/icon-128x128.png',
3785 - ],
3786 - ];
3787 -
3788 - // Return custom icons if available, otherwise use default WordPress.org URLs
3789 - if (isset($custom_icons[$plugin_slug_clean])) {
3790 - return $custom_icons[$plugin_slug_clean];
3791 - }
3792 -
3793 - return [
3794 - "https://ps.w.org/{$plugin_slug_clean}/assets/icon-256x256.gif", // Try GIF first
3795 - "https://ps.w.org/{$plugin_slug_clean}/assets/icon-256x256.png", // Then PNG
3796 - "https://ps.w.org/{$plugin_slug_clean}/assets/icon-128x128.gif", // Medium GIF
3797 - "https://ps.w.org/{$plugin_slug_clean}/assets/icon-128x128.png", // Medium PNG
3798 - ];
3799 - }
3800 - }
3801 - ?>
3802 - <div class="upk-dashboard-panel"
3803 - bdt-scrollspy="target: > div > div > .bdt-card; cls: bdt-animation-slide-bottom-small; delay: 300">
3804 - <div class="upk-dashboard-others-plugin">
3805 -
3806 - <?php foreach ($upk_plugins as $plugin) :
3807 - $is_active = is_plugin_active($plugin['slug']);
3808 - // $is_recommended = $plugin['recommended'] && !$is_active;
3809 -
3810 - // Get plugin logo with fallback
3811 - $logo_url = $plugin['logo'] ?? '';
3812 - $plugin_name = $plugin['name'] ?? '';
3813 - $plugin_slug = $plugin['slug'] ?? '';
3814 -
3815 - if (empty($logo_url) || !filter_var($logo_url, FILTER_VALIDATE_URL)) {
3816 - // Generate fallback URLs for WordPress.org
3817 - $actual_slug = str_replace('.php', '', basename($plugin_slug));
3818 - $fallback_urls = get_plugin_fallback_urls($actual_slug);
3819 - $logo_url = $fallback_urls[0];
3820 - }
3821 - ?>
3822 -
3823 - <div class="bdt-card bdt-card-body bdt-flex bdt-flex-middle bdt-flex-between">
3824 - <div class="bdt-others-plugin-content bdt-flex bdt-flex-middle">
3825 - <div class="bdt-plugin-logo-wrap bdt-flex bdt-flex-middle">
3826 - <div class="bdt-plugin-logo-container">
3827 - <img src="<?php echo esc_url($logo_url); ?>"
3828 - alt="<?php echo esc_attr($plugin_name); ?>"
3829 - class="bdt-plugin-logo"
3830 - onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';">
3831 - <div class="default-plugin-icon" style="display:none;">📦</div>
3832 - </div>
3833 -
3834 - <div class="bdt-others-plugin-user-wrap bdt-flex bdt-flex-middle">
3835 - <h1 class="upk-feature-title"><?php echo esc_html($plugin_name); ?></h1>
3836 -
3837 - <!-- <?php //if ($is_active) : ?>
3838 - <span class="bdt-others-plugin-active"><?php //esc_html_e('ACTIVE', 'ultimate-post-kit'); ?></span>
3839 - <?php //endif; ?> -->
3840 -
3841 - </div>
3842 - </div>
3843 - <div class="bdt-others-plugin-content-text">
3844 -
3845 -
3846 -
3847 -
3848 -
3849 - <?php if (!empty($plugin['description'])) : ?>
3850 - <p><?php echo esc_html($plugin['description']); ?></p>
3851 - <?php endif; ?>
3852 -
3853 - <span class="active-installs bdt-margin-small-top">
3854 - <?php esc_html_e('Active Installs: ', 'ultimate-post-kit');
3855 - // echo wp_kses_post($plugin['active_installs'] ?? '0');
3856 - if (isset($plugin['active_installs_count']) && $plugin['active_installs_count'] > 0) {
3857 - echo ' <span class="installs-count">' . number_format($plugin['active_installs_count']) . '+' . '</span>';
3858 - } else {
3859 - echo ' <span class="installs-count">Fewer than 10' . '</span>';
3860 - }
3861 - ?>
3862 - </span>
3863 -
3864 - <?php if (isset($plugin['downloaded_formatted']) && !empty($plugin['downloaded_formatted'])): ?>
3865 - <div class="downloads bdt-margin-small-top">
3866 - <span><?php esc_html_e('Downloads: ', 'ultimate-post-kit'); ?><?php echo esc_html($plugin['downloaded_formatted']); ?></span>
3867 - </div>
3868 - <?php endif; ?>
3869 -
3870 - <div class="bdt-others-plugin-rating bdt-margin-small-top bdt-flex bdt-flex-middle">
3871 - <span class="bdt-others-plugin-rating-stars">
3872 - <?php
3873 - $rating = floatval($plugin['rating'] ?? 0);
3874 - $full_stars = floor($rating);
3875 - $has_half_star = ($rating - $full_stars) >= 0.5;
3876 - $empty_stars = 5 - $full_stars - ($has_half_star ? 1 : 0);
3877 -
3878 - // Full stars
3879 - for ($i = 0; $i < $full_stars; $i++) {
3880 - echo '<i class="dashicons dashicons-star-filled"></i>';
3881 - }
3882 -
3883 - // Half star
3884 - if ($has_half_star) {
3885 - echo '<i class="dashicons dashicons-star-half"></i>';
3886 - }
3887 -
3888 - // Empty stars
3889 - for ($i = 0; $i < $empty_stars; $i++) {
3890 - echo '<i class="dashicons dashicons-star-empty"></i>';
3891 - }
3892 - ?>
3893 - </span>
3894 - <span class="bdt-others-plugin-rating-text bdt-margin-small-left">
3895 - <?php echo esc_html($plugin['rating'] ?? '0'); ?> <?php esc_html_e('out of 5 stars.', 'ultimate-post-kit'); ?>
3896 - <?php if (isset($plugin['num_ratings']) && $plugin['num_ratings'] > 0): ?>
3897 - <span class="rating-count">(<?php echo number_format($plugin['num_ratings']); ?> <?php esc_html_e('ratings', 'ultimate-post-kit'); ?>)</span>
3898 - <?php endif; ?>
3899 - </span>
3900 - </div>
3901 -
3902 - <?php if (isset($plugin['last_updated']) && !empty($plugin['last_updated'])): ?>
3903 - <div class="bdt-others-plugin-updated bdt-margin-small-top">
3904 - <span><?php esc_html_e('Last Updated: ', 'ultimate-post-kit'); ?><?php echo esc_html(format_last_updated($plugin['last_updated'])); ?></span>
3905 - </div>
3906 - <?php endif; ?>
3907 - </div>
3908 - </div>
3909 -
3910 - <div class="bdt-others-plugins-link">
3911 - <?php echo $this->get_plugin_action_button($plugin['slug'], 'https://wordpress.org/plugins/' . dirname($plugin['slug']) . '/'); ?>
3912 - <?php if (!empty($plugin['homepage'])) : ?>
3913 - <a class="bdt-button bdt-dashboard-sec-btn" target="_blank" href="<?php echo esc_url($plugin['homepage']); ?>">
3914 - <?php esc_html_e('Learn More', 'ultimate-post-kit'); ?>
3915 - </a>
3916 - <?php endif; ?>
3917 - </div>
3918 - </div>
3919 -
3920 - <?php endforeach; ?>
3921 - </div>
3922 - </div>
3923 - <?php
3924 - }
3925 -
3926 - /**
3927 2121 * Check plugin status (installed, active, or not installed)
3928 2122 *
3929 2123 * @param string $plugin_path Plugin file path
3930 2124 * @return string 'active', 'installed', or 'not_installed'
@@ -3944,61 +2138,9 @@
3944 2138 // Plugin is not installed
3945 2139 return 'not_installed';
3946 2140 }
3947 2141
3948 - /**
3949 - * AJAX handler for saving custom code
3950 - *
3951 - * @access public
3952 - * @return void
3953 - */
3954 - public function save_custom_code_ajax() {
3955 - // Verify nonce
3956 - if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'upk_custom_code_nonce' ) ) {
3957 - wp_send_json_error( [ 'message' => 'Invalid security token.' ] );
3958 - }
3959 2142
3960 - // Check user capability
3961 - if ( ! current_user_can( 'manage_options' ) ) {
3962 - wp_send_json_error( [ 'message' => 'Insufficient permissions.' ] );
3963 - }
3964 -
3965 - // Sanitize and save the custom code
3966 - $custom_css = isset( $_POST['custom_css'] ) ? wp_unslash( $_POST['custom_css'] ) : '';
3967 - $custom_js = isset( $_POST['custom_js'] ) ? wp_unslash( $_POST['custom_js'] ) : '';
3968 - $custom_css_2 = isset( $_POST['custom_css_2'] ) ? wp_unslash( $_POST['custom_css_2'] ) : '';
3969 - $custom_js_2 = isset( $_POST['custom_js_2'] ) ? wp_unslash( $_POST['custom_js_2'] ) : '';
3970 -
3971 - // Handle excluded pages - ensure we get proper array format
3972 - $excluded_pages = array();
3973 - if ( isset( $_POST['excluded_pages'] ) ) {
3974 - if ( is_array( $_POST['excluded_pages'] ) ) {
3975 - $excluded_pages = $_POST['excluded_pages'];
3976 - } elseif ( is_string( $_POST['excluded_pages'] ) && ! empty( $_POST['excluded_pages'] ) ) {
3977 - // Handle case where it might be a single value
3978 - $excluded_pages = [ $_POST['excluded_pages'] ];
3979 - }
3980 - }
3981 -
3982 - // Sanitize excluded pages - convert to integers and remove empty values
3983 - $excluded_pages = array_map( 'intval', $excluded_pages );
3984 - $excluded_pages = array_filter( $excluded_pages, function( $page_id ) {
3985 - return $page_id > 0;
3986 - } );
3987 -
3988 - // Save to database
3989 - update_option( 'upk_custom_css', $custom_css );
3990 - update_option( 'upk_custom_js', $custom_js );
3991 - update_option( 'upk_custom_css_2', $custom_css_2 );
3992 - update_option( 'upk_custom_js_2', $custom_js_2 );
3993 - update_option( 'upk_excluded_pages', $excluded_pages );
3994 -
3995 - wp_send_json_success( [
3996 - 'message' => 'Custom code saved successfully!',
3997 - 'excluded_count' => count( $excluded_pages )
3998 - ] );
3999 - }
4000 -
4001 2143 /**
4002 2144 * Handle AJAX plugin installation
4003 2145 *
4004 2146 * @access public
@@ -4005,9 +2147,10 @@
4005 2147 * @return void
4006 2148 */
4007 2149 public function install_plugin_ajax() {
4008 2150 // Check nonce
4009 - if (!wp_verify_nonce($_POST['nonce'], 'upk_install_plugin_nonce')) {
2151 + $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
2152 + if (!wp_verify_nonce( $nonce, 'upk_install_plugin_nonce')) {
4010 2153 wp_send_json_error(['message' => __('Security check failed', 'ultimate-post-kit')]);
4011 2154 }
4012 2155
4013 2156 // Check user capability
@@ -4014,9 +2157,9 @@
4014 2157 if (!current_user_can('install_plugins')) {
4015 2158 wp_send_json_error(['message' => __('You do not have permission to install plugins', 'ultimate-post-kit')]);
4016 2159 }
4017 2160
4018 - $plugin_slug = sanitize_text_field($_POST['plugin_slug']);
2161 + $plugin_slug = isset($_POST['plugin_slug']) ? sanitize_text_field(wp_unslash($_POST['plugin_slug'])) : '';
4019 2162
4020 2163 if (empty($plugin_slug)) {
4021 2164 wp_send_json_error(['message' => __('Plugin slug is required', 'ultimate-post-kit')]);
4022 2165 }
@@ -4109,315 +2252,21 @@
4109 2252 __('Install', 'ultimate-post-kit') . '</a>';
4110 2253 }
4111 2254 }
4112 2255
4113 - /**
4114 - * Extra Options Start Here
4115 - */
4116 2256
4117 - /**
4118 - * Render Custom CSS & JS Section
4119 - *
4120 - * @access public
4121 - * @return void
4122 - */
4123 - public function render_custom_css_js_section() {
4124 - ?>
4125 - <div class="upk-custom-code-section">
4126 - <!-- Header Section -->
4127 - <div class="upk-code-section-header">
4128 - <h2 class="upk-section-title"><?php esc_html_e('Header Code Injection', 'ultimate-post-kit'); ?></h2>
4129 - <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>
4130 - </div>
4131 - <div class="upk-code-row bdt-grid bdt-grid-small" bdt-grid>
4132 - <div class="bdt-width-1-2@m">
4133 - <div class="upk-code-editor-wrapper">
4134 - <h3 class="upk-code-editor-title"><?php esc_html_e('CSS', 'ultimate-post-kit'); ?></h3>
4135 - <p class="upk-code-editor-description"><?php esc_html_e('Enter raw CSS code without &lt;style&gt; tags.', 'ultimate-post-kit'); ?></p>
4136 - <div class="upk-codemirror-editor-container">
4137 - <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>
4138 - </div>
4139 - </div>
4140 - </div>
4141 - <div class="bdt-width-1-2@m">
4142 - <div class="upk-code-editor-wrapper">
4143 - <h3 class="upk-code-editor-title"><?php esc_html_e('JS', 'ultimate-post-kit'); ?></h3>
4144 - <p class="upk-code-editor-description"><?php esc_html_e('Enter raw JavaScript code without &lt;script&gt; tags.', 'ultimate-post-kit'); ?></p>
4145 - <div class="upk-codemirror-editor-container">
4146 - <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>
4147 - </div>
4148 - </div>
4149 - </div>
4150 - </div>
4151 2257
4152 - <!-- Footer Section -->
4153 - <div class="upk-code-section-header bdt-margin-medium-top">
4154 - <h2 class="upk-section-title"><?php esc_html_e('Footer Code Injection', 'ultimate-post-kit'); ?></h2>
4155 - <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>
4156 - </div>
4157 - <div class="upk-code-row bdt-grid bdt-grid-small bdt-margin-small-top" bdt-grid>
4158 - <div class="bdt-width-1-2@m">
4159 - <div class="upk-code-editor-wrapper">
4160 - <h3 class="upk-code-editor-title"><?php esc_html_e('CSS', 'ultimate-post-kit'); ?></h3>
4161 - <p class="upk-code-editor-description"><?php esc_html_e('Enter raw CSS code without &lt;style&gt; tags.', 'ultimate-post-kit'); ?></p>
4162 - <div class="upk-codemirror-editor-container">
4163 - <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>
4164 - </div>
4165 - </div>
4166 - </div>
4167 - <div class="bdt-width-1-2@m">
4168 - <div class="upk-code-editor-wrapper">
4169 - <h3 class="upk-code-editor-title"><?php esc_html_e('JS', 'ultimate-post-kit'); ?></h3>
4170 - <p class="upk-code-editor-description"><?php esc_html_e('Enter raw JavaScript code without &lt;script&gt; tags.', 'ultimate-post-kit'); ?></p>
4171 - <div class="upk-codemirror-editor-container">
4172 - <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>
4173 - </div>
4174 - </div>
4175 - </div>
4176 - </div>
4177 -
4178 - <!-- Page Exclusion Section -->
4179 - <div class="upk-code-section-header bdt-margin-medium-top">
4180 - <h2 class="upk-section-title"><?php esc_html_e('Page & Post Exclusion Settings', 'ultimate-post-kit'); ?></h2>
4181 - <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>
4182 - </div>
4183 - <div class="upk-page-exclusion-wrapper">
4184 - <label for="upk-excluded-pages" class="upk-exclusion-label">
4185 - <?php esc_html_e('Exclude Pages & Posts:', 'ultimate-post-kit'); ?>
4186 - </label>
4187 - <select id="upk-excluded-pages" name="upk_excluded_pages[]" multiple class="upk-page-select">
4188 - <option value=""><?php esc_html_e('-- Select pages/posts to exclude --', 'ultimate-post-kit'); ?></option>
4189 - <?php
4190 - $excluded_pages = get_option('upk_excluded_pages', array());
4191 - if (!is_array($excluded_pages)) {
4192 - $excluded_pages = array();
4193 - }
4194 -
4195 - // Get all published pages
4196 - $pages = get_pages(array(
4197 - 'sort_order' => 'ASC',
4198 - 'sort_column' => 'post_title',
4199 - 'post_status' => 'publish'
4200 - ));
4201 -
4202 - // Get recent posts (last 50)
4203 - $posts = get_posts(array(
4204 - 'numberposts' => 50,
4205 - 'post_status' => 'publish',
4206 - 'post_type' => 'post',
4207 - 'orderby' => 'date',
4208 - 'order' => 'DESC'
4209 - ));
4210 -
4211 - // Display pages first
4212 - if (!empty($pages)) {
4213 - echo '<optgroup label="' . esc_attr__('Pages', 'ultimate-post-kit') . '">';
4214 - foreach ($pages as $page) {
4215 - $selected = in_array($page->ID, $excluded_pages) ? 'selected' : '';
4216 - echo '<option value="' . esc_attr($page->ID) . '" ' . $selected . '>' . esc_html($page->post_title) . '</option>';
4217 - }
4218 - echo '</optgroup>';
4219 - }
4220 -
4221 - // Then display posts
4222 - if (!empty($posts)) {
4223 - echo '<optgroup label="' . esc_attr__('Recent Posts', 'ultimate-post-kit') . '">';
4224 - foreach ($posts as $post) {
4225 - $selected = in_array($post->ID, $excluded_pages) ? 'selected' : '';
4226 - $post_date = date('M j, Y', strtotime($post->post_date));
4227 - echo '<option value="' . esc_attr($post->ID) . '" ' . $selected . '>' . esc_html($post->post_title) . ' (' . $post_date . ')</option>';
4228 - }
4229 - echo '</optgroup>';
4230 - }
4231 - ?>
4232 - </select>
4233 - <p class="upk-exclusion-help">
4234 - <?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'); ?>
4235 - </p>
4236 - </div>
4237 -
4238 - <!-- Success/Error Messages -->
4239 - <div id="upk-custom-code-message" class="upk-code-message bdt-margin-small-top" style="display: none;">
4240 - <div class="bdt-alert bdt-alert-success" bdt-alert>
4241 - <a href class="bdt-alert-close" bdt-close></a>
4242 - <p><?php esc_html_e('Custom code saved successfully!', 'ultimate-post-kit'); ?></p>
4243 - </div>
4244 - </div>
4245 - </div>
4246 - <?php
4247 - }
4248 -
4249 2258 /**
4250 - * Extra Options Start Here
4251 - */
4252 -
4253 - public function ultimate_post_kit_extra_options() {
4254 - ?>
4255 - <div class="upk-dashboard-panel"
4256 - bdt-scrollspy="target: > div > div > .bdt-card; cls: bdt-animation-slide-bottom-small; delay: 300">
4257 - <div class="upk-dashboard-extra-options">
4258 - <div class="bdt-card bdt-card-body">
4259 - <h1 class="upk-feature-title"><?php esc_html_e('Extra Options', 'ultimate-post-kit'); ?></h1>
4260 -
4261 - <div class="upk-extra-options-tabs">
4262 - <ul class="bdt-tab" bdt-tab="connect: #upk-extra-options-tab-content; animation: bdt-animation-fade">
4263 - <li class="bdt-active"><a
4264 - href="#"><?php esc_html_e('Custom CSS & JS', 'ultimate-post-kit'); ?></a></li>
4265 - <li><a href="#"><?php esc_html_e('White Label', 'ultimate-post-kit'); ?></a></li>
4266 - </ul>
4267 -
4268 - <div id="upk-extra-options-tab-content" class="bdt-switcher">
4269 - <!-- Custom CSS & JS Tab -->
4270 - <div>
4271 - <?php $this->render_custom_css_js_section(); ?>
4272 - </div>
4273 -
4274 - <!-- White Label Tab -->
4275 - <div>
4276 - <?php $this->render_white_label_section(); ?>
4277 - </div>
4278 - </div>
4279 - </div>
4280 - </div>
4281 - </div>
4282 - </div>
4283 - <?php
4284 - }
4285 -
4286 -
4287 - /**
4288 2259 * Rollback Version Content
4289 2260 *
4290 2261 * @access public
4291 2262 * @return void
4292 2263 */
4293 - public function ultimate_post_kit_rollback_version_content() {
2264 + public function upk_rollback_version_content() {
4294 2265 // Use the already initialized rollback version instance
4295 - $this->rollback_version->ultimate_post_kit_rollback_version_content();
2266 + $this->rollback_version->upk_rollback_version_content();
4296 2267 }
4297 2268
4298 - /**
4299 - * Get allowed white label license types (SHA-256 hashes)
4300 - * This centralized method makes it easy to add new license types in the future
4301 - * Note: AppSumo and Lifetime licenses require WL flag in other_param instead of automatic access
4302 - *
4303 - * @access public static
4304 - * @return array Array of SHA-256 hashes for allowed license types
4305 - */
4306 - public static function get_white_label_allowed_license_types() {
4307 - $allowed_types = [
4308 - 'agency' => 'c4b2af4722ee54e317672875b2d8cf49aa884bf5820ec6091114fea5ec6560e4',
4309 - 'extended' => '4d7120eb6c796b04273577476eb2e20c34c51d7fa1025ec19c3414448abc241e',
4310 - 'developer' => '88fa0d759f845b47c044c2cd44e29082cf6fea665c30c146374ec7c8f3d699e3',
4311 - // Note: AppSumo and Lifetime licenses removed from automatic access
4312 - // They require WL flag in other_param for white label functionality
4313 - ];
4314 -
4315 - return $allowed_types;
4316 - }
4317 -
4318 - /**
4319 - * Revoke white label access token
4320 - *
4321 - * @access public
4322 - * @return bool
4323 - */
4324 - public function revoke_white_label_access_token() {
4325 - $token_data = get_option( 'upk_white_label_access_token', [] );
4326 -
4327 - if ( ! empty( $token_data ) ) {
4328 - delete_option( 'upk_white_label_access_token' );
4329 - return true;
4330 - }
4331 -
4332 - return false;
4333 - }
4334 -
4335 - /**
4336 - * Validate white label access token
4337 - *
4338 - * @access public
4339 - * @param string $token
4340 - * @return bool
4341 - */
4342 - public function validate_white_label_access_token( $token ) {
4343 - $stored_token_data = get_option( 'upk_white_label_access_token', [] );
4344 -
4345 - if ( empty( $stored_token_data ) || ! isset( $stored_token_data['token'] ) ) {
4346 - return false;
4347 - }
4348 -
4349 - // Check token match
4350 - if ( $stored_token_data['token'] !== $token ) {
4351 - return false;
4352 - }
4353 -
4354 - // Check if token was generated for current license
4355 - $current_license_key = self::get_license_key();
4356 - if ( $stored_token_data['license_key'] !== $current_license_key ) {
4357 - return false;
4358 - }
4359 -
4360 - return true;
4361 - }
4362 -
4363 - /**
4364 - * AJAX handler for revoking white label access token
4365 - *
4366 - * @access public
4367 - * @return void
4368 - */
4369 - public function revoke_white_label_token_ajax() {
4370 - // Check nonce and permissions
4371 - if (!wp_verify_nonce($_POST['nonce'], 'upk_white_label_nonce')) {
4372 - wp_send_json_error(['message' => __('Security check failed', 'ultimate-post-kit')]);
4373 - }
4374 -
4375 - if (!current_user_can('manage_options')) {
4376 - wp_send_json_error(['message' => __('You do not have permission to manage white label settings', 'ultimate-post-kit')]);
4377 - }
4378 -
4379 - // Check license eligibility
4380 - if (!self::is_white_label_license()) {
4381 - wp_send_json_error(['message' => __('Your license does not support white label features', 'ultimate-post-kit')]);
4382 - }
4383 -
4384 - // Revoke the token
4385 - $revoked = $this->revoke_white_label_access_token();
4386 -
4387 - if ($revoked) {
4388 - wp_send_json_success([
4389 - 'message' => __('White label access token has been revoked successfully', 'ultimate-post-kit')
4390 - ]);
4391 - } else {
4392 - wp_send_json_error([
4393 - 'message' => __('No active access token found to revoke', 'ultimate-post-kit')
4394 - ]);
4395 - }
4396 - }
4397 -
4398 - /**
4399 - * Get License Key
4400 - *
4401 - * @access public
4402 - * @return string
4403 - */
4404 -
4405 - public static function get_license_key() {
4406 - $license_key = get_option('ultimate_post_kit_license_key');
4407 - return trim($license_key);
4408 - }
4409 -
4410 - /**
4411 - * Get License Email
4412 - *
4413 - * @access public
4414 - * @return string
4415 - */
4416 -
4417 - public static function get_license_email() {
4418 - return trim(get_option('ultimate_post_kit_license_email', get_bloginfo('admin_email')));
4419 - }
4420 2269
4421 2270 }
4422 2271
4423 2272 new UltimatePostKit_Admin_Settings();