PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.14
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.14
51.1.87 51.1.86 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 All 41 releases
king-addons / includes / Core.php

Core.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.14, at includes/Core.php

1,230 lines 52.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Core class do all things at the start of the plugin
5 */
6
7 namespace King_Addons;
8
9 use Elementor\Plugin;
10 use Elementor\Widgets_Manager;
11 use Elementor\Controls_Manager;
12
13 if (!defined('ABSPATH')) {
14 exit; // Exit if accessed directly.
15 }
16
17 final class Core
18 {
19 /**
20 * Instance
21 *
22 * @var Core|null The single instance of the class.
23 */
24 private static ?Core $_instance = null;
25
26 /**
27 * Instance
28 *
29 * Ensures only one instance of the class is loaded or can be loaded.
30 *
31 * @return Core An instance of the class.
32 * @since 1.0.0
33 */
34 public static function instance(): Core
35 {
36 if (is_null(self::$_instance)) {
37 self::$_instance = new self();
38 }
39 return self::$_instance;
40 }
41
42 /**
43 * Constructor
44 *
45 * Perform some compatibility checks to make sure basic requirements are meet.
46 * If all compatibility checks pass, initialize the functionality.
47 *
48 * @since 1.0.0
49 */
50 public function __construct()
51 {
52 require_once(KING_ADDONS_PATH . 'includes/ModulesMap.php');
53 require_once(KING_ADDONS_PATH . 'includes/LibrariesMap.php');
54
55 if ($this->hasElementorCompatibility()) {
56
57 // Initial requirements check
58 require_once(KING_ADDONS_PATH . 'includes/helpers/Check_Requirements/Check_Requirements.php');
59
60 // Templates Catalog
61 if (KING_ADDONS_EXT_TEMPLATES_CATALOG) {
62 require_once(KING_ADDONS_PATH . 'includes/TemplatesMap.php');
63 require_once(KING_ADDONS_PATH . 'includes/extensions/Templates/CollectionsMap.php');
64 require_once(KING_ADDONS_PATH . 'includes/extensions/Templates/Templates.php');
65
66 // Template Catalog Button for Elementor Editor
67 require_once(KING_ADDONS_PATH . 'includes/extensions/Template_Catalog_Button/Template_Catalog_Button.php');
68 Template_Catalog_Button::instance();
69 }
70
71 // Sections Catalog
72 // if (KING_ADDONS_EXT_SECTIONS_CATALOG) {
73 // require_once(KING_ADDONS_PATH . 'includes/extensions/Sections_Catalog/Sections_Catalog.php');
74 // Sections_Catalog::instance();
75 // }
76
77 // Header & Footer Builder
78 if (KING_ADDONS_EXT_HEADER_FOOTER_BUILDER) {
79 require_once(KING_ADDONS_PATH . 'includes/extensions/Header_Footer_Builder/Header_Footer_Builder.php');
80 Header_Footer_Builder::instance();
81 }
82
83 // Popup Builder
84 if (KING_ADDONS_EXT_POPUP_BUILDER) {
85 require_once(KING_ADDONS_PATH . 'includes/extensions/Popup_Builder/Popup_Builder.php');
86 Popup_Builder::instance();
87 }
88
89 // Admin
90 require_once(KING_ADDONS_PATH . 'includes/Admin.php');
91
92 // Additional - Controls
93 require_once(KING_ADDONS_PATH . 'includes/controls/Ajax_Select2/Ajax_Select2.php');
94 require_once(KING_ADDONS_PATH . 'includes/controls/Ajax_Select2/Ajax_Select2_API.php');
95 require_once(KING_ADDONS_PATH . 'includes/controls/Animations/Animations.php');
96 require_once(KING_ADDONS_PATH . 'includes/controls/Animations/Button_Animations.php');
97
98 // Additional - Widgets
99 require_once(KING_ADDONS_PATH . 'includes/widgets/Search/Search_Ajax.php');
100 require_once(KING_ADDONS_PATH . 'includes/widgets/MailChimp/MailChimp_Ajax.php');
101
102 // Additional - Grids, Magazine Grid
103 require_once(KING_ADDONS_PATH . 'includes/helpers/Grid/Filter_Posts_Ajax.php');
104 require_once(KING_ADDONS_PATH . 'includes/helpers/Grid/Filter_WooCommerce_Products_Ajax.php');
105 require_once(KING_ADDONS_PATH . 'includes/helpers/Grid/Post_Likes_Ajax.php');
106
107 // Additional - Form Builder
108 if (KING_ADDONS_WGT_FORM_BUILDER) {
109 require_once(KING_ADDONS_PATH . 'includes/widgets/Form_Builder/helpers/Create_Submission.php');
110 require_once(KING_ADDONS_PATH . 'includes/widgets/Form_Builder/helpers/Send_Email.php');
111 require_once(KING_ADDONS_PATH . 'includes/widgets/Form_Builder/helpers/Send_Webhook.php');
112 require_once(KING_ADDONS_PATH . 'includes/widgets/Form_Builder/helpers/Subscribe_Mailchimp.php');
113 require_once(KING_ADDONS_PATH . 'includes/widgets/Form_Builder/helpers/Update_Action_Meta.php');
114 require_once(KING_ADDONS_PATH . 'includes/widgets/Form_Builder/helpers/Upload_Email_File.php');
115 require_once(KING_ADDONS_PATH . 'includes/widgets/Form_Builder/helpers/Verify_Google_Recaptcha.php');
116 require_once(KING_ADDONS_PATH . 'includes/widgets/Form_Builder/helpers/View_Submissions_Pro.php');
117 }
118
119 // ADDITIONAL CLASSES
120
121 // Alt Text Generator for Media Library
122 require_once(KING_ADDONS_PATH . 'includes/extensions/alt-text-generator/Alt_Text_Generator.php');
123 new Alt_Text_Generator();
124
125 // Dynamic Posts Grid AJAX Helper
126 require_once(KING_ADDONS_PATH . 'includes/helpers/Dynamic_Posts_Grid_Ajax.php');
127 new Dynamic_Posts_Grid_Ajax();
128
129 // Screenshot Generator
130 // require_once(KING_ADDONS_PATH . 'includes/extensions/Templates/screenshot-generator.php');
131 // require_once(KING_ADDONS_PATH . 'includes/extensions/Templates/screenshot-admin-page.php');
132 // new King_Addons\KingAddons\ScreenshotAdmin();
133
134 // END: ADDITIONAL CLASSES
135
136 self::enableWidgetsByDefault();
137
138 add_action('elementor/init', [$this, 'initElementor']);
139
140 add_action('elementor/elements/categories_registered', [$this, 'addWidgetCategory']);
141 add_action('elementor/controls/controls_registered', [$this, 'registerControls']);
142
143 self::enableFeatures();
144
145 // Load and register AJAX handlers for Login Register Form widget
146 require_once(KING_ADDONS_PATH . 'includes/widgets/Login_Register_Form/Login_Register_Form_Ajax.php');
147 require_once(KING_ADDONS_PATH . 'includes/widgets/Login_Register_Form/User_Profile_Fields.php');
148 require_once(KING_ADDONS_PATH . 'includes/widgets/Login_Register_Form/Email_Handler.php');
149 require_once(KING_ADDONS_PATH . 'includes/widgets/Login_Register_Form/Social_Login_Handler.php');
150 add_action('wp_ajax_nopriv_king_addons_user_login', ['King_Addons\Widgets\Login_Register_Form\Login_Register_Form_Ajax', 'handle_login_ajax']);
151 add_action('wp_ajax_king_addons_user_login', ['King_Addons\Widgets\Login_Register_Form\Login_Register_Form_Ajax', 'handle_login_ajax']);
152 add_action('wp_ajax_nopriv_king_addons_user_register', ['King_Addons\Widgets\Login_Register_Form\Login_Register_Form_Ajax', 'handle_register_ajax']);
153 add_action('wp_ajax_king_addons_user_register', ['King_Addons\Widgets\Login_Register_Form\Login_Register_Form_Ajax', 'handle_register_ajax']);
154 add_action('wp_ajax_nopriv_king_addons_user_lostpassword', ['King_Addons\Widgets\Login_Register_Form\Login_Register_Form_Ajax', 'handle_lostpassword_ajax']);
155 add_action('wp_ajax_king_addons_user_lostpassword', ['King_Addons\Widgets\Login_Register_Form\Login_Register_Form_Ajax', 'handle_lostpassword_ajax']);
156
157 // Initialize user profile fields
158 \King_Addons\Widgets\Login_Register_Form\User_Profile_Fields::init();
159
160 // Initialize social login handler
161 \King_Addons\Widgets\Login_Register_Form\Social_Login_Handler::init();
162
163 // Initialize Security Dashboard for admins
164 if (is_admin()) {
165 require_once(KING_ADDONS_PATH . 'includes/widgets/Login_Register_Form/Security_Dashboard.php');
166 \King_Addons\Widgets\Login_Register_Form\Security_Dashboard::init();
167 }
168
169 new Admin();
170
171 add_action('wp_enqueue_scripts', [$this, 'enqueueFrontendStyles']);
172 add_action('wp_enqueue_scripts', [$this, 'enqueueLightboxDynamicStyles']);
173
174 // Notice - Upgrade Suggestion
175 if (!king_addons_freemius()->can_use_premium_code__premium_only()) {
176 add_action('wp_ajax_king_addons_premium_notice_dismiss', [$this, 'king_addons_premium_notice_dismiss_callback']);
177 add_action('admin_notices', [$this, 'showNoticeUpgrade']);
178 }
179
180 // Conditionally enqueue AI text-field enhancement script and styles in Elementor editor
181 $ai_options = get_option('king_addons_ai_options', []);
182 $enable_ai_text_buttons = isset($ai_options['enable_ai_buttons']) ? (bool) $ai_options['enable_ai_buttons'] : true;
183 if ( $enable_ai_text_buttons ) {
184 // Enqueue AI text-field enhancement script
185 add_action('elementor/editor/after_enqueue_scripts', [ $this, 'enqueueAiFieldScript' ]);
186 // Enqueue styles for AI prompt UI
187 add_action('elementor/editor/after_enqueue_styles', [ $this, 'enqueueAiFieldStyles' ]);
188 // Enqueue AI page translator script
189 add_action('elementor/editor/after_enqueue_scripts', [ $this, 'enqueueAiTranslatorScript' ]);
190 }
191
192 $enable_ai_image_generation_button = isset($ai_options['enable_ai_image_generation_button']) ? (bool) $ai_options['enable_ai_image_generation_button'] : true;
193 if ( $enable_ai_image_generation_button ) {
194 add_action('elementor/editor/after_enqueue_scripts', [ $this, 'enqueueAiImageGenerationScript' ]);
195 // Enqueue styles for AI Image Generation controls
196 add_action('elementor/editor/after_enqueue_styles', [ $this, 'enqueueAiImageFieldStyles' ]);
197 }
198
199 }
200 }
201
202 function king_addons_premium_notice_dismiss_callback()
203 {
204 // Check user capabilities
205 if (!current_user_can('manage_options')) {
206 wp_die();
207 }
208 $user_id = get_current_user_id();
209 // Save the current time as the last dismissal time for the premium notice
210 update_user_meta($user_id, 'king_addons_premium_notice_dismissed_time', time());
211 wp_die(); // End AJAX request
212 }
213
214 function showNoticeUpgrade()
215 {
216 // Check user capabilities; show notice only to administrators as an example
217 if (!current_user_can('manage_options')) {
218 return;
219 }
220
221 $user_id = get_current_user_id();
222 $now = time();
223 // Retrieve the last time the premium notice was dismissed by the user
224 $last_dismissed = get_user_meta($user_id, 'king_addons_premium_notice_dismissed_time', true);
225
226 // If the premium notice was dismissed less than a week ago (604800 seconds), do not show it
227 if ($last_dismissed && ($now - $last_dismissed) < 604800) {
228 // if ($last_dismissed && ($now - $last_dismissed) < 60) {
229 return;
230 }
231 ?>
232 <div class="king-addons-upgrade-notice notice notice-info is-dismissible"
233 style="border-left: 4px solid #FF4040;padding: 10px 15px;">
234 <p style="font-size: 15px; margin:0; display: flex; align-items: center;">
235 <span>Unlock <strong style="font-weight: 700;">650+</strong> premium templates and <strong
236 style="font-weight: 700;">200+</strong> advanced features for only $<strong
237 style="font-weight: 700;">4.99</strong>/month. Upgrade now and boost your website's performance!</span>
238 </p>
239 <p style="font-size: 14px; opacity: 0.6;">Trusted by 20,000+ users</p>
240 <p style="display: flex;">
241 <a style="font-size: 14px;padding: 4px 22px;display: flex;align-items: center;background-image: linear-gradient(120deg, #A20BD8 0%, #FF4040 100%);border: none;"
242 href="https://kingaddons.com/pricing?utm_source=kng-notice-offer&utm_medium=plugin&utm_campaign=kng"
243 class="button button-primary"><img style="margin-right: 7px;width: 15px;height: 15px;"
244 src="<?php echo esc_url(KING_ADDONS_URL) . 'includes/admin/img/icon-for-admin.svg'; ?>"
245 alt="<?php echo esc_html__('Upgrade Now', 'king-addons'); ?>">Upgrade Now</a>
246 <a style="margin-left: 20px;display: flex;align-items: center;"
247 href="https://kingaddons.com/pricing?utm_source=kng-notice-offer&utm_medium=plugin&utm_campaign=kng"
248 class="link">Learn More</a>
249 </p>
250 </div>
251 <script>
252 (function($) {
253 // Wait for the document to be ready
254 $(document).ready(function() {
255 // Attach click handler to the dismiss button of the premium notice
256 $('.king-addons-upgrade-notice.notice.is-dismissible').on('click', '.notice-dismiss', function() {
257 $.post(ajaxurl, {
258 action: 'king_addons_premium_notice_dismiss'
259 });
260 });
261 });
262 })(jQuery);
263 </script>
264 <?php
265 }
266
267 function enqueueFrontendStyles()
268 {
269 /**
270 * It fixes the default Elementor SVG icon rendering feature (Settings -> Features -> Inline Font Icons)
271 * because sometimes Elementor still renders Font Awesome icons but doesn't load the corresponding Font Awesome styles.
272 * Therefore, we have to enqueue the styles.
273 */
274 wp_enqueue_style(
275 'font-awesome-5-all',
276 ELEMENTOR_ASSETS_URL . 'lib/font-awesome/css/all' . (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min') . '.css',
277 false,
278 KING_ADDONS_VERSION
279 );
280 }
281
282 function hasElementorCompatibility(): bool
283 {
284 // Check if Elementor installed and activated
285 if (!did_action('elementor/loaded')) {
286 add_action('admin_notices', [$this, 'showAdminNotice_ElementorRequired']);
287 return false;
288 }
289
290 // Check for required Elementor version
291 if (!version_compare(ELEMENTOR_VERSION, '3.19.0', '>=')) {
292 add_action('admin_notices', [$this, 'showAdminNotice_ElementorMinimumVersion']);
293 return false;
294 }
295
296 return true;
297 }
298
299 function showAdminNotice_ElementorRequired(): void
300 {
301 $screen = get_current_screen();
302 if (isset($screen->parent_file) && 'plugins.php' === $screen->parent_file && 'update' === $screen->id) {
303 return;
304 }
305
306 if (isset(get_plugins()['elementor/elementor.php'])) {
307 if (!current_user_can('activate_plugins') || is_plugin_active('elementor/elementor.php')) {
308 return;
309 }
310 $plugin = 'elementor/elementor.php';
311 $activation_url = wp_nonce_url('plugins.php?action=activate&amp;plugin=' . $plugin . '&amp;plugin_status=all&amp;paged=1&amp;s', 'activate-plugin_' . $plugin);
312 $message = '<div class="error"><p>' . esc_html__('King Addons plugin is not working because you need to activate the Elementor plugin.', 'king-addons') . '</p>';
313 /** @noinspection HtmlUnknownTarget */
314 $message .= '<p>' . sprintf('<a href="%s" class="button-primary">%s</a>', $activation_url, esc_html__('Activate Elementor now', 'king-addons')) . '</p></div>';
315 } else {
316 if (!current_user_can('install_plugins')) {
317 return;
318 }
319 $install_url = wp_nonce_url(self_admin_url('update.php?action=install-plugin&plugin=elementor'), 'install-plugin_elementor');
320 $message = '<div class="error"><p>' . esc_html__('King Addons plugin is not working because you need to install the Elementor plugin.', 'king-addons') . '</p>';
321 /** @noinspection HtmlUnknownTarget */
322 $message .= '<p>' . sprintf('<a href="%s" class="button-primary">%s</a>', $install_url, esc_html__('Install Elementor now', 'king-addons')) . '</p></div>';
323 }
324 echo $message;
325 }
326
327 function showAdminNotice_ElementorMinimumVersion(): void
328 {
329 $message = sprintf(
330 /* translators: 1: Plugin name 2: Elementor 3: Required Elementor version */
331 esc_html__('%1$s plugin requires %2$s plugin version %3$s or greater.', 'king-addons'),
332 esc_html__('King Addons', 'king-addons'),
333 esc_html__('Elementor', 'king-addons'),
334 '3.19.0'
335 );
336 echo '<div class="notice notice-error"><p>' . esc_html($message) . '</p></div>';
337 }
338
339 public function initElementor(): void
340 {
341 add_action('elementor/widgets/register', [$this, 'registerWidgets']);
342 add_action('elementor/editor/after_enqueue_styles', [$this, 'enqueueEditorStyles']);
343 add_action('elementor/editor/after_enqueue_scripts', [$this, 'enqueueEditorScripts']);
344 }
345
346 function addWidgetCategory(): void
347 {
348 Plugin::instance()->elements_manager->add_category(
349 'king-addons',
350 [
351 'title' => esc_html__('King Addons', 'king-addons'),
352 'icon' => 'fa fa-plug'
353 ]
354 );
355 }
356
357 /**
358 * Registers Elementor widgets with a mechanism to skip (and remember) broken widgets
359 * that caused a fatal error previously, and try them again if the plugin version is updated.
360 *
361 * @param Widgets_Manager $widgets_manager
362 * @return void
363 */
364 function registerWidgets(Widgets_Manager $widgets_manager): void
365 {
366 // Used to track which widget is currently being loaded when a fatal error occurs
367 static $currentlyLoadingWidgetId = null;
368
369 $currentPluginVersion = KING_ADDONS_VERSION;
370
371 // Get plugin options to check if a widget is enabled
372 $options = get_option('king_addons_options');
373
374 /**
375 * Retrieve the array of broken widgets from the WordPress options.
376 * The structure is expected to be something like:
377 *
378 * 'widget_id' => [
379 * 'version' => '1.2.0',
380 * 'error' => 'Some fatal error message'
381 * ],
382 * ...
383 *
384 */
385 $brokenWidgets = get_option('king_addons_broken_widgets', []);
386
387 /**
388 * STEP 1: Clear out any "broken widgets" where the stored version is
389 * less than the current plugin version. This gives them a second chance
390 * after an update, assuming the issue may have been fixed.
391 */
392 foreach ($brokenWidgets as $brokenId => $brokenData) {
393 if (
394 isset($brokenData['version'])
395 && version_compare($currentPluginVersion, $brokenData['version'], '>')
396 ) {
397 // If the plugin version is now higher, we remove the widget from the blacklist
398 unset($brokenWidgets[$brokenId]);
399 }
400 }
401
402 // Update the option after cleaning up
403 update_option('king_addons_broken_widgets', $brokenWidgets);
404
405 /**
406 * STEP 2: Use register_shutdown_function to detect any fatal errors (E_ERROR, E_PARSE, etc.)
407 * that might occur during the loading of a widget. If an error is detected, store that widget
408 * in the "broken" list with the current plugin version and the error message.
409 */
410 register_shutdown_function(function () use (&$currentlyLoadingWidgetId, $currentPluginVersion) {
411 $error = error_get_last();
412 if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
413 // If a fatal error occurred while loading a specific widget
414 if (!empty($currentlyLoadingWidgetId)) {
415 $brokenWidgetsLocal = get_option('king_addons_broken_widgets', []);
416 $brokenWidgetsLocal[$currentlyLoadingWidgetId] = [
417 'version' => $currentPluginVersion,
418 'error' => $error['message'] ?? ''
419 ];
420 update_option('king_addons_broken_widgets', $brokenWidgetsLocal);
421 }
422 }
423 });
424
425 /**
426 * STEP 3: Now we iterate through all widgets in our modules map and try to load them.
427 * If a widget is in the broken list, we skip it to avoid repeated fatal errors.
428 */
429 foreach (ModulesMap::getModulesMapArray()['widgets'] as $widget_id => $widget) {
430 // Check if the widget is enabled in the options
431 if (!isset($options[$widget_id]) || $options[$widget_id] !== 'enabled') {
432 continue;
433 }
434
435 // If this widget is listed as broken, skip it
436 if (array_key_exists($widget_id, $brokenWidgets)) {
437 // Log something here if needed:
438 // error_log("Skipping widget {$widget_id}, it previously caused a fatal error.");
439 continue;
440 }
441
442 // Track which widget we're loading
443 $currentlyLoadingWidgetId = $widget_id;
444
445 // Include the base widget class
446 $widget_class = $widget['php-class'];
447 $path_widget_class = "King_Addons\\" . $widget_class;
448 require_once(KING_ADDONS_PATH . 'includes/widgets/' . $widget_class . '/' . $widget_class . '.php');
449
450 // Check if we can load the Pro version
451 if (
452 function_exists('king_addons_freemius')
453 && king_addons_freemius()->can_use_premium_code__premium_only()
454 && defined('KING_ADDONS_PRO_PATH')
455 ) {
456 if (!empty($widget['has-pro'])) {
457 $pro_file_path = KING_ADDONS_PRO_PATH . 'includes/widgets/' . $widget_class . '_Pro/' . $widget_class . '_Pro.php';
458
459 if (file_exists($pro_file_path)) {
460 require_once($pro_file_path);
461 $path_widget_class_pro = "King_Addons\\" . $widget_class . '_Pro';
462 $widgets_manager->register(new $path_widget_class_pro);
463 } else {
464 // If Pro file doesn't exist, register the base widget
465 $widgets_manager->register(new $path_widget_class);
466 }
467 } else {
468 // No 'has-pro', register the base widget
469 $widgets_manager->register(new $path_widget_class);
470 }
471 } else {
472 // No Freemius Pro available, register the base widget
473 $widgets_manager->register(new $path_widget_class);
474 }
475
476 // Clear the tracking variable after successful load
477 $currentlyLoadingWidgetId = null;
478 }
479 }
480
481 function enableWidgetsByDefault(): void
482 {
483 $options = get_option('king_addons_options');
484
485 foreach (ModulesMap::getModulesMapArray()['widgets'] as $widget_id => $widget) {
486
487 if (!($options[$widget_id] ?? null)) {
488 $options[$widget_id] = 'enabled';
489 update_option('king_addons_options', $options);
490 }
491 }
492 }
493
494 function enableFeatures(): void
495 {
496 $options = get_option('king_addons_options');
497
498 foreach (ModulesMap::getModulesMapArray()['features'] as $feature_id => $feature) {
499
500 if (!($options[$feature_id] ?? null)) {
501 $options[$feature_id] = 'enabled';
502 update_option('king_addons_options', $options);
503 }
504
505 if ($options[$feature_id] === 'enabled') {
506 $feature_class = $feature['php-class'];
507 $path_feature_class = "King_Addons\\" . $feature_class;
508 require_once(KING_ADDONS_PATH . 'includes/features/' . $feature_class . '/' . $feature_class . '.php');
509 new $path_feature_class;
510 }
511 }
512 }
513
514 public function registerControls(Controls_Manager $controls_manager): void
515 {
516 $controls_manager->register(new AJAX_Select2\Ajax_Select2());
517 $controls_manager->register(new Animations\Animations());
518 $controls_manager->register(new Animations\Animations_Alternative());
519 $controls_manager->register(new Button_Animations\Button_Animations());
520 }
521
522 function enqueueEditorStyles(): void
523 {
524 wp_enqueue_style(KING_ADDONS_ASSETS_UNIQUE_KEY . '-elementor-editor', KING_ADDONS_URL . 'includes/admin/css/elementor-editor.css', '', KING_ADDONS_VERSION);
525 }
526
527 function enqueueEditorScripts(): void
528 {
529 wp_enqueue_script(KING_ADDONS_ASSETS_UNIQUE_KEY . '-elementor-editor', KING_ADDONS_URL . 'includes/admin/js/elementor-editor.js', '', KING_ADDONS_VERSION);
530
531 // Localize script with PRO status
532 wp_localize_script(KING_ADDONS_ASSETS_UNIQUE_KEY . '-elementor-editor', 'kingAddonsEditor', [
533 'isPro' => king_addons_freemius()->can_use_premium_code__premium_only() ? true : false
534 ]);
535
536 wp_enqueue_script(KING_ADDONS_ASSETS_UNIQUE_KEY . '-data-table-export', KING_ADDONS_URL . 'includes/widgets/Data_Table/preview-handler.js', '', KING_ADDONS_VERSION);
537
538 if (KING_ADDONS_WGT_FORM_BUILDER) {
539 wp_enqueue_script(KING_ADDONS_ASSETS_UNIQUE_KEY . '-form-builder-editor-handler', KING_ADDONS_URL . 'includes/widgets/Form_Builder/editor-handler.js', '', KING_ADDONS_VERSION);
540 }
541 }
542
543 public static function renderProFeaturesSection($module, $section, $type, $widget_name, $features): void
544 {
545 if (king_addons_freemius()->can_use_premium_code__premium_only()) {
546 return;
547 }
548
549 $module->start_controls_section(
550 'king_addons_pro_features_section',
551 [
552 'label' => KING_ADDONS_ELEMENTOR_ICON_PRO . '<span class="king-addons-pro-features-heading">' . esc_html__('Pro Features', 'king-addons') . '</span>',
553 'tab' => $section ?: null,
554 ]
555 );
556
557 $list_html = '<ul>' . implode('', array_map(fn($feature) => "<li>$feature</li>", $features)) . '</ul>';
558
559 $module->add_control(
560 'king_addons_pro_features_list',
561 [
562 'type' => $type,
563 'raw' => $list_html . '<a class="king-addons-pro-features-cta-btn" href="https://kingaddons.com/pricing/?utm_source=kng-module-' . $widget_name . '-upgrade-pro&utm_medium=plugin&utm_campaign=kng" target="_blank">' . esc_html__('Upgrade Now', 'king-addons') . '</a>',
564 'content_classes' => 'king-addons-pro-features-list',
565 ]
566 );
567
568 $module->end_controls_section();
569 }
570
571 public static function renderUpgradeProNotice($module, $controls_manager, $widget_name, $option, $condition = []): void
572 {
573 if (king_addons_freemius()->can_use_premium_code__premium_only()) {
574 return;
575 }
576
577 $module->add_control(
578 $option . '_pro_notice_',
579 [
580 'raw' => 'Upgrade to the <strong><a href="https://kingaddons.com/pricing/?utm_source=kng-module-' . $widget_name . '-settings-upgrade-pro&utm_medium=plugin&utm_campaign=kng" target="_blank">Pro version</a></strong> now<br> and unlock this feature!',
581 'type' => $controls_manager,
582 'content_classes' => 'king-addons-pro-notice',
583 'condition' => [
584 $option => $condition,
585 ]
586 ]
587 );
588 }
589
590 public static function getCustomTypes($query, $exclude_defaults = true): array
591 {
592 $custom_types = $query === 'tax'
593 ? get_taxonomies(['show_in_nav_menus' => true], 'objects')
594 : get_post_types(['show_in_nav_menus' => true], 'objects');
595
596 return array_filter(
597 array_map(fn($type) => $type->label, $custom_types),
598 fn($label, $key) => !$exclude_defaults || !in_array($key, ['post', 'page', 'category', 'post_tag']),
599 ARRAY_FILTER_USE_BOTH
600 );
601 }
602
603 public static function getShareIcon($args = []): string
604 {
605 $args = wp_parse_args($args, [
606 'network' => '',
607 'url' => '',
608 'title' => '',
609 'text' => '',
610 'image' => '',
611 'show_whatsapp_title' => 'no',
612 'show_whatsapp_excerpt' => 'no',
613 'tooltip' => 'no',
614 'icons' => 'no',
615 'labels' => 'no',
616 'custom_label' => '',
617 ]);
618
619 $url = esc_url($args['url']);
620 $title = wp_strip_all_tags($args['title']);
621 $text = wp_strip_all_tags($args['text']);
622 $image = esc_url($args['image']);
623 $network = $args['network'];
624
625 $get_whatsapp_url = function ($a) {
626 if ('yes' === $a['show_whatsapp_title'] && 'yes' === $a['show_whatsapp_excerpt']) {
627 return 'https://api.whatsapp.com/send?text=*' . $a['title'] . '*%0a' . $a['text'] . '%0a' . $a['url'];
628 } elseif ('yes' === $a['show_whatsapp_title']) {
629 return 'https://api.whatsapp.com/send?text=*' . $a['title'] . '*%0a' . $a['url'];
630 } elseif ('yes' === $a['show_whatsapp_excerpt']) {
631 return 'https://api.whatsapp.com/send?text=*' . $a['text'] . '%0a' . $a['url'];
632 }
633 return 'https://api.whatsapp.com/send?text=' . $a['url'];
634 };
635
636 $networks_map = [
637 'facebook-f' => [
638 'url' => "https://www.facebook.com/sharer.php?u=$url",
639 'title' => esc_html__('Facebook', 'king-addons'),
640 'icon' => 'fab',
641 ],
642 'x-twitter' => [
643 'url' => "https://twitter.com/intent/tweet?url=$url",
644 'title' => esc_html__('X (Twitter)', 'king-addons'),
645 'icon' => 'fab',
646 ],
647 'linkedin-in' => [
648 'url' => "https://www.linkedin.com/shareArticle?mini=true&url=$url&title=$title&summary=$text&source=$url",
649 'title' => esc_html__('LinkedIn', 'king-addons'),
650 'icon' => 'fab',
651 ],
652 'pinterest-p' => [
653 'url' => "https://www.pinterest.com/pin/create/button/?url=$url&media=$image",
654 'title' => esc_html__('Pinterest', 'king-addons'),
655 'icon' => 'fab',
656 ],
657 'reddit' => [
658 'url' => "https://reddit.com/submit?url=$url&title=$title",
659 'title' => esc_html__('Reddit', 'king-addons'),
660 'icon' => 'fab',
661 ],
662 'tumblr' => [
663 'url' => "https://tumblr.com/share/link?url=$url",
664 'title' => esc_html__('Tumblr', 'king-addons'),
665 'icon' => 'fab',
666 ],
667 'digg' => [
668 'url' => "https://digg.com/submit?url=$url",
669 'title' => esc_html__('Digg', 'king-addons'),
670 'icon' => 'fab',
671 ],
672 'xing' => [
673 'url' => "https://www.xing.com/app/user?op=share&url=$url",
674 'title' => esc_html__('Xing', 'king-addons'),
675 'icon' => 'fab',
676 ],
677 'vk' => [
678 'url' => "https://vk.ru/share.php?url=$url&title=$title&description=" . wp_trim_words($text, 250) . "&image=$image/",
679 'title' => esc_html__('VK', 'king-addons'),
680 'icon' => 'fab',
681 ],
682 'odnoklassniki' => [
683 'url' => "https://connect.ok.ru/offer?url=$url",
684 'title' => esc_html__('OK', 'king-addons'),
685 'icon' => 'fab',
686 ],
687 'get-pocket' => [
688 'url' => "https://getpocket.com/edit?url=$url",
689 'title' => esc_html__('Pocket', 'king-addons'),
690 'icon' => 'fab',
691 ],
692 'skype' => [
693 'url' => "https://web.skype.com/share?url=$url",
694 'title' => esc_html__('Skype', 'king-addons'),
695 'icon' => 'fab',
696 ],
697 'whatsapp' => [
698 'url' => $get_whatsapp_url($args),
699 'title' => esc_html__('WhatsApp', 'king-addons'),
700 'icon' => 'fab',
701 ],
702 'telegram' => [
703 'url' => "https://telegram.me/share/url?url=$url&text=$text",
704 'title' => esc_html__('Telegram', 'king-addons'),
705 'icon' => 'fab',
706 ],
707 'envelope' => [
708 'url' => "mailto:?subject=$title&body=$url",
709 'title' => esc_html__('Email', 'king-addons'),
710 'icon' => 'fas',
711 ],
712 'print' => [
713 'url' => "javascript:window.print()",
714 'title' => esc_html__('Print', 'king-addons'),
715 'icon' => 'fas',
716 ],
717 ];
718
719 if (!isset($networks_map[$network])) {
720 return '';
721 }
722
723 $share_url = $networks_map[$network]['url'];
724 $network_title = $networks_map[$network]['title'];
725 $icon_category = $networks_map[$network]['icon'];
726
727 $output = '<a href="' . esc_url($share_url) . '" class="king-addons-share-icon king-addons-share-' . esc_attr($network) . '" target="_blank">';
728
729 if ('yes' === $args['tooltip']) {
730 $output .= '<span class="king-addons-share-tooltip king-addons-tooltip">' . esc_html($network_title) . '</span>';
731 }
732
733 if ('yes' === $args['icons']) {
734 $output .= '<i class="' . esc_attr($icon_category) . ' fa-' . esc_attr($network) . '"></i>';
735 }
736
737 if ('yes' === $args['labels']) {
738 $label = !empty($args['custom_label']) ? $args['custom_label'] : $network_title;
739 $output .= '<span class="king-addons-share-label">' . esc_html($label) . '</span>';
740 }
741
742 $output .= '</a>';
743
744 return $output;
745 }
746
747 public static function validateHTMLTags($setting, $default, $tags_whitelist)
748 {
749 $value = $setting;
750 if (!in_array($value, $tags_whitelist)) {
751 $value = $default;
752 }
753 return $value;
754 }
755
756 public static function getIcon($icon, $dir)
757 {
758 if (empty($icon) || strpos($icon, 'fa-') === false) {
759 return '';
760 }
761
762 $dir = $dir ? "-$dir" : '';
763 return wp_kses(
764 '<i class="' . esc_attr($icon . $dir) . '"></i>',
765 ['i' => ['class' => []]]
766 );
767 }
768
769 public static function getPluginName()
770 {
771 return 'King Addons';
772 }
773
774 public static function getAnimationTimings(): array
775 {
776 /** @noinspection DuplicatedCode */
777 $timings = [
778 'ease-default' => 'Default',
779 'linear' => 'Linear',
780 'ease-in' => 'Ease In',
781 'ease-out' => 'Ease Out',
782 'pro-eio' => 'EI Out (Pro)',
783 'pro-eiqd' => 'EI Quad (Pro)',
784 'pro-eicb' => 'EI Cubic (Pro)',
785 'pro-eiqrt' => 'EI Quart (Pro)',
786 'pro-eiqnt' => 'EI Quint (Pro)',
787 'pro-eisn' => 'EI Sine (Pro)',
788 'pro-eiex' => 'EI Expo (Pro)',
789 'pro-eicr' => 'EI Circ (Pro)',
790 'pro-eibk' => 'EI Back (Pro)',
791 'pro-eoqd' => 'EO Quad (Pro)',
792 'pro-eocb' => 'EO Cubic (Pro)',
793 'pro-eoqrt' => 'EO Quart (Pro)',
794 'pro-eoqnt' => 'EO Quint (Pro)',
795 'pro-eosn' => 'EO Sine (Pro)',
796 'pro-eoex' => 'EO Expo (Pro)',
797 'pro-eocr' => 'EO Circ (Pro)',
798 'pro-eobk' => 'EO Back (Pro)',
799 'pro-eioqd' => 'EIO Quad (Pro)',
800 'pro-eiocb' => 'EIO Cubic (Pro)',
801 'pro-eioqrt' => 'EIO Quart (Pro)',
802 'pro-eioqnt' => 'EIO Quint (Pro)',
803 'pro-eiosn' => 'EIO Sine (Pro)',
804 'pro-eioex' => 'EIO Expo (Pro)',
805 'pro-eiocr' => 'EIO Circ (Pro)',
806 'pro-eiobk' => 'EIO Back (Pro)',
807 ];
808
809 if (king_addons_freemius()->can_use_premium_code__premium_only()) {
810 /** @noinspection DuplicatedCode */
811 $timings = [
812 'ease-default' => 'Default',
813 'linear' => 'Linear',
814 'ease-in' => 'Ease In',
815 'ease-out' => 'Ease Out',
816 'ease-in-out' => 'Ease In Out',
817 'ease-in-quad' => 'Ease In Quad',
818 'ease-in-cubic' => 'Ease In Cubic',
819 'ease-in-quart' => 'Ease In Quart',
820 'ease-in-quint' => 'Ease In Quint',
821 'ease-in-sine' => 'Ease In Sine',
822 'ease-in-expo' => 'Ease In Expo',
823 'ease-in-circ' => 'Ease In Circ',
824 'ease-in-back' => 'Ease In Back',
825 'ease-out-quad' => 'Ease Out Quad',
826 'ease-out-cubic' => 'Ease Out Cubic',
827 'ease-out-quart' => 'Ease Out Quart',
828 'ease-out-quint' => 'Ease Out Quint',
829 'ease-out-sine' => 'Ease Out Sine',
830 'ease-out-expo' => 'Ease Out Expo',
831 'ease-out-circ' => 'Ease Out Circ',
832 'ease-out-back' => 'Ease Out Back',
833 'ease-in-out-quad' => 'Ease In Out Quad',
834 'ease-in-out-cubic' => 'Ease In Out Cubic',
835 'ease-in-out-quart' => 'Ease In Out Quart',
836 'ease-in-out-quint' => 'Ease In Out Quint',
837 'ease-in-out-sine' => 'Ease In Out Sine',
838 'ease-in-out-expo' => 'Ease In Out Expo',
839 'ease-in-out-circ' => 'Ease In Out Circ',
840 'ease-in-out-back' => 'Ease In Out Back',
841 ];
842 }
843
844 return $timings;
845 }
846
847 public static function getAnimationTimingsConditionsPro()
848 {
849 return [
850 'pro-eibk',
851 'pro-eicb',
852 'pro-eicr',
853 'pro-eiex',
854 'pro-eio',
855 'pro-eiobk',
856 'pro-eiocb',
857 'pro-eiocr',
858 'pro-eioex',
859 'pro-eioqd',
860 'pro-eioqnt',
861 'pro-eioqrt',
862 'pro-eiosn',
863 'pro-eiqd',
864 'pro-eiqnt',
865 'pro-eiqrt',
866 'pro-eisn',
867 'pro-eobk',
868 'pro-eocb',
869 'pro-eocr',
870 'pro-eoex',
871 'pro-eoqd',
872 'pro-eoqnt',
873 'pro-eoqrt',
874 'pro-eosn',
875 ];
876 }
877
878 public static function isBlogArchive()
879 {
880 return (
881 is_home()
882 && '0' === get_option('page_on_front')
883 && '0' === get_option('page_for_posts')
884 ) || (
885 intval(get_option('page_for_posts')) === get_queried_object_id()
886 && !is_404()
887 );
888 }
889
890 public static function filterOembedResults($html)
891 {
892 preg_match('/src="([^"]+)"/', $html, $m);
893 return $m[1] . '&auto_play=true';
894 }
895
896 public static function getWooCommerceTaxonomies()
897 {
898 $filtered = array_filter(get_object_taxonomies('product'), fn($t) => get_taxonomy($t)->show_ui);
899 return array_combine($filtered, array_map(fn($t) => get_taxonomy($t)->label, $filtered));
900 }
901
902 public static function getCustomMetaKeysTaxonomies()
903 {
904 $data = [];
905 $tax_types = Core::getCustomTypes('tax', false);
906
907 foreach ($tax_types as $taxonomy_slug => $post_type_name) {
908 $meta_keys = [];
909 foreach (get_terms($taxonomy_slug) as $tax) {
910 $keys = array_keys(get_term_meta($tax->term_id));
911 $keys = array_filter($keys, fn($key) => '_' !== $key[0]);
912 $meta_keys = array_merge($meta_keys, $keys);
913 }
914 $data[$taxonomy_slug] = array_unique($meta_keys);
915 }
916
917
918 $merged = call_user_func_array('array_merge', array_values($data));
919 $merged_meta_keys = array_values(array_unique($merged));
920
921 $options = array_combine($merged_meta_keys, $merged_meta_keys);
922
923 return [$data, $options];
924 }
925
926 public static function getMailchimpLists()
927 {
928 $api_key = get_option('king_addons_mailchimp_api_key', '');
929 $mailchimp_list = ['def' => esc_html__('Select List', 'king-addons')];
930
931 if (!$api_key) {
932 return $mailchimp_list;
933 }
934
935 $url = 'https://' . explode('-', $api_key)[1] . '.api.mailchimp.com/3.0/lists/';
936 $response = wp_remote_get($url, [
937 'headers' => ['Authorization' => 'Basic ' . base64_encode('user:' . $api_key)]
938 ]);
939
940 $body = json_decode(wp_remote_retrieve_body($response));
941 if (!empty($body->lists)) {
942 foreach ($body->lists as $list) {
943 $mailchimp_list[$list->id] = $list->name . ' (' . $list->stats->member_count . ')';
944 }
945 }
946
947 return $mailchimp_list;
948 }
949
950 public static function getMailchimpGroups()
951 {
952 $apiKey = get_option('king_addons_mailchimp_api_key');
953 $domain = 'https://' . substr($apiKey, strpos($apiKey, '-') + 1) . '.api.mailchimp.com/3.0/';
954 $authArgs = ['headers' => ['Authorization' => 'Basic ' . base64_encode('user:' . $apiKey)]];
955 $groups = ['def' => 'Select Group'];
956 $mailchimpIDs = Core::getMailchimpLists();
957
958 foreach ($mailchimpIDs as $audience => $ignore) {
959 if ($audience === 'def') {
960 continue;
961 }
962
963 $cats = wp_remote_get("{$domain}lists/$audience/interest-categories", $authArgs);
964 $cats = json_decode($cats['body'])->categories ?? [];
965
966 foreach ($cats as $cat) {
967 $interests = wp_remote_get("{$domain}lists/$audience/interest-categories/$cat->id/interests", $authArgs);
968 $interests = json_decode($interests['body'])->interests ?? [];
969
970 foreach ($interests as $int) {
971 $groups[$int->id] = $int->name;
972 }
973 }
974 }
975
976 return $groups;
977 }
978
979 public static function getShopURL($settings)
980 {
981 global $wp;
982 $url = ('' === get_option('permalink_structure'))
983 ? remove_query_arg(['page', 'paged'], add_query_arg($wp->query_string, '', home_url($wp->request)))
984 : preg_replace('%/page/[0-9]+%', '', home_url(trailingslashit($wp->request)));
985 $url = add_query_arg('kingaddonsfilters', '', $url);
986 $single_params = [
987 'min_price' => true,
988 'max_price' => true,
989 'orderby' => false,
990 'psearch' => false,
991 'filter_product_cat' => false,
992 'filter_product_tag' => false,
993 'filter_rating' => false,
994 ];
995 foreach ($single_params as $param => $needs_clean) {
996 if (isset($_GET[$param])) {
997 $value = wp_unslash($_GET[$param]);
998 $value = $needs_clean ? wc_clean($value) : $value;
999 $url = add_query_arg($param, $value, $url);
1000 }
1001 }
1002 /** @noinspection DuplicatedCode */
1003 if ($chosen_attrs = WC()->query->get_layered_nav_chosen_attributes()) {
1004 foreach ($chosen_attrs as $name => $data) {
1005 $filter_name = wc_attribute_taxonomy_slug($name);
1006 if (!empty($data['terms'])) {
1007 $url = add_query_arg('filter_' . $filter_name, implode(',', $data['terms']), $url);
1008 }
1009 if (!empty($settings)) {
1010 if ('or' === $settings['tax_query_type'] || isset($_GET['query_type_' . $filter_name])) {
1011 $url = add_query_arg('query_type_' . $filter_name, 'or', $url);
1012 }
1013 }
1014 }
1015 }
1016 return $url;
1017 }
1018
1019 public static function getClientIP()
1020 {
1021 $server_ip_keys = [
1022 'HTTP_CLIENT_IP',
1023 'HTTP_X_FORWARDED_FOR',
1024 'HTTP_X_FORWARDED',
1025 'HTTP_X_CLUSTER_CLIENT_IP',
1026 'HTTP_FORWARDED_FOR',
1027 'HTTP_FORWARDED',
1028 'REMOTE_ADDR',
1029 ];
1030
1031 foreach ($server_ip_keys as $key) {
1032 if (isset($_SERVER[$key])) {
1033 $ip = wp_kses_post_deep(wp_unslash($_SERVER[$key]));
1034 if (filter_var($ip, FILTER_VALIDATE_IP)) {
1035 return $ip;
1036 }
1037 }
1038 }
1039
1040 return '127.0.0.1';
1041 }
1042
1043 public static function getCustomMetaKeys()
1044 {
1045 // Get all custom post types (slug => name).
1046 $post_types = Core::getCustomTypes('post', false);
1047
1048 // Build $data with each post type's unique custom meta keys (excluding keys beginning with "_").
1049 $data = array_combine(
1050 array_keys($post_types),
1051 array_map(function ($slug) {
1052 $keys = [];
1053 foreach (get_posts(['post_type' => $slug, 'posts_per_page' => -1]) as $post) {
1054 // get_post_custom_keys can return null, so cast to array:
1055 foreach ((array)get_post_custom_keys($post->ID) as $meta_key) {
1056 // Exclude protected keys (those beginning with "_").
1057 if ($meta_key[0] !== '_') {
1058 $keys[] = $meta_key;
1059 }
1060 }
1061 }
1062 return array_values(array_unique($keys));
1063 }, array_keys($post_types))
1064 );
1065
1066 // Flatten all meta keys across all post types, remove duplicates, and reindex.
1067 $merged_meta_keys = array_values(array_unique(array_merge([], ...$data)));
1068
1069 // Create an associative array where key == value (for convenient dropdowns, etc.).
1070 $options = array_combine($merged_meta_keys, $merged_meta_keys);
1071
1072 // Return both the per-post-type data and the merged, deduplicated options.
1073 return [$data, $options];
1074 }
1075
1076 public function enqueueLightboxDynamicStyles()
1077 {
1078 wp_register_style('king-addons-lightbox-dynamic-style', false);
1079 wp_enqueue_style('king-addons-lightbox-dynamic-style');
1080
1081 $bg = esc_html(get_option('king_addons_lightbox_bg_color', 'rgba(0,0,0,0.6)'));
1082 $toolbar = esc_html(get_option('king_addons_lightbox_toolbar_color', 'rgba(0,0,0,0.8)'));
1083 $caption = esc_html(get_option('king_addons_lightbox_caption_color', 'rgba(0,0,0,0.8)'));
1084 $gallery = esc_html(get_option('king_addons_lightbox_gallery_color', '#444444'));
1085 $progress_bar = esc_html(get_option('king_addons_lightbox_pb_color', '#8a8a8a'));
1086 $ui_color = esc_html(get_option('king_addons_lightbox_ui_color', '#efefef'));
1087 $icon_size = floatval(get_option('king_addons_lightbox_icon_size', 20));
1088 $icon_size_big = $icon_size + 4;
1089 $ui_hover = esc_html(get_option('king_addons_lightbox_ui_hover_color', '#ffffff'));
1090 $text_color = esc_html(get_option('king_addons_lightbox_text_color', '#efefef'));
1091 $text_size = esc_html(get_option('king_addons_lightbox_text_size', 14));
1092 $arrow_size = esc_html(get_option('king_addons_lightbox_arrow_size', 35));
1093
1094 $custom_css = "#lg-counter { color: $text_color !important; font-size: {$text_size}px !important; opacity: 0.9; } .lg-backdrop { background-color: $bg !important; } .lg-dropdown:after { border-bottom-color: $toolbar !important; } .lg-icon { color: $ui_color !important; font-size: {$icon_size}px !important; background-color: transparent !important; } .lg-icon.lg-toogle-thumb { font-size: {$icon_size_big}px !important; } .lg-icon:hover, .lg-dropdown-text:hover { color: $ui_hover !important; } .lg-prev, .lg-next { font-size: {$arrow_size}px !important; } .lg-progress { background-color: $progress_bar !important; } .lg-sub-html { background-color: $caption !important; } .lg-sub-html, .lg-dropdown-text { color: $text_color !important; font-size: {$text_size}px !important; } .lg-thumb-item { border-radius: 0 !important; border: none !important; opacity: 0.5; } .lg-thumb-item.active { opacity: 1; } .lg-thumb-outer, .lg-progress-bar { background-color: $gallery !important; } .lg-thumb-outer { padding: 0 10px; } .lg-toolbar, .lg-dropdown { background-color: $toolbar !important; }";
1095
1096 wp_add_inline_style('king-addons-lightbox-dynamic-style', $custom_css);
1097 }
1098
1099 /**
1100 * Enqueues the AI button injection script in the Elementor editor panel.
1101 *
1102 * @return void
1103 */
1104 public function enqueueAiFieldScript(): void
1105 {
1106 wp_enqueue_script(
1107 'king-addons-ai-field',
1108 KING_ADDONS_URL . 'includes/admin/js/ai-textfield.js',
1109 ['jquery', 'elementor-editor'],
1110 KING_ADDONS_VERSION,
1111 true
1112 );
1113
1114 // Localize for AJAX
1115 wp_localize_script(
1116 'king-addons-ai-field',
1117 'KingAddonsAiField',
1118 [
1119 'ajax_url' => admin_url('admin-ajax.php'),
1120 'generate_nonce' => wp_create_nonce('king_addons_ai_generate_nonce'),
1121 'change_nonce' => wp_create_nonce('king_addons_ai_change_nonce'),
1122 'generate_action' => 'king_addons_ai_generate_text',
1123 'change_action' => 'king_addons_ai_change_text',
1124 'icon_url' => KING_ADDONS_URL . 'includes/admin/img/ai.svg',
1125 'rewrite_icon_url'=> KING_ADDONS_URL . 'includes/admin/img/ai-refresh.svg',
1126 'settings_url' => admin_url('admin.php?page=king-addons-ai-settings'),
1127 'plugin_url' => KING_ADDONS_URL,
1128 'is_pro' => king_addons_freemius()->can_use_premium_code__premium_only() ? true : false,
1129 'premium_active' => king_addons_freemius()->can_use_premium_code__premium_only() ? true : false,
1130 'translator_enabled' => isset($ai_options['enable_ai_page_translator']) ? (bool) $ai_options['enable_ai_page_translator'] : true,
1131 ]
1132 );
1133 }
1134
1135 /**
1136 * Enqueues the AI image generation field script in the Elementor editor panel.
1137 *
1138 * @return void
1139 */
1140 public function enqueueAiImageGenerationScript(): void
1141 {
1142 // Retrieve AI options and ensure it's an array to prevent warnings.
1143 $ai_options = get_option('king_addons_ai_options', []);
1144 wp_enqueue_script(
1145 'king-addons-ai-image-field',
1146 KING_ADDONS_URL . 'includes/admin/js/ai-imagefield.js',
1147 ['jquery', 'elementor-editor'],
1148 KING_ADDONS_VERSION,
1149 true
1150 );
1151
1152 // Localize for AJAX
1153 wp_localize_script(
1154 'king-addons-ai-image-field',
1155 'KingAddonsAiImageField',
1156 [
1157 'ajax_url' => admin_url('admin-ajax.php'),
1158 'generate_nonce' => wp_create_nonce('king_addons_ai_generate_image_nonce'),
1159 'generate_action' => 'king_addons_ai_generate_image',
1160 'image_model' => sanitize_text_field( $ai_options['openai_image_model'] ?? '' ),
1161 'icon_url' => KING_ADDONS_URL . 'includes/admin/img/ai.svg',
1162 'rewrite_icon_url'=> KING_ADDONS_URL . 'includes/admin/img/ai-refresh.svg',
1163 'settings_url' => admin_url('admin.php?page=king-addons-ai-settings'),
1164 'plugin_url' => KING_ADDONS_URL,
1165 ]
1166 );
1167 }
1168
1169 /**
1170 * Enqueues the styles for AI prompt UI in the Elementor editor panel.
1171 *
1172 * @return void
1173 */
1174 public function enqueueAiFieldStyles(): void
1175 {
1176 // Enqueue CSS for the AI prompt UI
1177 wp_enqueue_style(
1178 'king-addons-ai-field-css',
1179 KING_ADDONS_URL . 'includes/admin/css/ai-textfield.css',
1180 [],
1181 KING_ADDONS_VERSION
1182 );
1183 }
1184
1185 /**
1186 * Enqueues styles for AI Image Generation UI in the Elementor editor panel.
1187 *
1188 * @return void
1189 */
1190 public function enqueueAiImageFieldStyles(): void
1191 {
1192 wp_enqueue_style(
1193 'king-addons-ai-imagefield',
1194 KING_ADDONS_URL . 'includes/admin/css/ai-imagefield.css',
1195 [],
1196 KING_ADDONS_VERSION
1197 );
1198 }
1199
1200 /**
1201 * Enqueues the AI page translator script in the Elementor editor panel.
1202 *
1203 * @return void
1204 */
1205 public function enqueueAiTranslatorScript(): void
1206 {
1207 // Check if AI Page Translator is enabled in settings
1208 $ai_options = get_option('king_addons_ai_options', []);
1209 $translator_enabled = isset($ai_options['enable_ai_page_translator']) ? (bool) $ai_options['enable_ai_page_translator'] : true;
1210
1211 if (!$translator_enabled) {
1212 return; // Don't load script if translator is disabled
1213 }
1214
1215 wp_enqueue_script(
1216 'king-addons-ai-translator',
1217 KING_ADDONS_URL . 'includes/admin/js/ai-page-translator.js',
1218 ['jquery', 'elementor-editor'],
1219 KING_ADDONS_VERSION,
1220 true
1221 );
1222
1223 // Note: Using existing KingAddonsAiField localization
1224 // The translator script will use the same AJAX endpoints and settings
1225 // No need for separate localization as it reuses existing AI infrastructure
1226 }
1227 }
1228
1229 Core::instance();
1230