PluginProbe
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder / 51.1.65
King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder v51.1.65
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 51.1.47 51.1.49 51.1.51 All 36 releases
king-addons / king-addons.php

king-addons.php in King Addons for Elementor – 80+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce, Mega Menu, Popup Builder 51.1.65, at king-addons.php

544 lines 18.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
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 * Author URI: https://kingaddons.com/
7 * Author: KingAddons.com
8 * Version: 51.1.65
9 * Text Domain: king-addons
10 * Requires at least: 6.0
11 * Requires PHP: 7.4
12 * License: GPLv3
13 * License URI: https://www.gnu.org/licenses/gpl-3.0.html
14 */
15
16 /** @noinspection SpellCheckingInspection */
17 if (!defined('ABSPATH')) {
18 exit; // Exit if accessed directly.
19 }
20
21 // Load plugin textdomain immediately to prevent early translation loading notices.
22 load_plugin_textdomain('king-addons');
23
24 /** PLUGIN VERSION */
25 const KING_ADDONS_VERSION = '51.1.65';
26
27 /** DEFINES */
28 define('KING_ADDONS_PATH', plugin_dir_path(__FILE__));
29 define('KING_ADDONS_URL', plugins_url('/', __FILE__));
30
31 /** ASSETS KEY - It's using to have the unique wp_register (style, script) handle */
32 const KING_ADDONS_ASSETS_UNIQUE_KEY = 'king-addons';
33
34 require_once(KING_ADDONS_PATH . 'includes/helpers/Global/global-constants.php');
35
36 if (!function_exists('king_addons_freemius')) {
37 // Create a helper function for easy SDK access.
38 function king_addons_freemius()
39 {
40 global $king_addons_freemius;
41
42 if (!isset($king_addons_freemius)) {
43 // Include Freemius SDK.
44 require_once dirname(__FILE__) . '/freemius/start.php';
45
46 /** @noinspection PhpUnhandledExceptionInspection */
47 $king_addons_freemius = fs_dynamic_init(array(
48 'id' => '16154',
49 'slug' => 'king-addons',
50 'premium_slug' => 'king-addons-pro',
51 'type' => 'plugin',
52 'public_key' => 'pk_eac3624cbc14c1846cf1ab9abbd68',
53 'is_premium' => false,
54 'premium_suffix' => 'pro',
55 // If your plugin is a serviceware, set this option to false.
56 'has_premium_version' => true,
57 'has_addons' => false,
58 'has_paid_plans' => true,
59 'has_affiliation' => 'selected',
60 'menu' => array(
61 'slug' => 'king-addons',
62 'first-path' => 'plugins.php',
63 'pricing' => false,
64 'contact' => false,
65 'support' => false,
66 'affiliation' => false,
67 ),
68 ));
69 }
70
71 return $king_addons_freemius;
72 }
73
74 // Init Freemius.
75 king_addons_freemius();
76 // Signal that SDK was initiated.
77 do_action('king_addons_freemius_loaded');
78 king_addons_freemius()->add_filter('show_deactivation_subscription_cancellation', '__return_false');
79 king_addons_freemius()->add_filter('deactivate_on_activation', '__return_false');
80 }
81
82 /**
83 * Safe check for Pro/Premium availability.
84 *
85 * This helper function safely checks if the premium code can be used,
86 * preventing fatal errors if Freemius is not properly initialized.
87 *
88 * @since 51.1.40
89 * @return bool True if premium code can be used, false otherwise.
90 */
91 if (!function_exists('king_addons_can_use_pro')) {
92 function king_addons_can_use_pro(): bool
93 {
94 if (!function_exists('king_addons_freemius')) {
95 return false;
96 }
97
98 $fs = king_addons_freemius();
99 if (!is_object($fs) || !method_exists($fs, 'can_use_premium_code')) {
100 return false;
101 }
102
103 return (bool) $fs->can_use_premium_code();
104 }
105 }
106
107 if (!function_exists('king_addons_doActivation')) {
108 function king_addons_doActivation()
109 {
110 add_option('king_addons_plugin_activated', true);
111 if (false === get_option('king_addons_optionActivationTime')) {
112 add_option('king_addons_optionActivationTime', absint(intval(strtotime('now'))));
113 }
114
115 // Ensure wishlist tables are created on activation.
116 require_once plugin_dir_path(__FILE__) . 'includes/wishlist/Wishlist_DB.php';
117 \King_Addons\Wishlist\Wishlist_DB::maybe_create_tables();
118
119 // Ensure Smart Links tables are created on activation.
120 require_once plugin_dir_path(__FILE__) . 'includes/extensions/Smart_Links/Smart_Links_DB.php';
121 \King_Addons\Smart_Links\Smart_Links_DB::maybe_create_tables();
122 update_option('king_addons_smart_links_flush_rewrite', 1);
123 }
124
125 register_activation_hook(__FILE__, 'king_addons_doActivation');
126 }
127
128 if (!function_exists('king_addons_doDectivation')) {
129 function king_addons_doDectivation()
130 {
131 delete_option('king_addons_HFB_flushed_rewrite_rules');
132 delete_option('king_addons_optionActivationTime');
133 }
134
135 register_deactivation_hook(__FILE__, 'king_addons_doDectivation');
136 }
137
138 if (!function_exists('king_addons_doRedirect_after_activation')) {
139 function king_addons_doRedirect_after_activation()
140 {
141 if (did_action('elementor/loaded')) {
142 if (get_option('king_addons_plugin_activated', false)) {
143 delete_option('king_addons_plugin_activated');
144 wp_redirect(admin_url('admin.php?page=king-addons'));
145 exit;
146 }
147 }
148 }
149
150 add_action('admin_init', 'king_addons_doRedirect_after_activation');
151 }
152
153 /**
154 * Main function
155 *
156 * @return void
157 * @since 1.0.0
158 * @access public
159 */
160 if (!function_exists('king_addons_doPlugin')) {
161 /** @noinspection PhpMissingReturnTypeInspection */
162 function king_addons_doPlugin()
163 {
164 require_once(KING_ADDONS_PATH . 'includes/Core.php');
165 }
166 // Using after_setup_theme to fix: PHP Notice: Function _load_textdomain_just_in_time was called incorrectly.
167 add_action('after_setup_theme', 'king_addons_doPlugin');
168 }
169
170 /**
171 * Register Assets
172 *
173 * @return void
174 * @since 1.0.0
175 * @access public
176 */
177 if (!function_exists('king_addons_registerAssets')) {
178 /** @noinspection PhpMissingReturnTypeInspection */
179 function king_addons_registerAssets()
180 {
181 require_once(KING_ADDONS_PATH . 'includes/RegisterAssets.php');
182 }
183
184 add_action('wp_loaded', 'king_addons_registerAssets');
185 }
186
187 /**
188 * Enqueue small frontend-only CSS fixes.
189 *
190 * @return void
191 * @since 51.1.42
192 */
193 if (!function_exists('king_addons_enqueue_frontend_fixes_css')) {
194 function king_addons_enqueue_frontend_fixes_css(): void
195 {
196 if (is_admin()) {
197 return;
198 }
199
200 wp_enqueue_style(
201 KING_ADDONS_ASSETS_UNIQUE_KEY . '-fixes-for-elementor',
202 KING_ADDONS_URL . 'includes/assets/css/fixes-for-elementor.css',
203 [],
204 KING_ADDONS_VERSION
205 );
206 }
207
208 add_action('wp_enqueue_scripts', 'king_addons_enqueue_frontend_fixes_css', 99);
209 // Ensure the stylesheet is also loaded in Elementor's preview iframe inside the editor.
210 add_action('elementor/frontend/after_enqueue_styles', 'king_addons_enqueue_frontend_fixes_css', 99);
211 add_action('elementor/preview/enqueue_styles', 'king_addons_enqueue_frontend_fixes_css', 99);
212 }
213
214 /**
215 * Hides spaming notices from another plugins on the plugin settings page
216 *
217 * @return void
218 * @since 1.0.0
219 * @access public
220 */
221 if (!function_exists('king_addons_hideAnotherNotices')) {
222 /** @noinspection PhpMissingReturnTypeInspection */
223 function king_addons_hideAnotherNotices()
224 {
225 // Exclude the account page from notice hiding.
226 // URL: /wp-admin/admin.php?page=king-addons-account
227 if (isset($_GET['page']) && $_GET['page'] === 'king-addons-account') {
228 return;
229 }
230
231 $screen = function_exists('get_current_screen') ? get_current_screen() : null;
232 if (!$screen || empty($screen->id)) {
233 return;
234 }
235
236 $current_screen = (string) $screen->id;
237
238 // Legacy explicit screens that do not follow the generic prefixes.
239 $legacy_screens = [
240 'edit-king-addons-el-hf',
241 'edit-king-addons-fb-sub',
242 'header-footer_page_king-addons-el-hf-settings',
243 ];
244
245 $is_king_addons_screen = (strpos($current_screen, 'king-addons_') === 0)
246 || (strpos($current_screen, 'toplevel_page_king-addons') === 0)
247 || in_array($current_screen, $legacy_screens, true);
248
249 if ($is_king_addons_screen) {
250 // Remove all notices
251 remove_all_actions('user_admin_notices');
252 remove_all_actions('admin_notices');
253 }
254 }
255
256 add_action('in_admin_header', 'king_addons_hideAnotherNotices', 99);
257 }
258
259 /**
260 * Custom admin footer text on King Addons pages
261 * Shows rating request similar to WooCommerce
262 *
263 * @param string $footer_text Default footer text.
264 * @return string Modified footer text.
265 * @since 51.2.0
266 */
267 if (!function_exists('king_addons_admin_footer_text')) {
268 function king_addons_admin_footer_text($footer_text)
269 {
270 if (!current_user_can('manage_options')) {
271 return $footer_text;
272 }
273
274 $screen = function_exists('get_current_screen') ? get_current_screen() : null;
275 if (!$screen || empty($screen->id)) {
276 return $footer_text;
277 }
278
279 $current_screen = (string) $screen->id;
280
281 // Check if we're on a King Addons admin page
282 $legacy_screens = [
283 'edit-king-addons-el-hf',
284 'edit-king-addons-fb-sub',
285 'header-footer_page_king-addons-el-hf-settings',
286 ];
287
288 $is_king_addons_screen = (strpos($current_screen, 'king-addons_') === 0)
289 || (strpos($current_screen, 'toplevel_page_king-addons') === 0)
290 || in_array($current_screen, $legacy_screens, true);
291
292 if (!$is_king_addons_screen) {
293 return $footer_text;
294 }
295
296 // Check if user has already rated
297 if (!get_option('king_addons_admin_footer_text_rated')) {
298 $footer_text = sprintf(
299 /* translators: 1: King Addons 2: five stars */
300 __('If you like %1$s please leave us a %2$s rating. A huge thanks in advance!', 'king-addons'),
301 sprintf('<strong>%s</strong>', esc_html__('King Addons', 'king-addons')),
302 '<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>'
303 );
304 } else {
305 $footer_text = __('Thank you for using King Addons!', 'king-addons');
306 }
307
308 return '<span id="footer-thankyou">' . $footer_text . '</span>';
309 }
310
311 add_filter('admin_footer_text', 'king_addons_admin_footer_text', 1);
312 }
313
314 /**
315 * Enqueue script for rating link click handler
316 *
317 * @return void
318 * @since 51.2.0
319 */
320 if (!function_exists('king_addons_rating_script')) {
321 function king_addons_rating_script()
322 {
323 if (!current_user_can('manage_options')) {
324 return;
325 }
326
327 // Only on King Addons pages and only if not already rated
328 $screen = function_exists('get_current_screen') ? get_current_screen() : null;
329 if (!$screen || empty($screen->id)) {
330 return;
331 }
332
333 $current_screen = (string) $screen->id;
334
335 $legacy_screens = [
336 'edit-king-addons-el-hf',
337 'edit-king-addons-fb-sub',
338 'header-footer_page_king-addons-el-hf-settings',
339 ];
340
341 $is_king_addons_screen = (strpos($current_screen, 'king-addons_') === 0)
342 || (strpos($current_screen, 'toplevel_page_king-addons') === 0)
343 || in_array($current_screen, $legacy_screens, true);
344
345 if (!$is_king_addons_screen || get_option('king_addons_admin_footer_text_rated')) {
346 return;
347 }
348
349 $script = "
350 (function() {
351 'use strict';
352 var ratingLink = document.querySelector('a.king-addons-rating-link');
353 if (ratingLink) {
354 ratingLink.addEventListener('click', function(e) {
355 var link = e.currentTarget;
356 var formData = new FormData();
357 formData.append('action', 'king_addons_rated');
358 formData.append('nonce', '" . esc_js(wp_create_nonce('king_addons_rated')) . "');
359
360 fetch('" . esc_js(admin_url('admin-ajax.php')) . "', {
361 method: 'POST',
362 body: formData,
363 credentials: 'same-origin'
364 });
365
366 var parent = link.parentElement;
367 if (parent) {
368 parent.textContent = link.getAttribute('data-rated');
369 }
370 });
371 }
372 })();
373 ";
374
375 $handle = 'king-addons-admin-footer-rating';
376 wp_register_script($handle, '', [], KING_ADDONS_VERSION, true);
377 wp_enqueue_script($handle);
378 wp_add_inline_script($handle, $script);
379 }
380
381 add_action('admin_enqueue_scripts', 'king_addons_rating_script');
382 }
383
384 /**
385 * AJAX handler for saving rated status
386 *
387 * @return void
388 * @since 51.2.0
389 */
390 if (!function_exists('king_addons_rated_callback')) {
391 function king_addons_rated_callback()
392 {
393 if (!current_user_can('manage_options')) {
394 wp_die(-1, 403);
395 }
396
397 check_ajax_referer('king_addons_rated', 'nonce');
398
399 update_option('king_addons_admin_footer_text_rated', 1);
400 wp_die();
401 }
402
403 add_action('wp_ajax_king_addons_rated', 'king_addons_rated_callback');
404 }
405
406 /**
407 * Apply theme detection script to Account page
408 * Reads user's theme preference and applies ka-v3-dark class if needed
409 *
410 * @return void
411 * @since 51.2.0
412 */
413 if (!function_exists('king_addons_account_page_theme_script')) {
414 function king_addons_account_page_theme_script()
415 {
416 $screen = function_exists('get_current_screen') ? get_current_screen() : null;
417 if (!$screen || $screen->id !== 'king-addons_page_king-addons-account') {
418 return;
419 }
420
421 // Get user's theme preference
422 $theme_mode = get_user_meta(get_current_user_id(), 'king_addons_theme_mode', true);
423 $allowed_theme_modes = ['dark', 'light', 'auto'];
424 if (!in_array($theme_mode, $allowed_theme_modes, true)) {
425 $theme_mode = 'dark'; // Default to dark theme
426 }
427 ?>
428 <script>
429 (function() {
430 var themeMode = '<?php echo esc_js($theme_mode); ?>';
431 var root = document.documentElement;
432 var mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
433
434 // Prevent flash by disabling transitions early (body isn't available in admin_head).
435 root.classList.add('ka-no-transition');
436
437 function isDarkForMode(mode) {
438 if (mode === 'auto') {
439 return !!(mql && mql.matches);
440 }
441
442 return mode === 'dark';
443 }
444
445 function applyTheme(mode) {
446 var isDark = isDarkForMode(mode);
447
448 root.classList.toggle('ka-v3-dark', isDark);
449
450 // body may not exist yet (this script runs in <head>).
451 if (document.body) {
452 document.body.classList.toggle('ka-v3-dark', isDark);
453 }
454 }
455
456 applyTheme(themeMode);
457
458 // Once body exists, ensure it mirrors the html class.
459 document.addEventListener('DOMContentLoaded', function() {
460 applyTheme(themeMode);
461 if (document.body) {
462 document.body.classList.remove('ka-no-transition');
463 }
464 });
465
466 // Listen for system theme changes if in auto mode.
467 if (themeMode === 'auto' && mql) {
468 var onMqlChange = function() {
469 applyTheme('auto');
470 };
471
472 if (typeof mql.addEventListener === 'function') {
473 mql.addEventListener('change', onMqlChange);
474 } else if (typeof mql.addListener === 'function') {
475 mql.addListener(onMqlChange);
476 }
477 }
478
479 // Re-enable transitions.
480 setTimeout(function() {
481 root.classList.remove('ka-no-transition');
482 }, 50);
483 })();
484 </script>
485 <?php
486 }
487
488 add_action('admin_head', 'king_addons_account_page_theme_script', 1);
489 }
490
491 /**
492 * Apply styles to the plugin menu icon because some plugins broke the menu icon styles
493 *
494 * @return void
495 * @since 24.8.25
496 * @access public
497 */
498 if (!function_exists('king_addons_styleMenuIcon')) {
499 /** @noinspection PhpMissingReturnTypeInspection */
500 function king_addons_styleMenuIcon()
501 {
502 wp_enqueue_style('king-addons-plugin-style-menu-icon', plugin_dir_url(__FILE__) . 'includes/admin/css/menu-icon.css', '', KING_ADDONS_VERSION);
503 if (get_current_screen()->id == 'king-addons_page_king-addons-pricing') {
504 wp_enqueue_style('king-addons-plugin-style-pricing', plugin_dir_url(__FILE__) . 'includes/admin/css/pricing.css', '', KING_ADDONS_VERSION);
505 }
506 // Load Account page styles
507 if (get_current_screen()->id == 'king-addons_page_king-addons-account') {
508 wp_enqueue_style('king-addons-plugin-style-account', plugin_dir_url(__FILE__) . 'includes/admin/css/account.css', '', KING_ADDONS_VERSION);
509 }
510 }
511
512 add_action('admin_enqueue_scripts', 'king_addons_styleMenuIcon');
513 }
514
515 /**
516 * Add "Upgrade to Pro" link to the Plugins list table.
517 *
518 * @param array $links Existing plugin action links.
519 *
520 * @return array Modified action links with Upgrade link.
521 * @since 24.12.78
522 */
523 if (! function_exists('king_addons_add_action_links')) {
524 function king_addons_add_action_links(array $links): array
525 {
526 // Pricing page with UTM parameters for tracking.
527 $pro_url = 'https://kingaddons.com/pricing/?utm_source=kng-plugin-list&utm_medium=wp-plugins-page&utm_campaign=kng';
528
529 // Prepend the Upgrade link.
530 $links['go_pro'] = sprintf(
531 '<a href="%1$s" target="_blank" class="king-addons-plugins-gopro">%2$s</a>',
532 esc_url($pro_url),
533 esc_html__('Upgrade to Pro', 'king-addons')
534 );
535
536 return $links;
537 }
538
539 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
540 add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'king_addons_add_action_links');
541 add_filter('network_admin_plugin_action_links_' . plugin_basename(__FILE__), 'king_addons_add_action_links');
542 }
543 }
544