PluginProbe ʕ •ᴥ•ʔ
Essential Addons for Elementor – Popular Elementor Templates & Widgets / 6.6.9
Essential Addons for Elementor – Popular Elementor Templates & Widgets v6.6.9
6.6.9 6.6.8 6.6.7 6.6.6 6.6.5 6.6.4 6.6.3 5.7.3 5.7.4 5.8.0 5.8.1 5.8.10 5.8.11 5.8.12 5.8.13 5.8.14 5.8.15 5.8.16 5.8.18 5.8.2 5.8.3 5.8.4 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.10 5.9.11 5.9.12 5.9.13 5.9.14 5.9.15 5.9.16 5.9.17 5.9.18 5.9.19 5.9.2 5.9.20 5.9.21 5.9.22 5.9.23 5.9.24 5.9.25 5.9.26 5.9.27 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 6.0.1 6.0.10 6.0.11 6.0.12 6.0.13 6.0.14 6.0.15 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.0.8 6.0.9 6.1.0 6.1.1 6.1.10 6.1.11 trunk 6.1.12 1.0.0 6.1.13 1.0.1 6.1.14 1.1.0 6.1.15 2.0 6.1.17 2.1 6.1.18 2.10.0 6.1.19 2.10.1 6.1.2 2.10.2 6.1.20 2.10.3 6.1.3 2.10.4 6.1.4 2.10.5 6.1.5 2.2.0 6.1.6 2.2.1 6.1.7 2.2.2 6.1.8 2.2.3 6.1.9 2.2.4 6.2.0 2.2.5 6.2.1 2.3.0 6.2.2 2.3.1 6.2.3 2.4.0 6.2.4 2.4.1 6.3.0 2.4.2 6.3.1 2.4.3 6.3.2 2.5.0 6.3.3 2.6.0 6.4.0 2.7.0 6.5.0 2.7.1 6.5.1 2.7.10 6.5.10 2.7.11 6.5.11 2.7.2 6.5.12 2.7.3 6.5.13 2.7.4 6.5.2 2.7.5 6.5.3 2.7.6 6.5.4 2.7.7 6.5.5 2.7.8 6.5.6 2.7.9 6.5.7 2.8.0 6.5.8 2.8.1 6.5.9 2.8.2 6.6.0 2.8.3 6.6.1 2.8.4 6.6.2 2.8.5 2.8.6 2.8.7 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 2.9.8 2.9.9 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.4.1 3.1.5 3.2.0 3.3.0 3.3.1 3.3.2 3.3.3 3.4.0 3.5.0 3.5.1 3.5.2 3.6.0 3.6.1 3.6.2 3.7.0 3.7.1 3.7.2 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.6.6 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.8.0 4.8.1 4.8.2 4.8.3 4.8.4 4.9.0 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.6 4.9.7 5.0.0 5.0.1 5.0.10 5.0.11 5.0.12 5.0.13 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.0.9 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.2.0 5.2.1 5.2.2 5.2.3 5.2.4 5.3.0 5.3.1 5.3.2 5.4.6 5.5.5 5.6.5 5.7.2
essential-addons-for-elementor-lite / includes / Classes / Plugin_Usage_Tracker.php
essential-addons-for-elementor-lite / includes / Classes Last commit date
AllTraits.php 1 year ago Asset_Builder.php 9 months ago Bootstrap.php 2 weeks ago Compatibility_Support.php 2 months ago Elements_Manager.php 7 months ago Helper.php 1 month ago Migration.php 5 months ago Plugin_Usage_Tracker.php 5 months ago WPDeveloper_Core_Installer.php 5 months ago WPDeveloper_Notice.php 2 months ago WPDeveloper_Plugin_Installer.php 5 months ago WPDeveloper_Setup_Wizard.php 2 months ago index.php 3 years ago
Plugin_Usage_Tracker.php
1275 lines
1 <?php
2 /**
3 * Plugin_Usage_Tracker
4 * This class is responsible for data sending to insights.
5 * @version 3.0.0
6 */
7 namespace Essential_Addons_Elementor\Classes;
8 /**
9 * Exit if accessed directly
10 */
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Main SDK for Plugin_Usage_Tracker.
17 */
18 class Plugin_Usage_Tracker {
19 /**
20 * WP Insights Version
21 */
22 const WPINS_VERSION = '3.0.3';
23 /**
24 * API URL
25 */
26 const API_URL = 'https://send.wpinsight.com/process-plugin-data';
27 /**
28 * Installed Plugin File
29 *
30 * @var string
31 */
32 private $plugin_file = null;
33 /**
34 * Installed Plugin Name
35 *
36 * @var string
37 */
38 private $plugin_name = null;
39 /**
40 * How often the event should subsequently
41 * @var string
42 */
43 public $recurrence = 'daily';
44 private $event_hook = null;
45 /**
46 * Instace of Plugin_Usage_Tracker
47 * @var Plugin_Usage_Tracker
48 */
49 private static $_instance = null;
50
51 private $disabled_wp_cron;
52 private $enable_self_cron;
53 private $require_optin;
54 private $include_goodbye_form;
55 private $marketing;
56 private $options;
57 private $item_id;
58 private $notice_options;
59
60 /**
61 * Get Instance of Plugin_Usage_Tracker
62 * @return Plugin_Usage_Tracker
63 */
64 public static function get_instance( $plugin_file, $args = [] ){
65 if( is_null( static::$_instance ) ) {
66 static::$_instance = new static( $plugin_file, $args );
67 }
68 return static::$_instance;
69 }
70 /**
71 * Automatically Invoked when initialized.
72 *
73 * @param array $args
74 */
75 public function __construct( $plugin_file, $args = [] ){
76 $this->plugin_file = $plugin_file;
77 $this->plugin_name = basename( $this->plugin_file, '.php' );
78 $this->disabled_wp_cron = defined('DISABLE_WP_CRON') && DISABLE_WP_CRON == true;
79 $this->enable_self_cron = $this->disabled_wp_cron == true ? true : false;
80
81 $this->event_hook = 'put_do_weekly_action';
82
83 $this->require_optin = isset( $args['opt_in'] ) ? $args['opt_in'] : true;
84 $this->include_goodbye_form = isset( $args['goodbye_form'] ) ? $args['goodbye_form'] : true;
85 $this->marketing = isset( $args['email_marketing'] ) ? $args['email_marketing'] : true;
86 $this->options = isset( $args['options'] ) ? $args['options'] : [];
87 $this->item_id = isset( $args['item_id'] ) ? $args['item_id'] : false;
88 /**
89 * Activation Hook
90 */
91 register_activation_hook( $this->plugin_file, array( $this, 'activate_this_plugin' ) );
92 /**
93 * Deactivation Hook
94 */
95 register_deactivation_hook( $this->plugin_file, array( $this, 'deactivate_this_plugin' ) );
96 }
97 /**
98 * When user agreed to opt-in tracking schedule is enabled.
99 * @since 3.0.0
100 */
101 public function schedule_tracking() {
102 if( $this->disabled_wp_cron ) {
103 return;
104 }
105 if ( ! wp_next_scheduled( $this->event_hook ) ) {
106 wp_schedule_event( time(), $this->recurrence, $this->event_hook );
107 }
108 }
109 /**
110 * Add the schedule event if the plugin is tracked.
111 *
112 * @return void
113 */
114 public function activate_this_plugin(){
115 $allow_tracking = $this->is_tracking_allowed();
116 if( ! $allow_tracking ) {
117 return;
118 }
119 $this->schedule_tracking();
120 }
121 /**
122 * Remove the schedule event when plugin is deactivated and send the deactivated reason to inishghts if user submitted.
123 * @since 3.0.0
124 */
125 public function deactivate_this_plugin() {
126 /**
127 * Check tracking is allowed or not.
128 */
129 $allow_tracking = $this->is_tracking_allowed();
130 if( ! $allow_tracking ) {
131 return;
132 }
133 $body = $this->get_data();
134 $body['status'] = 'Deactivated';
135 $body['deactivated_date'] = time();
136
137 // Check deactivation reason and add for insights data.
138 if( false !== get_option( 'wpins_deactivation_reason_' . $this->plugin_name ) ) {
139 $body['deactivation_reason'] = get_option( 'wpins_deactivation_reason_' . $this->plugin_name );
140 }
141 if( false !== get_option( 'wpins_deactivation_details_' . $this->plugin_name ) ) {
142 $body['deactivation_details'] = get_option( 'wpins_deactivation_details_' . $this->plugin_name );
143 }
144
145 $this->send_data( $body );
146 delete_option( 'wpins_deactivation_reason_' . $this->plugin_name );
147 delete_option( 'wpins_deactivation_details_' . $this->plugin_name );
148 /**
149 * Clear the event schedule.
150 */
151 if( ! $this->disabled_wp_cron ) {
152 wp_clear_scheduled_hook( $this->event_hook );
153 }
154 }
155 /**
156 * Initial Method to Hook Everything.
157 * @return void
158 */
159 public function init(){
160 // $this->clicked();
161 add_action('wpdeveloper_notice_clicked_for_' . $this->plugin_name, array($this, 'clicked'));
162 add_action( $this->event_hook, array( $this, 'do_tracking' ) );
163 // For Test
164 // add_action( 'admin_init', array( $this, 'force_tracking' ) );
165 // add_action( 'admin_notices', array( $this, 'notice' ) );
166 add_action('wpdeveloper_optin_notice_for_' . $this->plugin_name, array($this, 'notice'));
167 /**
168 * Deactivation Reason Form and Submit Data to Insights.
169 */
170 add_filter( 'plugin_action_links_' . plugin_basename( $this->plugin_file ), array( $this, 'deactivate_action_links' ) );
171 add_action( 'admin_footer-plugins.php', array( $this, 'deactivate_reasons_form' ) );
172 add_action( 'wp_ajax_deactivation_form_' . esc_attr( $this->plugin_name ), array( $this, 'deactivate_reasons_form_submit' ) );
173 }
174 /**
175 * For Redirecting Current Page without Arguments!
176 *
177 * @return void
178 */
179 private function redirect_to(){
180 $request_uri = !empty( $_SERVER['REQUEST_URI'] ) ? wp_parse_url( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), PHP_URL_PATH ) : '';
181 $query_string = !empty( $_SERVER['REQUEST_URI'] ) ? wp_parse_url( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ), PHP_URL_QUERY ) : '';
182 parse_str( $query_string, $current_url );
183
184 $unset_array = array( 'dismiss', 'plugin', '_wpnonce', 'later', 'plugin_action', 'marketing_optin' );
185
186 foreach( $unset_array as $value ) {
187 if( isset( $current_url[ $value ] ) ) {
188 unset( $current_url[ $value ] );
189 }
190 }
191
192 $current_url = http_build_query($current_url);
193 $redirect_url = $request_uri . '?' . $current_url;
194 return $redirect_url;
195 }
196 /**
197 * This method forcing the do_tracking method to execute instant.
198 * @return void
199 */
200 public function force_tracking(){
201 $this->do_tracking( true );
202 }
203 /**
204 * This method is responsible for all the magic from the front of the plugin.
205 * @since 3.0.0
206 * @param $force Force tracking if it's not the correct time to track/
207 */
208 public function do_tracking( $force = false ) {
209 /**
210 * Check URL is set or not.
211 */
212 if ( empty( self::API_URL ) ) {
213 return;
214 }
215 /**
216 * Check is tracking allowed or not.
217 */
218 if( ! $this->is_tracking_allowed() ) {
219 return;
220 }
221 /**
222 * Check is this the correct time to track or not.
223 * or Force to track.
224 */
225 if( ! $this->is_time_to_track() && ! $force ) {
226 return;
227 }
228 /**
229 * Get All Data.
230 */
231 $body = $this->get_data();
232 /**
233 * Send all data.
234 */
235 return $this->send_data( $body );
236 }
237 /**
238 * Is tracking allowed?
239 * @since 1.0.0
240 */
241 private function is_tracking_allowed() {
242 // First, check if the user has changed their mind and opted out of tracking
243 if( $this->has_user_opted_out() ) {
244 $this->set_is_tracking_allowed( false, $this->plugin_name );
245 return false;
246 }
247 // The wpins_allow_tracking option is an array of plugins that are being tracked
248 $allow_tracking = get_option( 'wpins_allow_tracking' );
249 // If this plugin is in the array, then tracking is allowed
250 if( isset( $allow_tracking[$this->plugin_name] ) ) {
251 return true;
252 }
253 return false;
254 }
255 /**
256 * Set a flag in DB If tracking is allowed.
257 *
258 * @since 3.0.0
259 * @param $is_allowed Boolean true if is allowed.
260 */
261 public function set_is_tracking_allowed( $is_allowed, $plugin = null ) {
262 if( empty( $plugin ) ) {
263 $plugin = $this->plugin_name;
264 }
265 /**
266 * Get All Tracked Plugin List using this Tracker.
267 */
268 $allow_tracking = get_option( 'wpins_allow_tracking' );
269 /**
270 * Check user is opted out for tracking or not.
271 */
272 if( $this->has_user_opted_out() ) {
273 if( isset( $allow_tracking[$plugin] ) ) {
274 unset( $allow_tracking[$plugin] );
275 }
276 } else if( $is_allowed || ! $this->require_optin ) {
277 /**
278 * If user has agreed to allow tracking
279 */
280 if( empty( $allow_tracking ) || ! is_array( $allow_tracking ) ) {
281 $allow_tracking = array( $plugin => $plugin );
282 } else {
283 $allow_tracking[$plugin] = $plugin;
284 }
285 } else {
286 if( isset( $allow_tracking[$plugin] ) ) {
287 unset( $allow_tracking[$plugin] );
288 }
289 }
290 update_option( 'wpins_allow_tracking', $allow_tracking );
291 }
292
293 /**
294 * Check the user has opted out or not.
295 *
296 * @since 3.0.0
297 * @return Boolean
298 */
299 protected function has_user_opted_out() {
300 if( ! empty( $this->options ) ) {
301 foreach( $this->options as $option_name ) {
302 $options = get_option( $option_name );
303 if( ! empty( $options['wpins_opt_out'] ) ) {
304 return true;
305 }
306 }
307 }
308 return false;
309 }
310 /**
311 * Check if it's time to track
312 *
313 * @since 3.0.0
314 */
315 public function is_time_to_track() {
316 $track_times = get_option( 'wpins_last_track_time', array() );
317 return ! isset( $track_times[$this->plugin_name] ) ? true :
318 ( ( isset( $track_times[$this->plugin_name] ) && $track_times[$this->plugin_name] ) < strtotime( '-1 day' ) ? true : false );
319 }
320 /**
321 * Set tracking time.
322 *
323 * @since 3.0.0
324 */
325 public function set_track_time() {
326 $track_times = get_option( 'wpins_last_track_time', array() );
327 $track_times[ $this->plugin_name ] = time();
328 update_option( 'wpins_last_track_time', $track_times );
329 }
330 /**
331 * This method is responsible for collecting all data.
332 *
333 * @since 3.0.0
334 */
335 public function get_data() {
336 $body = array(
337 'plugin_slug' => sanitize_text_field( $this->plugin_name ),
338 'url' => get_bloginfo( 'url' ),
339 'site_name' => get_bloginfo( 'name' ),
340 'site_version' => get_bloginfo( 'version' ),
341 'site_language' => get_bloginfo( 'language' ),
342 'charset' => get_bloginfo( 'charset' ),
343 'wpins_version' => self::WPINS_VERSION,
344 'php_version' => phpversion(),
345 'multisite' => is_multisite(),
346 'file_location' => __FILE__
347 );
348
349 // Collect the email if the correct option has been set
350 if( $this->marketing ) {
351 if( ! function_exists( 'wp_get_current_user' ) ) {
352 include ABSPATH . 'wp-includes/pluggable.php';
353 }
354 $current_user = wp_get_current_user();
355 $email = $current_user->user_email;
356 if( is_email( $email ) ) {
357 $body['email'] = $email;
358 } else {
359 $email = get_option( 'admin_email' );
360 if( is_email($email) ) {
361 $body['email'] = $email;
362 }
363 }
364 }
365 $body['marketing_method'] = $this->marketing;
366 $body['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : '';
367
368 /**
369 * Collect all active and inactive plugins
370 */
371 if( ! function_exists( 'get_plugins' ) ) {
372 include ABSPATH . '/wp-admin/includes/plugin.php';
373 }
374 $plugins = array_keys( get_plugins() );
375 $active_plugins = is_network_admin() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : get_option( 'active_plugins', array() );
376 foreach ( $plugins as $key => $plugin ) {
377 if ( in_array( $plugin, $active_plugins ) ) {
378 unset( $plugins[$key] );
379 }
380 }
381 $body['active_plugins'] = $active_plugins;
382 $body['inactive_plugins'] = $plugins;
383
384 /**
385 * Text Direction.
386 */
387 $body['text_direction'] = ( function_exists( 'is_rtl' ) ? ( is_rtl() ? 'RTL' : 'LTR' ) : 'NOT SET' );
388 /**
389 * Get Our Plugin Data.
390 * @since 3.0.0
391 */
392 $plugin = $this->plugin_data();
393 if( empty( $plugin ) ) {
394 $body['message'] .= __( 'We can\'t detect any plugin information. This is most probably because you have not included the code in the plugin main file.', 'essential-addons-for-elementor-lite' );
395 $body['status'] = 'NOT FOUND';
396 } else {
397 if( isset( $plugin['Name'] ) ) {
398 $body['plugin'] = sanitize_text_field( $plugin['Name'] );
399 }
400 if( isset( $plugin['Version'] ) ) {
401 $body['version'] = sanitize_text_field( $plugin['Version'] );
402 }
403 $body['status'] = 'Active';
404 }
405
406 /**
407 * Get active theme name and version
408 * @since 3.0.0
409 */
410 $theme = wp_get_theme();
411 if( $theme->Name ) {
412 $body['theme'] = sanitize_text_field( $theme->Name );
413 }
414 if( $theme->Version ) {
415 $body['theme_version'] = sanitize_text_field( $theme->Version );
416 }
417
418 if ( ! empty( $this->get_used_elements_count() ) ) {
419 $body['optional_data'] = $this->get_used_elements_count();
420 }
421
422 return $body;
423 }
424
425 /**
426 * Collect plugin data,
427 * Retrieve current plugin information
428 *
429 * @since 3.0.0
430 */
431 public function plugin_data() {
432 if( ! function_exists( 'get_plugin_data' ) ) {
433 include ABSPATH . '/wp-admin/includes/plugin.php';
434 }
435 $plugin = get_plugin_data( $this->plugin_file );
436 return $plugin;
437 }
438 /**
439 * Send the data to insights.
440 * @since 3.0.0
441 */
442 public function send_data( $body ) {
443 /**
444 * Get SITE ID
445 */
446 $site_id_key = "wpins_{$this->plugin_name}_site_id";
447 $site_id = get_option( $site_id_key, false );
448 $failed_data = [];
449 $site_url = get_bloginfo( 'url' );
450 $original_site_url = get_option( "wpins_{$this->plugin_name}_original_url", false );
451
452 if( ( $original_site_url === false || $original_site_url != $site_url ) && version_compare( $body['wpins_version'], '3.0.1', '>=' ) ) {
453 $site_id = false;
454 }
455 /**
456 * Send Initial Data to API
457 */
458 if( $site_id == false && $this->item_id !== false ) {
459 if( isset( $_SERVER['REMOTE_ADDR'] ) && ! empty( $_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1' ) ) {
460 $country_request = wp_remote_get( 'http://ip-api.com/json/'. sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) .'?fields=country');
461 if( ! is_wp_error( $country_request ) && $country_request['response']['code'] == 200 ) {
462 $ip_data = json_decode( $country_request["body"] );
463 $body['country'] = isset( $ip_data->country ) ? $ip_data->country : 'NOT SET';
464 }
465 }
466
467 $body['plugin_slug'] = $this->plugin_name;
468 $body['url'] = $site_url;
469 $body['item_id'] = $this->item_id;
470
471 $request = $this->remote_post( $body );
472 if( ! is_wp_error( $request ) && $request['response']['code'] == 200 ) {
473 $retrieved_body = json_decode( wp_remote_retrieve_body( $request ), true );
474 if( is_array( $retrieved_body ) && isset( $retrieved_body['siteId'] ) ) {
475 update_option( $site_id_key, $retrieved_body['siteId'] );
476 update_option( "wpins_{$this->plugin_name}_original_url", $site_url );
477 update_option( "wpins_{$this->plugin_name}_{$retrieved_body['siteId']}", $body );
478 }
479 } else {
480 $failed_data = $body;
481 }
482 }
483
484 $site_id_data_key = "wpins_{$this->plugin_name}_{$site_id}";
485 $site_id_data_failed_key = "wpins_{$this->plugin_name}_{$site_id}_send_failed";
486
487 if( $site_id != false ) {
488 $old_sent_data = get_option( $site_id_data_key, [] );
489 $diff_data = $this->diff( $body, $old_sent_data );
490 $failed_data = get_option( $site_id_data_failed_key, [] );
491 if( ! empty( $failed_data ) && $diff_data != $failed_data ) {
492 $failed_data = array_merge( $failed_data, $diff_data );
493 }
494 }
495
496 if( ! empty( $failed_data ) && $site_id != false ) {
497 $failed_data['plugin_slug'] = $this->plugin_name;
498 $failed_data['url'] = $site_url;
499 $failed_data['site_id'] = $site_id;
500 if( $original_site_url != false ) {
501 $failed_data['original_url'] = $original_site_url;
502 }
503
504 $request = $this->remote_post( $failed_data );
505 if( ! is_wp_error( $request ) ) {
506 delete_option( $site_id_data_failed_key );
507 $replaced_data = array_merge( $old_sent_data, $failed_data );
508 update_option( $site_id_data_key, $replaced_data );
509 }
510 }
511
512 if( ! empty( $diff_data ) && $site_id != false && empty( $failed_data ) ) {
513 $diff_data['plugin_slug'] = $this->plugin_name;
514 $diff_data['url'] = $site_url;
515 $diff_data['site_id'] = $site_id;
516 if( $original_site_url != false ) {
517 $diff_data['original_url'] = $original_site_url;
518 }
519
520 $request = $this->remote_post( $diff_data );
521 if( is_wp_error( $request ) ) {
522 update_option( $site_id_data_failed_key, $diff_data );
523 } else {
524 $replaced_data = array_merge( $old_sent_data, $diff_data );
525 update_option( $site_id_data_key, $replaced_data );
526 }
527 }
528
529 $this->set_track_time();
530
531 if( isset( $request ) && is_wp_error( $request ) ) {
532 return $request;
533 }
534
535 if( isset( $request ) ) {
536 return true;
537 }
538 return false;
539 }
540 /**
541 * WP_REMOTE_POST method responsible for send data to the API_URL
542 *
543 * @param array $data
544 * @param array $args
545 * @return void
546 */
547 protected function remote_post( $data = array(), $args = array() ){
548 if( empty( $data ) ) {
549 return;
550 }
551
552 $args = wp_parse_args( $args, array(
553 'method' => 'POST',
554 'timeout' => 30,
555 'redirection' => 5,
556 'httpversion' => '1.1',
557 'blocking' => true,
558 'body' => $data,
559 'user-agent' => 'PUT/1.0.0; ' . get_bloginfo( 'url' )
560 ));
561 $request = wp_remote_post( esc_url( self::API_URL ), $args );
562 if( is_wp_error( $request ) || ( isset( $request['response'], $request['response']['code'] ) && $request['response']['code'] != 200 ) ) {
563 return new \WP_Error( 500, 'Something went wrong.' );
564 }
565 return $request;
566 }
567 /**
568 * Difference between old and new data
569 *
570 * @param array $new_data
571 * @param array $old_data
572 * @return void
573 */
574 protected function diff( $new_data, $old_data ){
575 $data = [];
576 if( ! empty( $new_data ) ) {
577 foreach( $new_data as $key => $value ) {
578 if( isset( $old_data[ $key ] ) ) {
579 if( $old_data[ $key ] == $value ) {
580 continue;
581 }
582 }
583 $data[ $key ] = $value;
584 }
585 }
586 return $data;
587 }
588 /**
589 * Display the admin notice to users to allow them to opt in
590 *
591 * @since 3.0.0
592 */
593 public function notice() {
594 /**
595 * Return if notice is not set.
596 */
597 if( ! isset( $this->notice_options['notice'] ) ) {
598 return;
599 }
600 /**
601 * Check is allowed or blocked for notice.
602 */
603 $block_notice = get_option( 'wpins_block_notice' );
604 if( isset( $block_notice[$this->plugin_name] ) ) {
605 return;
606 }
607 if ( ! current_user_can( 'manage_options' ) ) {
608 return;
609 }
610
611 $url_yes = add_query_arg( [
612 'plugin' => $this->plugin_name,
613 'plugin_action' => 'yes',
614 ] );
615 $url_no = add_query_arg( array(
616 'plugin' => $this->plugin_name,
617 'plugin_action' => 'no'
618 ) );
619
620 $url_yes = wp_nonce_url( $url_yes, '_wpnonce_optin_' . $this->plugin_name );
621 $url_no = wp_nonce_url( $url_no, '_wpnonce_optin_' . $this->plugin_name );
622
623 // Decide on notice text
624 $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-'. esc_attr( $this->plugin_name ) .'-collect">'. $this->notice_options['consent_button_text'] .'</a>';
625 $extra_notice_text = $this->notice_options['extra_notice'];
626
627 $output = '';
628 $output .= '<div class="notice notice-info updated put-dismiss-notice">';
629 $output .= '<p>'. $notice_text .'</p>';
630 $output .= '<div class="wpinsights-data" style="display: none;">';
631 $output .= '<p>'. $extra_notice_text .'</p>';
632 $output .= '</div>';
633 $output .= '<p>';
634 $output .= '<a href="'. esc_url( $url_yes ) .'" class="button-primary">'. $this->notice_options['yes'] .'</a>&nbsp;';
635 $output .= '<a href="'. esc_url( $url_no ) .'" class="button-secondary">'. $this->notice_options['no'] .'</a>';
636 $output .= '</p>';
637 $output .= "<script type='text/javascript'>jQuery('.wpinsights-". esc_attr( $this->plugin_name ) ."-collect').on('click', function(e) {e.preventDefault();jQuery('.wpinsights-data').slideToggle('fast');});</script>";
638 $output .= '</div>';
639
640 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
641 echo $output;
642 }
643 /**
644 * Set all notice options to customized notice.
645 *
646 * @since 3.0.0
647 * @param array $options
648 * @return void
649 */
650 public function set_notice_options( $options = [] ){
651 $default_options = [
652 'consent_button_text' => __( 'What we collect.', 'essential-addons-for-elementor-lite' ),
653 'yes' => __( 'Sure, I\'d like to help', 'essential-addons-for-elementor-lite' ),
654 'no' => __( 'No Thanks.', 'essential-addons-for-elementor-lite' ),
655 ];
656 $options = wp_parse_args( $options, $default_options );
657 $this->notice_options = $options;
658 }
659 /**
660 * Responsible for track the click from Notice.
661 * @return void
662 */
663 public function clicked(){
664 if ( isset( $_GET['_wpnonce'] ) && isset( $_GET['plugin'] ) && sanitize_text_field( wp_unslash( $_GET['plugin'] ) ) === $this->plugin_name && isset( $_GET['plugin_action'] ) ) {
665 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), '_wpnonce_optin_' . $this->plugin_name ) ) {
666 return;
667 }
668
669 if( isset( $_GET['tab'] ) && $_GET['tab'] === 'plugin-information' ) {
670 return;
671 }
672 $plugin = sanitize_text_field( wp_unslash( $_GET['plugin'] ) );
673 $action = sanitize_text_field( wp_unslash( $_GET['plugin_action'] ) );
674 if( $action == 'yes' ) {
675 $this->schedule_tracking();
676 $this->set_is_tracking_allowed( true, $plugin );
677 if( $this->do_tracking( true ) ) {
678 $this->update_block_notice( $plugin );
679 }
680 /**
681 * Redirect User To the Current URL, but without set query arguments.
682 */
683 wp_safe_redirect( $this->redirect_to() );
684 } else {
685 $this->set_is_tracking_allowed( false, $plugin );
686 $this->update_block_notice( $plugin );
687 }
688 }
689 }
690 /**
691 * Set if we should block the opt-in notice for this plugin
692 *
693 * @since 3.0.0
694 */
695 public function update_block_notice( $plugin = null ) {
696 if( empty( $plugin ) ) {
697 $plugin = $this->plugin_name;
698 }
699 $block_notice = get_option( 'wpins_block_notice' );
700 if( empty( $block_notice ) || ! is_array( $block_notice ) ) {
701 $block_notice = array( $plugin => $plugin );
702 } else {
703 $block_notice[$plugin] = $plugin;
704 }
705 update_option( 'wpins_block_notice', $block_notice );
706 }
707 /**
708 * AJAX callback when the deactivated form is submitted.
709 * @since 3.0.0
710 */
711 public function deactivate_reasons_form_submit() {
712 check_ajax_referer( 'wpins_deactivation_nonce', 'security' );
713 if( isset( $_POST['values'] ) ) {
714 $values = sanitize_text_field( wp_unslash( $_POST['values'] ) );
715 update_option( 'wpins_deactivation_reason_' . $this->plugin_name, $values );
716 }
717 if( isset( $_POST['details'] ) ) {
718 $details = sanitize_text_field( wp_unslash( $_POST['details'] ) );
719 update_option( 'wpins_deactivation_details_' . $this->plugin_name, $details );
720 }
721 echo 'success';
722 wp_die();
723 }
724 /**
725 * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
726 * @since 3.0.0
727 */
728 public function deactivate_action_links( $links ) {
729 /**
730 * Check is tracking allowed or not.
731 */
732 if( ! $this->is_tracking_allowed() ) {
733 return $links;
734 }
735 if( isset( $links['deactivate'] ) && $this->include_goodbye_form ) {
736 $deactivation_link = $links['deactivate'];
737 /**
738 * Change the default deactivate button link.
739 */
740 $deactivation_link = str_replace( '<a ', '<div class="wpinsights-goodbye-form-wrapper-'. esc_attr( $this->plugin_name ) .'"><div class="wpinsights-goodbye-form-bg"></div><span class="wpinsights-goodbye-form" id="wpinsights-goodbye-form"></span></div><a onclick="javascript:event.preventDefault();" id="wpinsights-goodbye-link-' . esc_attr( $this->plugin_name ) . '" ', $deactivation_link );
741 $links['deactivate'] = $deactivation_link;
742 }
743 return $links;
744 }
745 /**
746 * ALL Deactivate Reasons.
747 * @since 3.0.0
748 */
749 public function deactivation_reasons() {
750 $form = array();
751 $form['heading'] = __( 'We Value Your Feedback', 'essential-addons-for-elementor-lite' );
752 $form['body'] = __( "Could you please tell us why you're deactivating our plugin? Your insights will help us to improve.", 'essential-addons-for-elementor-lite' );
753
754 $form['options'] = array(
755 __( 'I no longer need the plugin', 'essential-addons-for-elementor-lite' ),
756 [
757 'label' => __( 'I found a better plugin', 'essential-addons-for-elementor-lite' ),
758 'extra_field' => __( 'Please share which plugin', 'essential-addons-for-elementor-lite' )
759 ],
760 __( "I couldn't get the plugin to work", 'essential-addons-for-elementor-lite' ),
761 __( 'It\'s a temporary deactivation', 'essential-addons-for-elementor-lite' ),
762 [
763 'label' => __( 'Other', 'essential-addons-for-elementor-lite' ),
764 'extra_field' => __( 'Please share the reason', 'essential-addons-for-elementor-lite' ),
765 'type' => 'textarea'
766 ]
767 );
768 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
769 return apply_filters( 'wpins_form_text_' . $this->plugin_name, $form );
770 }
771 /**
772 * Deactivate Reasons Form.
773 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
774 *
775 * @since 3.0.0
776 */
777 public function deactivate_reasons_form() {
778 $form = $this->deactivation_reasons();
779 $class_plugin_name = esc_attr( $this->plugin_name );
780 $html = '<div class="ea__modal-close-btn"><svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M5.29289 5.29289C5.68342 4.90237 6.31658 4.90237 6.70711 5.29289L12 10.5858L17.2929 5.29289C17.6834 4.90237 18.3166 4.90237 18.7071 5.29289C19.0976 5.68342 19.0976 6.31658 18.7071 6.70711L13.4142 12L18.7071 17.2929C19.0976 17.6834 19.0976 18.3166 18.7071 18.7071C18.3166 19.0976 17.6834 19.0976 17.2929 18.7071L12 13.4142L6.70711 18.7071C6.31658 19.0976 5.68342 19.0976 5.29289 18.7071C4.90237 18.3166 4.90237 17.6834 5.29289 17.2929L10.5858 12L5.29289 6.70711C4.90237 6.31658 4.90237 5.68342 5.29289 5.29289Z"/></svg></div><div class="wpinsights-goodbye-form-head"><span><svg width="65" height="64" viewBox="0 0 65 64" fill="none" xmlns="http://www.w3.org/2000/svg"><rect x="0.5" width="64" height="64" rx="16" fill="#F6EEFF"/><path d="M41.8346 22.668L45.8346 18.668M19.168 45.3346L23.168 41.3346M26.5013 34.0013L29.8346 30.668M30.5013 38.0013L33.8346 34.668M24.9013 43.068C25.1986 43.3663 25.5518 43.603 25.9408 43.7645C26.3298 43.926 26.7468 44.0092 27.168 44.0092C27.5891 44.0092 28.0062 43.926 28.3951 43.7645C28.7841 43.603 29.1373 43.3663 29.4346 43.068L32.5013 40.0013L24.5013 32.0013L21.4346 35.068C21.1363 35.3653 20.8996 35.7185 20.7381 36.1075C20.5766 36.4964 20.4934 36.9135 20.4934 37.3346C20.4934 37.7558 20.5766 38.1728 20.7381 38.5618C20.8996 38.9508 21.1363 39.304 21.4346 39.6013L24.9013 43.068ZM32.5013 24.0013L40.5013 32.0013L43.568 28.9346C43.8663 28.6373 44.103 28.2841 44.2645 27.8951C44.426 27.5062 44.5092 27.0891 44.5092 26.668C44.5092 26.2468 44.426 25.8298 44.2645 25.4408C44.103 25.0518 43.8663 24.6986 43.568 24.4013L40.1013 20.9346C39.804 20.6363 39.4508 20.3996 39.0618 20.2381C38.6728 20.0766 38.2558 19.9934 37.8346 19.9934C37.4135 19.9934 36.9964 20.0766 36.6075 20.2381C36.2185 20.3996 35.8653 20.6363 35.568 20.9346L32.5013 24.0013Z" stroke="#750EF4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span><h1>' . $form['heading'] . '</h1></div>';
781 $html .= '<div class="wpinsights-goodbye-form-body"><p class="wpinsights-goodbye-form-caption">' . esc_html( $form['body'] ) . '</p>';
782 if( is_array( $form['options'] ) ) {
783 $html .= '<div id="wpinsights-goodbye-options" class="wpinsights-goodbye-options"><ul>';
784 foreach( $form['options'] as $option ) {
785 if( is_array( $option ) ) {
786 $id = strtolower( str_replace( " ", "_", esc_attr( $option['label'] ) ) );
787 $id = $id . '_' . $class_plugin_name;
788 $html .= '<li class="has-goodbye-extra">';
789 $html .= '<input type="radio" name="wpinsights-'. esc_attr( $class_plugin_name ) .'-goodbye-options" id="' . esc_attr( $id ) . '" value="' . esc_attr( $option['label'] ) . '">';
790 $html .= '<div><label for="' . $id . '">' . esc_attr( $option['label'] ) . '</label>';
791 if( isset( $option[ 'extra_field' ] ) && ! isset( $option['type'] )) {
792 $html .= '<input type="text" style="display: none" name="'. esc_attr( $id ) .'" id="' . str_replace( " ", "", esc_attr( $option['extra_field'] ) ) . '" placeholder="' . esc_attr( $option['extra_field'] ) . '">';
793 }
794 if( isset( $option[ 'extra_field' ] ) && isset( $option['type'] )) {
795 $html .= '<'. $option['type'] .' style="display: none" type="text" name="'. esc_attr( $id ) .'" id="' . str_replace( " ", "", esc_attr( $option['extra_field'] ) ) . '" placeholder="' . esc_attr( $option['extra_field'] ) . '"></' . $option['type'] . '>';
796 }
797 $html .= '</div></li>';
798 } else {
799 $id = strtolower( str_replace( " ", "_", esc_attr( $option ) ) );
800 $id = $id . '_' . $class_plugin_name;
801 $html .= '<li><input type="radio" name="wpinsights-'. $class_plugin_name .'-goodbye-options" id="' . esc_attr( $id ) . '" value="' . esc_attr( $option ) . '"> <label for="' . $id . '">' . esc_attr( $option ) . '</label></li>';
802 }
803 }
804 $html .= '</ul></div><!-- .wpinsights-'. $class_plugin_name .'-goodbye-options -->';
805 }
806 $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
807 $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', 'essential-addons-for-elementor-lite' ) . '</p>';
808
809 $wrapper_class = '.wpinsights-goodbye-form-wrapper-'. $class_plugin_name;
810
811 $styles = '';
812 $styles .= '<style type="text/css">';
813 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form-bg {';
814 $styles .= 'background: rgba( 0, 0, 0, .8 );position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 9;';
815 $styles .= '}';
816 $styles .= $wrapper_class . '{';
817 $styles .= 'position: relative; display: none;';
818 $styles .= '}';
819 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' ' . $wrapper_class . '{';
820 $styles .= 'display: flex !important; position: fixed;top: 0;left: 0;width: 100%;height: 100%; justify-content: center; align-items: center;';
821 $styles .= '}';
822 $styles .= $wrapper_class . ' .wpinsights-goodbye-form { display: none; }';
823 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form {';
824 $styles .= 'position: relative !important; width: 550px; max-width: 80%; background: #fff; box-shadow: 2px 8px 23px 3px rgba(0,0,0,.2); border-radius: 3px; white-space: normal; overflow: hidden; display: block; z-index: 999999;';
825 $styles .= '}';
826 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-head {';
827 $styles .= 'background: #fff; color: #495157; padding: 18px; box-shadow: 0 0 8px rgba(0,0,0,.1); font-size: 15px;';
828 $styles .= '}';
829 $styles .= $wrapper_class . ' .wpinsights-goodbye-form .wpinsights-goodbye-form-head strong { font-size: 15px; }';
830 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body { padding: 8px 18px; color: #333; }';
831 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body label { padding-left: 5px; color: #6d7882; }';
832 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {';
833 $styles .= 'font-weight: 500; font-size: 15px; color: #495157; line-height: 1.4;';
834 $styles .= '}';
835 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options { padding-top: 5px; }';
836 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li { margin-bottom: 15px; }';
837 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div { display: inline; padding-left: 3px; }';
838 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > input, '. $wrapper_class .' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > textarea {';
839 $styles .= 'margin: 10px 18px; padding: 8px; width: 80%;';
840 $styles .= '}';
841 $styles .= $wrapper_class . ' .deactivating-spinner { display: none; padding-bottom: 20px !important; }';
842 $styles .= $wrapper_class . ' .deactivating-spinner .spinner { float: none; margin: 4px 4px 0 18px; vertical-align: bottom; visibility: visible; }';
843 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer { padding: 8px 18px; margin-bottom: 15px; }';
844 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons { display: flex; align-items: center; justify-content: space-between; }';
845 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn {';
846 $styles .= 'background-color: #f3bafd; -webkit-border-radius: 3px; border-radius: 3px; color: #0c0d0e; line-height: 1; padding: 10px 20px; font-size: 13px; font-weight: 500; text-transform: uppercase; transition: .3s;';
847 $styles .= '}';
848 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn:hover {';
849 $styles .= 'background-color: #f5d0fe;';
850 $styles .= '}';
851 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {';
852 $styles .= 'font-size: 13px; color: #a4afb7; background: none; float: right; padding-right: 10px; width: auto; text-decoration: underline;';
853 $styles .= '}';
854 $styles .= $wrapper_class . ' .test {';
855 $styles .= '}';
856 $styles .= '
857
858 .wpinsights-form-active-essential_adons_elementor .wpinsights-goodbye-form-wrapper-essential_adons_elementor {
859 display: flex !important;
860 position: fixed;
861 top: 0;
862 left: 0;
863 right: 0;
864 bottom: 0;
865 width: 100%;
866 z-index: 9999;
867 height: 100%;
868 justify-content: center;
869 align-items: center;
870 }
871 .wpinsights-form-active-essential_adons_elementor .wpinsights-goodbye-form {
872 border-radius: 8px;
873 width: 563px;
874 overflow: visible;
875 position: relative;
876 }
877 .wpinsights-goodbye-form .ea__modal-close-btn {
878 position: absolute;
879 top: 0;
880 right: -55px;
881 width: 40px;
882 height: 40px;
883 background: #fff;
884 border-radius: 50%;
885 display: flex;
886 justify-content: center;
887 align-items: center;
888 font-size: 12px;
889 font-weight: 500;
890 color: #475467;
891 cursor: pointer;
892 }
893 .wpinsights-goodbye-form .ea__modal-close-btn svg {
894 width: 20px;
895 }
896 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-head {
897 background: #fff;
898 color: #495157;
899 padding: 24px;
900 border-radius: 8px 8px 0 0;
901 box-shadow: none;
902 border-bottom: 1px solid #EAECF0;
903 display: flex;
904 flex-direction: column;
905 gap: 16px;
906 align-items: center;
907 }
908 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-head > span {
909 display: inline-flex;
910 }
911 .wpinsights-goodbye-form-head h1 {
912 font-size: 22px;
913 font-weight: 450;
914 color: #1D2939;
915 padding: 0;
916 }
917 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body {
918 padding: 32px 40px;
919 max-height: calc(70vh - 230px);
920 overflow: auto;
921 }
922 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {
923 font-size: 18px;
924 color: #1D2939;
925 margin: 0;
926 padding-bottom: 16px;
927 font-weight: 400;
928 }
929 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body #wpinsights-goodbye-options {
930 padding-top: 0px;
931 }
932 .widefat td ul {
933 font-size: 14px;
934 margin: 0;
935 color: #475467;
936 line-height: 1.4em;
937 }
938 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li:not(:last-child) {
939 margin-bottom: 16px;
940 }
941 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li:last-child {
942 margin-bottom: 0;
943 }
944 input[type=radio] {
945 border-radius: 50%;
946 margin-right: .25rem;
947 line-height: .71428571;
948 margin: 0;
949 }
950 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body label {
951 padding-left: 4px;
952 color: #475467;
953 font-size: 14px;
954 }
955 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > input, .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > textarea {
956 padding: 10px 16px;
957 border-radius: 8px;
958 width: 100%;
959 border: 1px solid #D0D5DD;
960 margin: 0;
961 margin-top: 16px;
962 color: #1D2939;
963 font-size: 14px;
964 line-height: 1.5em;
965 resize: none;
966 max-height: 44px;
967 }
968 input[type=radio] {
969 border: 1px solid #D0D5DD;
970 box-shadow: none;
971 }
972 input[type=radio]:checked::before {
973 content: "";
974 border-radius: 50%;
975 width: .88rem;
976 height: .88rem;
977 margin: -.95px;
978 background-color: #750EF4;
979 border: 1px solid #E2CBFF;
980 line-height: 1.14285714;
981 outline: 0;
982 }
983 input[type=radio]:focus {
984 border-color: #D0D5DD;
985 box-shadow: none;
986 outline: 0;
987 }
988 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > input::placeholder,
989 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > textarea::placeholder{
990 color: #C6CBD2 !important;
991 }
992 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-footer {
993 padding: 16px 36px;
994 margin-bottom: 0;
995 border-top: 1px solid #EAECF0;
996 }
997 input:focus,
998 textarea:focus {
999 box-shadow: none !important;
1000 outline: 0 !important;
1001 }
1002 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons {
1003 display: flex;
1004 align-items: center;
1005 justify-content: flex-start;
1006 }
1007 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-footer .wpinsights-submit-btn {
1008 background: conic-gradient(from 195.22deg at 68.31% 39.29%, #8f20fb00, #8f20fb 360deg), linear-gradient(0deg, #6f0af2, #6f0af2);
1009 -webkit-border-radius: 8px;
1010 border-radius: 8px;
1011 color: #fff;
1012 padding: 8px 16px;
1013 font-size: 14px;
1014 font-weight: 500;
1015 line-height: 1.5em;
1016 text-transform: capitalize;
1017 transition: .3s;
1018 }
1019 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-footer .wpinsights-submit-btn:hover {
1020 background: conic-gradient(from 195.22deg at 68.31% 39.29%, #8f20fb00, #8f20fb 360deg), linear-gradient(0deg, #6f0af2, #6f0af2);
1021 }
1022
1023 .wpinsights-goodbye-form-wrapper-essential_adons_elementor .wpinsights-goodbye-form-footer .wpsp-put-deactivate-btn {
1024 font-size: 14px;
1025 font-weight: 500;
1026 color: #344054;
1027 margin-left: 10px;
1028 }
1029 .wp-person a:focus .gravatar, a:focus, a:focus .media-icon img, a:focus .plugin-icon {
1030 color: #043959;
1031 box-shadow: none;
1032 outline: 0;
1033 }
1034
1035 ';
1036 $styles .= '</style>';
1037
1038 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1039 echo $styles;
1040 ?>
1041 <script type="text/javascript">
1042 jQuery(document).ready(function($){
1043 $("#wpinsights-goodbye-link-<?php echo esc_js( $class_plugin_name ); ?>").on("click",function(){
1044 // We'll send the user to this deactivation link when they've completed or dismissed the form
1045 var url = document.getElementById("wpinsights-goodbye-link-<?php echo esc_js( $class_plugin_name ); ?>");
1046 $('body').toggleClass('wpinsights-form-active-<?php echo esc_js( $class_plugin_name ); ?>');
1047 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_js( $class_plugin_name ); ?> #wpinsights-goodbye-form").fadeIn();
1048 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_js( $class_plugin_name ); ?> #wpinsights-goodbye-form").html( '<?php
1049 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1050 echo $html; ?>' + '<div class="wpinsights-goodbye-form-footer"><div class="wpinsights-goodbye-form-buttons"><a id="wpinsights-submit-form-<?php echo esc_js( $class_plugin_name ); ?>" class="wpinsights-submit-btn" href="#"><?php esc_html_e( 'Submit and Deactivate', 'essential-addons-for-elementor-lite' ); ?></a>&nbsp;<a class="wpsp-put-deactivate-btn" href="'+url+'"><?php esc_html_e( 'Just Deactivate', 'essential-addons-for-elementor-lite' ); ?></a></div></div>');
1051 $('#wpinsights-submit-form-<?php echo esc_js( $class_plugin_name ); ?>').on('click', function(e){
1052 // As soon as we click, the body of the form should disappear
1053 $("#wpinsights-goodbye-form-<?php echo esc_js( $class_plugin_name ); ?> .wpinsights-goodbye-form-body").fadeOut();
1054 $("#wpinsights-goodbye-form-<?php echo esc_js( $class_plugin_name ); ?> .wpinsights-goodbye-form-footer").fadeOut();
1055 // Fade in spinner
1056 $("#wpinsights-goodbye-form-<?php echo esc_js( $class_plugin_name ); ?> .deactivating-spinner").fadeIn();
1057 e.preventDefault();
1058 var checkedInput = $("input[name='wpinsights-<?php echo esc_attr( $class_plugin_name ); ?>-goodbye-options']:checked"),
1059 checkedInputVal, details;
1060 if( checkedInput.length > 0 ) {
1061 checkedInputVal = checkedInput.val();
1062 details = $('input[name="'+ checkedInput[0].id +'"], textarea[name="'+ checkedInput[0].id +'"]').val();
1063 }
1064
1065 if( typeof details === 'undefined' ) {
1066 details = '';
1067 }
1068 if( typeof checkedInputVal === 'undefined' ) {
1069 checkedInputVal = 'No Reason';
1070 }
1071
1072 var data = {
1073 'action': 'deactivation_form_<?php echo esc_attr( $class_plugin_name ); ?>',
1074 'values': checkedInputVal,
1075 'details': details,
1076 'security': "<?php
1077 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1078 echo wp_create_nonce ( 'wpins_deactivation_nonce' ); ?>",
1079 'dataType': "json"
1080 }
1081
1082 $.post(
1083 ajaxurl,
1084 data,
1085 function(response){
1086 // Redirect to original deactivation URL
1087 window.location.href = url;
1088 }
1089 );
1090 });
1091 $('#wpinsights-goodbye-options > ul ').on('click', 'li label, li > input', function( e ){
1092 var parent = $(this).parents('li');
1093 parent.siblings().find('label').next('input, textarea').css('display', 'none');
1094 parent.find('label').next('input, textarea').css('display', 'block');
1095 });
1096 // If we click outside the form, the form will close
1097 $('.wpinsights-goodbye-form-bg, #wpinsights-goodbye-form > .ea__modal-close-btn').on('click',function(){
1098 $("#wpinsights-goodbye-form").fadeOut();
1099 $('body').removeClass('wpinsights-form-active-<?php echo esc_attr( $class_plugin_name ); ?>');
1100 });
1101 });
1102 });
1103 </script>
1104 <?php }
1105
1106 /**
1107 * Get Used Elements Count
1108 * Get eael all used elements from all pages
1109 * @return array
1110 *
1111 * @since 3.7.0
1112 */
1113 public static function get_used_elements_count() {
1114 $used_elements = [];
1115
1116 // First, try to get data from the new Elementor options table (prioritized)
1117 $global_usage = get_option( 'elementor_controls_usage', [] );
1118 if ( ! empty( $global_usage ) && is_array( $global_usage ) ) {
1119 $used_elements = self::extract_elements_from_global_usage( $global_usage );
1120 }
1121
1122 // If no data from options table or for backward compatibility, check post meta
1123 if ( empty( $used_elements ) ) {
1124 $used_elements = self::extract_elements_from_post_meta();
1125 }
1126
1127 return $used_elements;
1128 }
1129
1130 /**
1131 * Extract elements from new global usage data structure
1132 *
1133 * @param array $global_usage Global usage data from elementor_controls_usage option
1134 * @return array Used elements count
1135 *
1136 * @since 6.3.3
1137 */
1138 private static function extract_elements_from_global_usage( $global_usage ) {
1139 $used_elements = [];
1140 $replace_widget_name = array_flip( Elements_Manager::replace_widget_name() );
1141
1142 // Iterate through document types (wp-post, wp-page, etc.)
1143 foreach ( $global_usage as $doc_type => $elements ) {
1144 if ( ! is_array( $elements ) ) {
1145 continue;
1146 }
1147
1148 // Iterate through element types within each document type
1149 foreach ( $elements as $element_type => $element_data ) {
1150 if ( ! is_array( $element_data ) || ! isset( $element_data['count'] ) ) {
1151 continue;
1152 }
1153
1154 $element_name = $element_type;
1155 $count = (int) $element_data['count'];
1156
1157 // Handle widget name replacements
1158 if ( isset( $replace_widget_name[ $element_name ] ) ) {
1159 $element_name = $replace_widget_name[ $element_name ];
1160 }
1161
1162 // Only count Essential Addons elements
1163 if ( strpos( $element_name, 'eael-' ) === 0 ) {
1164 $used_elements[ $element_name ] = isset( $used_elements[ $element_name ] )
1165 ? $used_elements[ $element_name ] + $count
1166 : $count;
1167 }
1168
1169 // Check for extension usage in controls data
1170 if ( isset( $element_data['controls'] ) && is_array( $element_data['controls'] ) ) {
1171 self::extract_extension_usage_from_controls( $element_data['controls'], $used_elements );
1172 }
1173 }
1174 }
1175
1176 return $used_elements;
1177 }
1178
1179 /**
1180 * Extract elements from legacy post meta approach (backward compatibility)
1181 *
1182 * @return array Used elements count
1183 *
1184 * @since 6.3.3
1185 */
1186 private static function extract_elements_from_post_meta() {
1187 global $wpdb;
1188
1189 $sql = "SELECT `post_id`
1190 FROM $wpdb->postmeta
1191 WHERE `meta_key` = '_eael_widget_elements'";
1192
1193 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
1194 $post_ids = $wpdb->get_col( $sql );
1195 $used_elements = [];
1196
1197 foreach ( $post_ids as $post_id ) {
1198 $ea_elements = get_post_meta( (int) $post_id, '_eael_widget_elements', true );
1199 $el_controls = get_post_meta( (int) $post_id, '_elementor_controls_usage', true );
1200
1201 if ( empty( $ea_elements ) || empty( $el_controls ) || ! is_array( $ea_elements ) || ! is_array( $el_controls ) ) {
1202 continue;
1203 }
1204
1205 $replace_widget_name = array_flip( Elements_Manager::replace_widget_name() );
1206
1207 foreach ( $ea_elements as $element ) {
1208 $element_name = "eael-{$element}";
1209 $count = 0;
1210
1211 if ( isset( $replace_widget_name[ $element_name ] ) ) {
1212 $element_name = $replace_widget_name[ $element_name ];
1213 }
1214
1215 if ( ! empty( $el_controls[ $element_name ] ) && is_array( $el_controls[ $element_name ] ) ) {
1216 $count = $el_controls[ $element_name ]['count'];
1217 }
1218
1219 $used_elements[ $element_name ] = isset( $used_elements[ $element_name ] )
1220 ? $used_elements[ $element_name ] + $count
1221 : $count;
1222 }
1223
1224 // Extract extension usage from controls
1225 self::extract_extension_usage_from_controls( $el_controls, $used_elements );
1226 }
1227
1228 return $used_elements;
1229 }
1230
1231 /**
1232 * Extract extension usage from controls data
1233 *
1234 * @param array $controls Controls data
1235 * @param array &$used_elements Reference to used elements array
1236 *
1237 * @since 6.3.3
1238 */
1239 private static function extract_extension_usage_from_controls( $controls, &$used_elements ) {
1240 array_walk_recursive( $controls, function ( $value, $key ) use ( &$used_elements ) {
1241 $element_name = '';
1242
1243 if ( $key === 'eael_particle_switch' ) {
1244 $element_name = 'eael-section-particles';
1245 } elseif ( $key === 'eael_parallax_switcher' ) {
1246 $element_name = 'eael-section-parallax';
1247 } elseif ( $key === 'eael_tooltip_section_enable' ) {
1248 $element_name = 'eael-tooltip-section';
1249 } elseif ( $key === 'eael_ext_content_protection' ) {
1250 $element_name = 'eael-content-protection';
1251 } elseif ( $key === 'eael_cl_enable' ) {
1252 $element_name = 'eael-conditional-display';
1253 } elseif ( $key === 'eael_ext_advanced_dynamic_tags' ) {
1254 $element_name = 'eael-advanced-dynamic-tags';
1255 } elseif ( $key === 'eael_enable_custom_cursor' ) {
1256 $element_name = 'eael-custom-cursor';
1257 } elseif ( $key === 'eael_liquid_glass_effect_switch' ) {
1258 $element_name = 'eael-liquid-glass-effect';
1259 } elseif ( $key === 'eael_wrapper_link_switch' ) {
1260 $element_name = 'eael-wrapper-link';
1261 } elseif ( $key === 'eael_smooth_animation_section' ) {
1262 $element_name = 'eael-smooth-animation';
1263 } elseif ( $key === 'eael_hover_effect_switch' ) {
1264 $element_name = 'eael-special-hover-effect';
1265 }
1266
1267 if ( ! empty( $element_name ) ) {
1268 $used_elements[ $element_name ] = isset( $used_elements[ $element_name ] )
1269 ? $used_elements[ $element_name ] + $value
1270 : $value;
1271 }
1272 } );
1273 }
1274 }
1275