PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.83
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.83
51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 51.1.45 51.1.46 All 39 releases
← All changes | king-addons.php +355 -21 51.1.3551.1.83 View file →
@@ -1,12 +1,12 @@
1 1 <?php
2 2
3 3 /**
4 - * Plugin Name: King Addons
5 - * Description: 4,000+ ready Elementor sections, 650+ templates, 70+ FREE widgets for Elementor, and features like Live Search, Popups, Carousels, Image Hotspots, and Parallax Backgrounds.
4 + * Plugin Name: King Addons for Elementor
5 + * Description: Elementor addons, 4,000+ Templates & Sections, 80+ Widgets, AI Tools, Mega Menu, Popup Builder, WooCommerce, Templates & Sections. Lightweight & fast Elementor toolkit.
6 6 * Author URI: https://kingaddons.com/
7 7 * Author: KingAddons.com
8 - * Version: 51.1.32
8 + * Version: 51.1.83
9 9 * Text Domain: king-addons
10 10 * Requires at least: 6.0
11 11 * Requires PHP: 7.4
12 12 * License: GPLv3
@@ -21,9 +21,9 @@
21 21 // Load plugin textdomain immediately to prevent early translation loading notices.
22 22 load_plugin_textdomain('king-addons');
23 23
24 24 /** PLUGIN VERSION */
25 -const KING_ADDONS_VERSION = '51.1.32';
25 +const KING_ADDONS_VERSION = '51.1.83';
26 26
27 27 /** DEFINES */
28 28 define('KING_ADDONS_PATH', plugin_dir_path(__FILE__));
29 29 define('KING_ADDONS_URL', plugins_url('/', __FILE__));
@@ -32,8 +32,11 @@
32 32 const KING_ADDONS_ASSETS_UNIQUE_KEY = 'king-addons';
33 33
34 34 require_once(KING_ADDONS_PATH . 'includes/helpers/Global/global-constants.php');
35 35
36 +// Shared AI provider abstraction (OpenAI / OpenRouter), used by admin and extensions.
37 +require_once(KING_ADDONS_PATH . 'includes/AI_Provider.php');
38 +
36 39 if (!function_exists('king_addons_freemius')) {
37 40 // Create a helper function for easy SDK access.
38 41 function king_addons_freemius()
39 42 {
@@ -49,15 +52,15 @@
49 52 'slug' => 'king-addons',
50 53 'premium_slug' => 'king-addons-pro',
51 54 'type' => 'plugin',
52 55 'public_key' => 'pk_eac3624cbc14c1846cf1ab9abbd68',
53 - 'is_premium' => false, // temp
56 + 'is_premium' => false,
54 57 'premium_suffix' => 'pro',
55 58 // If your plugin is a serviceware, set this option to false.
56 59 'has_premium_version' => true,
57 60 'has_addons' => false,
58 - 'has_paid_plans' => false, // temp
59 - 'has_affiliation' => 'all',
61 + 'has_paid_plans' => true,
62 + 'has_affiliation' => 'selected',
60 63 'menu' => array(
61 64 'slug' => 'king-addons',
62 65 'first-path' => 'plugins.php',
63 66 'pricing' => false,
@@ -62,8 +65,9 @@
62 65 'first-path' => 'plugins.php',
63 66 'pricing' => false,
64 67 'contact' => false,
65 68 'support' => false,
69 + 'affiliation' => false,
66 70 ),
67 71 ));
68 72 }
69 73
@@ -77,8 +81,107 @@
77 81 king_addons_freemius()->add_filter('show_deactivation_subscription_cancellation', '__return_false');
78 82 king_addons_freemius()->add_filter('deactivate_on_activation', '__return_false');
79 83 }
80 84
85 +/**
86 + * Safe check for Pro/Premium availability.
87 + *
88 + * This helper function safely checks if the premium code can be used,
89 + * preventing fatal errors if Freemius is not properly initialized.
90 + *
91 + * @since 51.1.40
92 + * @return bool True if premium code can be used, false otherwise.
93 + */
94 +if (!function_exists('king_addons_can_use_pro')) {
95 + function king_addons_can_use_pro(): bool
96 + {
97 + if (!function_exists('king_addons_freemius')) {
98 + return false;
99 + }
100 +
101 + $fs = king_addons_freemius();
102 + if (!is_object($fs) || !method_exists($fs, 'can_use_premium_code')) {
103 + return false;
104 + }
105 +
106 + return (bool) $fs->can_use_premium_code();
107 + }
108 +}
109 +
110 +/**
111 + * Whether the WooCommerce Builder top-level menu is registered.
112 + *
113 + * Wishlist and other store screens hang off that menu when it exists,
114 + * and fall back to King Addons when it does not.
115 + *
116 + * @return bool
117 + */
118 +if (!function_exists('king_addons_woo_builder_menu_is_active')) {
119 + function king_addons_woo_builder_menu_is_active(): bool
120 + {
121 + $options = get_option('king_addons_options', []);
122 + $enabled = !isset($options['ext_woo-builder']) || $options['ext_woo-builder'] === 'enabled';
123 +
124 + return $enabled
125 + && (defined('KING_ADDONS_EXT_WOO_BUILDER') ? (bool) KING_ADDONS_EXT_WOO_BUILDER : true)
126 + && class_exists('WooCommerce')
127 + && function_exists('WC');
128 + }
129 +}
130 +
131 +/**
132 + * Parent slug for WooCommerce-related admin screens.
133 + *
134 + * Page slugs stay the same; only the WP menu parent changes.
135 + *
136 + * @return string
137 + */
138 +if (!function_exists('king_addons_woo_admin_parent_slug')) {
139 + function king_addons_woo_admin_parent_slug(): string
140 + {
141 + return king_addons_woo_builder_menu_is_active() ? 'king-addons-woo-builder' : 'king-addons';
142 + }
143 +}
144 +
145 +/**
146 + * Whether the current admin screen belongs to King Addons.
147 + *
148 + * Screen IDs follow the WP parent menu title, so Woo screens under
149 + * WooCommerce Builder become `woocommerce-builder_page_*`. Page slugs
150 + * still start with `king-addons`.
151 + *
152 + * @param string|null $current_screen Optional screen id; current screen if omitted.
153 + * @return bool
154 + */
155 +if (!function_exists('king_addons_is_plugin_admin_screen')) {
156 + function king_addons_is_plugin_admin_screen(?string $current_screen = null): bool
157 + {
158 + $page = isset($_GET['page']) ? sanitize_key(wp_unslash($_GET['page'])) : '';
159 + if ($page !== '' && strpos($page, 'king-addons') === 0) {
160 + return true;
161 + }
162 +
163 + if ($current_screen === null) {
164 + $screen = function_exists('get_current_screen') ? get_current_screen() : null;
165 + if (!$screen || empty($screen->id)) {
166 + return false;
167 + }
168 + $current_screen = (string) $screen->id;
169 + }
170 +
171 + $legacy_screens = [
172 + 'edit-king-addons-el-hf',
173 + 'edit-king-addons-fb-sub',
174 + 'header-footer_page_king-addons-el-hf-settings',
175 + ];
176 +
177 + return (strpos($current_screen, 'king-addons_') === 0)
178 + || (strpos($current_screen, 'toplevel_page_king-addons') === 0)
179 + || (strpos($current_screen, 'woocommerce-builder_page_') === 0)
180 + || in_array($current_screen, $legacy_screens, true);
181 + }
182 +}
183 +
81 184 if (!function_exists('king_addons_doActivation')) {
82 185 function king_addons_doActivation()
83 186 {
84 187 add_option('king_addons_plugin_activated', true);
@@ -84,8 +187,17 @@
84 187 add_option('king_addons_plugin_activated', true);
85 188 if (false === get_option('king_addons_optionActivationTime')) {
86 189 add_option('king_addons_optionActivationTime', absint(intval(strtotime('now'))));
87 190 }
191 +
192 + // Ensure wishlist tables are created on activation.
193 + require_once plugin_dir_path(__FILE__) . 'includes/wishlist/Wishlist_DB.php';
194 + \King_Addons\Wishlist\Wishlist_DB::maybe_create_tables();
195 +
196 + // Ensure Smart Links tables are created on activation.
197 + require_once plugin_dir_path(__FILE__) . 'includes/extensions/Smart_Links/Smart_Links_DB.php';
198 + \King_Addons\Smart_Links\Smart_Links_DB::maybe_create_tables();
199 + update_option('king_addons_smart_links_flush_rewrite', 1);
88 200 }
89 201
90 202 register_activation_hook(__FILE__, 'king_addons_doActivation');
91 203 }
@@ -149,8 +261,35 @@
149 261 add_action('wp_loaded', 'king_addons_registerAssets');
150 262 }
151 263
152 264 /**
265 + * Enqueue small frontend-only CSS fixes.
266 + *
267 + * @return void
268 + * @since 51.1.42
269 + */
270 +if (!function_exists('king_addons_enqueue_frontend_fixes_css')) {
271 + function king_addons_enqueue_frontend_fixes_css(): void
272 + {
273 + if (is_admin()) {
274 + return;
275 + }
276 +
277 + wp_enqueue_style(
278 + KING_ADDONS_ASSETS_UNIQUE_KEY . '-fixes-for-elementor',
279 + KING_ADDONS_URL . 'includes/assets/css/fixes-for-elementor.css',
280 + [],
281 + KING_ADDONS_VERSION
282 + );
283 + }
284 +
285 + add_action('wp_enqueue_scripts', 'king_addons_enqueue_frontend_fixes_css', 99);
286 + // Ensure the stylesheet is also loaded in Elementor's preview iframe inside the editor.
287 + add_action('elementor/frontend/after_enqueue_styles', 'king_addons_enqueue_frontend_fixes_css', 99);
288 + add_action('elementor/preview/enqueue_styles', 'king_addons_enqueue_frontend_fixes_css', 99);
289 +}
290 +
291 +/**
153 292 * Hides spaming notices from another plugins on the plugin settings page
154 293 *
155 294 * @return void
156 295 * @since 1.0.0
@@ -159,21 +298,15 @@
159 298 if (!function_exists('king_addons_hideAnotherNotices')) {
160 299 /** @noinspection PhpMissingReturnTypeInspection */
161 300 function king_addons_hideAnotherNotices()
162 301 {
163 - $current_screen = get_current_screen()->id;
164 - // error_log($current_screen);
165 - if (
166 - $current_screen == 'toplevel_page_king-addons' ||
167 - $current_screen == 'toplevel_page_king-addons-templates' ||
168 - $current_screen == 'toplevel_page_king-addons-popup-builder' ||
169 - $current_screen == 'edit-king-addons-el-hf' ||
170 - $current_screen == 'edit-king-addons-fb-sub' ||
171 - $current_screen == 'header-footer_page_king-addons-el-hf-settings' ||
172 - $current_screen == 'king-addons_page_king-addons-ai-settings' ||
173 - $current_screen == 'king-addons_page_king-addons-pricing' ||
174 - $current_screen == 'king-addons_page_king-addons-settings'
175 - ) {
302 + // Exclude the account page from notice hiding.
303 + // URL: /wp-admin/admin.php?page=king-addons-account
304 + if (isset($_GET['page']) && $_GET['page'] === 'king-addons-account') {
305 + return;
306 + }
307 +
308 + if (king_addons_is_plugin_admin_screen()) {
176 309 // Remove all notices
177 310 remove_all_actions('user_admin_notices');
178 311 remove_all_actions('admin_notices');
179 312 }
@@ -182,8 +315,205 @@
182 315 add_action('in_admin_header', 'king_addons_hideAnotherNotices', 99);
183 316 }
184 317
185 318 /**
319 + * Custom admin footer text on King Addons pages
320 + * Shows rating request similar to WooCommerce
321 + *
322 + * @param string $footer_text Default footer text.
323 + * @return string Modified footer text.
324 + * @since 51.2.0
325 + */
326 +if (!function_exists('king_addons_admin_footer_text')) {
327 + function king_addons_admin_footer_text($footer_text)
328 + {
329 + if (!current_user_can('manage_options')) {
330 + return $footer_text;
331 + }
332 +
333 + if (!king_addons_is_plugin_admin_screen()) {
334 + return $footer_text;
335 + }
336 +
337 + // Check if user has already rated
338 + if (!get_option('king_addons_admin_footer_text_rated')) {
339 + $footer_text = sprintf(
340 + /* translators: 1: King Addons 2: five stars */
341 + __('If you like %1$s please leave us a %2$s rating. A huge thanks in advance!', 'king-addons'),
342 + sprintf('<strong>%s</strong>', esc_html__('King Addons', 'king-addons')),
343 + '<a href="https://wordpress.org/support/plugin/king-addons/reviews?rate=5#new-post" target="_blank" class="king-addons-rating-link" aria-label="' . esc_attr__('five star', 'king-addons') . '" data-rated="' . esc_attr__('Thanks :)', 'king-addons') . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
344 + );
345 + } else {
346 + $footer_text = __('Thank you for using King Addons!', 'king-addons');
347 + }
348 +
349 + return '<span id="footer-thankyou">' . $footer_text . '</span>';
350 + }
351 +
352 + add_filter('admin_footer_text', 'king_addons_admin_footer_text', 1);
353 +}
354 +
355 +/**
356 + * Enqueue script for rating link click handler
357 + *
358 + * @return void
359 + * @since 51.2.0
360 + */
361 +if (!function_exists('king_addons_rating_script')) {
362 + function king_addons_rating_script()
363 + {
364 + if (!current_user_can('manage_options')) {
365 + return;
366 + }
367 +
368 + // Only on King Addons pages and only if not already rated
369 + if (!king_addons_is_plugin_admin_screen() || get_option('king_addons_admin_footer_text_rated')) {
370 + return;
371 + }
372 +
373 + $script = "
374 + (function() {
375 + 'use strict';
376 + var ratingLink = document.querySelector('a.king-addons-rating-link');
377 + if (ratingLink) {
378 + ratingLink.addEventListener('click', function(e) {
379 + var link = e.currentTarget;
380 + var formData = new FormData();
381 + formData.append('action', 'king_addons_rated');
382 + formData.append('nonce', '" . esc_js(wp_create_nonce('king_addons_rated')) . "');
383 +
384 + fetch('" . esc_js(admin_url('admin-ajax.php')) . "', {
385 + method: 'POST',
386 + body: formData,
387 + credentials: 'same-origin'
388 + });
389 +
390 + var parent = link.parentElement;
391 + if (parent) {
392 + parent.textContent = link.getAttribute('data-rated');
393 + }
394 + });
395 + }
396 + })();
397 + ";
398 +
399 + $handle = 'king-addons-admin-footer-rating';
400 + wp_register_script($handle, '', [], KING_ADDONS_VERSION, true);
401 + wp_enqueue_script($handle);
402 + wp_add_inline_script($handle, $script);
403 + }
404 +
405 + add_action('admin_enqueue_scripts', 'king_addons_rating_script');
406 +}
407 +
408 +/**
409 + * AJAX handler for saving rated status
410 + *
411 + * @return void
412 + * @since 51.2.0
413 + */
414 +if (!function_exists('king_addons_rated_callback')) {
415 + function king_addons_rated_callback()
416 + {
417 + if (!current_user_can('manage_options')) {
418 + wp_die(-1, 403);
419 + }
420 +
421 + check_ajax_referer('king_addons_rated', 'nonce');
422 +
423 + update_option('king_addons_admin_footer_text_rated', 1);
424 + wp_die();
425 + }
426 +
427 + add_action('wp_ajax_king_addons_rated', 'king_addons_rated_callback');
428 +}
429 +
430 +/**
431 + * Apply theme detection script to Account page
432 + * Reads user's theme preference and applies ka-v3-dark class if needed
433 + *
434 + * @return void
435 + * @since 51.2.0
436 + */
437 +if (!function_exists('king_addons_account_page_theme_script')) {
438 + function king_addons_account_page_theme_script()
439 + {
440 + $screen = function_exists('get_current_screen') ? get_current_screen() : null;
441 + if (!$screen || $screen->id !== 'king-addons_page_king-addons-account') {
442 + return;
443 + }
444 +
445 + // Get user's theme preference
446 + $theme_mode = get_user_meta(get_current_user_id(), 'king_addons_theme_mode', true);
447 + $allowed_theme_modes = ['dark', 'light', 'auto'];
448 + if (!in_array($theme_mode, $allowed_theme_modes, true)) {
449 + $theme_mode = 'auto';
450 + }
451 + ?>
452 + <script>
453 + (function() {
454 + var themeMode = '<?php echo esc_js($theme_mode); ?>';
455 + var root = document.documentElement;
456 + var mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
457 +
458 + // Prevent flash by disabling transitions early (body isn't available in admin_head).
459 + root.classList.add('ka-no-transition');
460 +
461 + function isDarkForMode(mode) {
462 + if (mode === 'auto') {
463 + return !!(mql && mql.matches);
464 + }
465 +
466 + return mode === 'dark';
467 + }
468 +
469 + function applyTheme(mode) {
470 + var isDark = isDarkForMode(mode);
471 +
472 + root.classList.toggle('ka-v3-dark', isDark);
473 +
474 + // body may not exist yet (this script runs in <head>).
475 + if (document.body) {
476 + document.body.classList.toggle('ka-v3-dark', isDark);
477 + }
478 + }
479 +
480 + applyTheme(themeMode);
481 +
482 + // Once body exists, ensure it mirrors the html class.
483 + document.addEventListener('DOMContentLoaded', function() {
484 + applyTheme(themeMode);
485 + if (document.body) {
486 + document.body.classList.remove('ka-no-transition');
487 + }
488 + });
489 +
490 + // Listen for system theme changes if in auto mode.
491 + if (themeMode === 'auto' && mql) {
492 + var onMqlChange = function() {
493 + applyTheme('auto');
494 + };
495 +
496 + if (typeof mql.addEventListener === 'function') {
497 + mql.addEventListener('change', onMqlChange);
498 + } else if (typeof mql.addListener === 'function') {
499 + mql.addListener(onMqlChange);
500 + }
501 + }
502 +
503 + // Re-enable transitions.
504 + setTimeout(function() {
505 + root.classList.remove('ka-no-transition');
506 + }, 50);
507 + })();
508 + </script>
509 + <?php
510 + }
511 +
512 + add_action('admin_head', 'king_addons_account_page_theme_script', 1);
513 +}
514 +
515 +/**
186 516 * Apply styles to the plugin menu icon because some plugins broke the menu icon styles
187 517 *
188 518 * @return void
189 519 * @since 24.8.25
@@ -196,8 +526,12 @@
196 526 wp_enqueue_style('king-addons-plugin-style-menu-icon', plugin_dir_url(__FILE__) . 'includes/admin/css/menu-icon.css', '', KING_ADDONS_VERSION);
197 527 if (get_current_screen()->id == 'king-addons_page_king-addons-pricing') {
198 528 wp_enqueue_style('king-addons-plugin-style-pricing', plugin_dir_url(__FILE__) . 'includes/admin/css/pricing.css', '', KING_ADDONS_VERSION);
199 529 }
530 + // Load Account page styles
531 + if (get_current_screen()->id == 'king-addons_page_king-addons-account') {
532 + wp_enqueue_style('king-addons-plugin-style-account', plugin_dir_url(__FILE__) . 'includes/admin/css/account.css', '', KING_ADDONS_VERSION);
533 + }
200 534 }
201 535
202 536 add_action('admin_enqueue_scripts', 'king_addons_styleMenuIcon');
203 537 }
@@ -229,5 +563,5 @@
229 563 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
230 564 add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'king_addons_add_action_links');
231 565 add_filter('network_admin_plugin_action_links_' . plugin_basename(__FILE__), 'king_addons_add_action_links');
232 566 }
233 -}
567 +}