PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.2.0
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.2.0
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / Utils / Insights.php

Insights.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.2.0, at includes/Utils/Insights.php

1,130 lines 44.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace WPDeveloper\BetterDocs\Utils;
3
4 use AllowDynamicProperties;
5
6 /**
7 * Exit if accessed directly
8 */
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 #[AllowDynamicProperties]
14
15 class Insights {
16 /**
17 * WP Insights Version
18 */
19 const WPINS_VERSION = '3.0.1';
20 /**
21 * API URL
22 */
23 const API_URL = 'https://send.wpinsight.com/process-plugin-data';
24 /**
25 * Installed Plugin File
26 *
27 * @var string
28 */
29 private $plugin_file = null;
30 /**
31 * Installed Plugin Name
32 *
33 * @var string
34 */
35 private $plugin_name = null;
36 /**
37 * How often the event should subsequently
38 *
39 * @var string
40 */
41 public $recurrence = 'daily';
42 private $event_hook = null;
43 private $has_notice = false;
44 private $disabled_wp_cron = false;
45 private $enable_self_cron = false;
46 private $require_optin = false;
47 private $include_goodbye_form = false;
48 private $marketing = false;
49 private $options = [];
50 private $notice_options = [];
51 private $item_id = false;
52 /**
53 * Instace of BetterDocs_Plugin_Usage_Tracker
54 *
55 * @var BetterDocs_Plugin_Usage_Tracker
56 */
57 private static $_instance = null;
58 /**
59 * Get Instance of BetterDocs_Plugin_Usage_Tracker
60 *
61 * @return BetterDocs_Plugin_Usage_Tracker
62 */
63 public static function get_instance( $plugin_file, $args = [] ) {
64 if ( is_null( static::$_instance ) ) {
65 static::$_instance = new static( $plugin_file, $args );
66 }
67 return static::$_instance;
68 }
69 /**
70 * Automatically Invoked when initialized.
71 *
72 * @param array $args
73 */
74 public function __construct( $plugin_file, $args = [] ) {
75 $this->plugin_file = $plugin_file;
76 $this->plugin_name = basename( $this->plugin_file, '.php' );
77 $this->disabled_wp_cron = defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON == true;
78 $this->enable_self_cron = $this->disabled_wp_cron == true ? true : false;
79
80 $this->event_hook = 'put_do_weekly_action';
81
82 $this->require_optin = isset( $args['opt_in'] ) ? $args['opt_in'] : true;
83 $this->include_goodbye_form = isset( $args['goodbye_form'] ) ? $args['goodbye_form'] : true;
84 $this->marketing = isset( $args['email_marketing'] ) ? $args['email_marketing'] : true;
85 $this->options = isset( $args['options'] ) ? $args['options'] : [];
86 $this->item_id = isset( $args['item_id'] ) ? $args['item_id'] : false;
87 /**
88 * Activation Hook
89 */
90 register_activation_hook( $this->plugin_file, array( $this, 'activate_this_plugin' ) );
91 /**
92 * Deactivation Hook
93 */
94 register_deactivation_hook( $this->plugin_file, array( $this, 'deactivate_this_plugin' ) );
95 }
96 /**
97 * When user agreed to opt-in tracking schedule is enabled.
98 *
99 * @since 2.5.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 *
124 * @since 2.5.0
125 */
126 public function deactivate_this_plugin() {
127 /**
128 * Check tracking is allowed or not.
129 */
130 $allow_tracking = $this->is_tracking_allowed();
131 if ( ! $allow_tracking ) {
132 return;
133 }
134 $body = $this->get_data();
135 $body['status'] = 'Deactivated';
136 $body['deactivated_date'] = time();
137
138 // Check deactivation reason and add for insights data.
139 if ( false !== get_option( 'wpins_deactivation_reason_' . $this->plugin_name ) ) {
140 $body['deactivation_reason'] = get_option( 'wpins_deactivation_reason_' . $this->plugin_name );
141 }
142 if ( false !== get_option( 'wpins_deactivation_details_' . $this->plugin_name ) ) {
143 $body['deactivation_details'] = get_option( 'wpins_deactivation_details_' . $this->plugin_name );
144 }
145
146 $this->send_data( $body );
147 delete_option( 'wpins_deactivation_reason_' . $this->plugin_name );
148 delete_option( 'wpins_deactivation_details_' . $this->plugin_name );
149 /**
150 * Clear the event schedule.
151 */
152 if ( ! $this->disabled_wp_cron ) {
153 wp_clear_scheduled_hook( $this->event_hook );
154 }
155 }
156 /**
157 * Initial Method to Hook Everything.
158 *
159 * @return void
160 */
161 public function init() {
162 add_action( 'wpdeveloper_notice_clicked_for_' . $this->plugin_name, array( $this, 'clicked' ) );
163 add_action( $this->event_hook, array( $this, 'do_tracking' ) );
164 // For Test
165 add_action( 'wpdeveloper_optin_notice_for_' . $this->plugin_name, array( $this, 'notice' ) );
166 /**
167 * Deactivation Reason Form and Submit Data to Insights.
168 */
169 if ( ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ) ) {
170 add_filter( 'plugin_action_links_' . plugin_basename( $this->plugin_file ), array( $this, 'deactivate_action_links' ) );
171 add_action( 'admin_print_footer_scripts', array( $this, 'notice_script' ) );
172 add_action( 'admin_footer-plugins.php', array( $this, 'deactivate_reasons_form' ) );
173 add_action( 'wp_ajax_deactivation_form_' . esc_attr( $this->plugin_name ), array( $this, 'deactivate_reasons_form_submit' ) );
174 }
175 }
176 /**
177 * For Redirecting Current Page without Arguments!
178 *
179 * @return string
180 */
181 private function redirect_to() {
182 $request_payload = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : ''; //phpcs:ignore -- Slash Is Needed Here Because This Is An Url
183 $request_uri = wp_parse_url( $request_payload, PHP_URL_PATH );
184 $query_string = wp_parse_url( $request_payload, PHP_URL_QUERY );
185 parse_str( $query_string, $current_url );
186
187 $unset_array = array( 'dismiss', 'plugin', '_wpnonce', 'later', 'plugin_action', 'marketing_optin' );
188
189 foreach ( $unset_array as $value ) {
190 if ( isset( $current_url[ $value ] ) ) {
191 unset( $current_url[ $value ] );
192 }
193 }
194
195 $current_url = http_build_query( $current_url );
196 $redirect_url = $request_uri . '?' . $current_url;
197 return $redirect_url;
198 }
199 /**
200 * This method forcing the do_tracking method to execute instant.
201 *
202 * @return void
203 */
204 public function force_tracking() {
205 $this->do_tracking( true );
206 }
207 /**
208 * This method is responsible for all the magic from the front of the plugin.
209 *
210 * @since 2.5.0
211 * @param $force Force tracking if it's not the correct time to track/
212 */
213 public function do_tracking( $force = false ) {
214 /**
215 * Check URL is set or not.
216 */
217 if ( empty( self::API_URL ) ) {
218 return;
219 }
220 /**
221 * Check is tracking allowed or not.
222 */
223 if ( ! $this->is_tracking_allowed() ) {
224 return;
225 }
226 /**
227 * Check is this the correct time to track or not.
228 * or Force to track.
229 */
230 if ( ! $this->is_time_to_track() && ! $force ) {
231 return;
232 }
233 /**
234 * Get All Data.
235 */
236 $body = $this->get_data();
237 /**
238 * Send all data.
239 */
240 return $this->send_data( $body );
241 }
242 /**
243 * Is tracking allowed?
244 *
245 * @since 1.0.0
246 */
247 private function is_tracking_allowed() {
248 // First, check if the user has changed their mind and opted out of tracking
249 if ( $this->has_user_opted_out() ) {
250 $this->set_is_tracking_allowed( false, $this->plugin_name );
251 return false;
252 }
253 // The wpins_allow_tracking option is an array of plugins that are being tracked
254 $allow_tracking = get_option( 'wpins_allow_tracking' );
255 // If this plugin is in the array, then tracking is allowed
256 if ( isset( $allow_tracking[ $this->plugin_name ] ) ) {
257 return true;
258 }
259 return false;
260 }
261 /**
262 * Set a flag in DB If tracking is allowed.
263 *
264 * @since 2.5.0
265 * @param $is_allowed Boolean true if is allowed.
266 */
267 public function set_is_tracking_allowed( $is_allowed, $plugin = null ) {
268 if ( empty( $plugin ) ) {
269 $plugin = $this->plugin_name;
270 }
271 /**
272 * Get All Tracked Plugin List using this Tracker.
273 */
274 $allow_tracking = get_option( 'wpins_allow_tracking' );
275 /**
276 * Check user is opted out for tracking or not.
277 */
278 if ( $this->has_user_opted_out() ) {
279 if ( isset( $allow_tracking[ $plugin ] ) ) {
280 unset( $allow_tracking[ $plugin ] );
281 }
282 } elseif ( $is_allowed || ! $this->require_optin ) {
283 /**
284 * If user has agreed to allow tracking
285 */
286 if ( empty( $allow_tracking ) || ! is_array( $allow_tracking ) ) {
287 $allow_tracking = array( $plugin => $plugin );
288 } else {
289 $allow_tracking[ $plugin ] = $plugin;
290 }
291 } elseif ( isset( $allow_tracking[ $plugin ] ) ) {
292 unset( $allow_tracking[ $plugin ] );
293 }
294 update_option( 'wpins_allow_tracking', $allow_tracking, 'no' );
295 }
296
297 /**
298 * Check the user has opted out or not.
299 *
300 * @since 2.5.0
301 * @return boolean
302 */
303 protected function has_user_opted_out() {
304 if ( ! empty( $this->options ) ) {
305 foreach ( $this->options as $option_name ) {
306 $options = get_option( $option_name );
307 if ( ! empty( $options['wpins_opt_out'] ) ) {
308 return true;
309 }
310 }
311 }
312 return false;
313 }
314 /**
315 * Check if it's time to track
316 *
317 * @since 2.5.0
318 */
319 public function is_time_to_track() {
320 $track_times = get_option( 'wpins_last_track_time', array() );
321 return ! isset( $track_times[ $this->plugin_name ] ) ? true :
322 ( ( isset( $track_times[ $this->plugin_name ] ) && $track_times[ $this->plugin_name ] ) < strtotime( '-1 day' ) ? true : false );
323 }
324 /**
325 * Set tracking time.
326 *
327 * @since 2.5.0
328 */
329 public function set_track_time() {
330 $track_times = get_option( 'wpins_last_track_time', array() );
331 $track_times[ $this->plugin_name ] = time();
332 update_option( 'wpins_last_track_time', $track_times, 'no' );
333 }
334 /**
335 * This method is responsible for collecting all data.
336 *
337 * @since 2.5.0
338 */
339 public function get_data() {
340 $body = array(
341 'plugin_slug' => sanitize_text_field( $this->plugin_name ),
342 'url' => get_bloginfo( 'url' ),
343 'site_name' => get_bloginfo( 'name' ),
344 'site_version' => get_bloginfo( 'version' ),
345 'site_language' => get_bloginfo( 'language' ),
346 'charset' => get_bloginfo( 'charset' ),
347 'wpins_version' => self::WPINS_VERSION,
348 'php_version' => phpversion(),
349 'multisite' => is_multisite(),
350 'file_location' => __FILE__,
351 );
352
353 // Collect the email if the correct option has been set
354 if ( $this->marketing ) {
355 if ( ! function_exists( 'wp_get_current_user' ) ) {
356 include ABSPATH . 'wp-includes/pluggable.php';
357 }
358 $current_user = wp_get_current_user();
359 $email = $current_user->user_email;
360 if ( is_email( $email ) ) {
361 $body['email'] = $email;
362 }
363 }
364 $body['marketing_method'] = $this->marketing;
365 $body['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : ''; //phpcs:ignore
366
367 /**
368 * Collect all active and inactive plugins
369 */
370 if ( ! function_exists( 'get_plugins' ) ) {
371 include ABSPATH . '/wp-admin/includes/plugin.php';
372 }
373 $plugins = array_keys( get_plugins() );
374 $active_plugins = is_network_admin() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : get_option( 'active_plugins', array() );
375 foreach ( $plugins as $key => $plugin ) {
376 if ( in_array( $plugin, $active_plugins ) ) {
377 unset( $plugins[ $key ] );
378 }
379 }
380 $body['active_plugins'] = $active_plugins;
381 $body['inactive_plugins'] = $plugins;
382
383 /**
384 * Text Direction.
385 */
386 $body['text_direction'] = ( function_exists( 'is_rtl' ) ? ( is_rtl() ? 'RTL' : 'LTR' ) : 'NOT SET' );
387 /**
388 * Get Our Plugin Data.
389 *
390 * @since 2.5.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.', 'betterdocs' );
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 *
409 * @since 2.5.0
410 */
411 $theme = wp_get_theme();
412 if ( $theme->Name ) {
413 $body['theme'] = sanitize_text_field( $theme->Name );
414 }
415 if ( $theme->Version ) {
416 $body['theme_version'] = sanitize_text_field( $theme->Version );
417 }
418 return $body;
419 }
420
421 /**
422 * Collect plugin data,
423 * Retrieve current plugin information
424 *
425 * @since 2.5.0
426 */
427 public function plugin_data() {
428 if ( ! function_exists( 'get_plugin_data' ) ) {
429 include ABSPATH . '/wp-admin/includes/plugin.php';
430 }
431 $plugin = get_plugin_data( $this->plugin_file );
432 return $plugin;
433 }
434 /**
435 * Send the data to insights.
436 *
437 * @since 2.5.0
438 */
439 public function send_data( $body ) {
440 /**
441 * Get SITE ID
442 */
443 $site_id_key = "wpins_{$this->plugin_name}_site_id";
444 $site_id = get_option( $site_id_key, false );
445 $failed_data = [];
446 $site_url = get_bloginfo( 'url' );
447 $original_site_url = get_option( "wpins_{$this->plugin_name}_original_url", false );
448 if ( $original_site_url === false && version_compare( $body['wpins_version'], '3.0.1', '==' ) ) {
449 $site_id = false;
450 }
451 /**
452 * Send Initial Data to API
453 */
454 if ( $site_id == false && $this->item_id !== false && $original_site_url === false ) {
455 if ( isset( $_SERVER['REMOTE_ADDR'] ) && ! empty( $_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1' ) ) { //phpcs:ignore
456 $country_request = wp_remote_get( 'http://ip-api.com/json/' . $_SERVER['REMOTE_ADDR'] . '?fields=country' ); //phpcs:ignore
457 if ( ! is_wp_error( $country_request ) && $country_request['response']['code'] == 200 ) {
458 $ip_data = json_decode( $country_request['body'] );
459 $body['country'] = isset( $ip_data->country ) ? $ip_data->country : 'NOT SET';
460 }
461 }
462
463 $body['plugin_slug'] = $this->plugin_name;
464 $body['url'] = $site_url;
465 $body['item_id'] = $this->item_id;
466
467 $request = $this->remote_post( $body );
468 if ( ! is_wp_error( $request ) && $request['response']['code'] == 200 ) {
469 $retrieved_body = json_decode( wp_remote_retrieve_body( $request ), true );
470 if ( is_array( $retrieved_body ) && isset( $retrieved_body['siteId'] ) ) {
471 update_option( $site_id_key, $retrieved_body['siteId'], 'no' );
472 update_option( "wpins_{$this->plugin_name}_original_url", $site_url, 'no' );
473 update_option( "wpins_{$this->plugin_name}_{$retrieved_body['siteId']}", $body, 'no' );
474 }
475 } else {
476 $failed_data = $body;
477 }
478 }
479
480 $site_id_data_key = "wpins_{$this->plugin_name}_{$site_id}";
481 $site_id_data_failed_key = "wpins_{$this->plugin_name}_{$site_id}_send_failed";
482
483 if ( $site_id != false ) {
484 $old_sent_data = get_option( $site_id_data_key, [] );
485 $diff_data = $this->diff( $body, $old_sent_data );
486 $failed_data = get_option( $site_id_data_failed_key, [] );
487 if ( ! empty( $failed_data ) && $diff_data != $failed_data ) {
488 $failed_data = array_merge( $failed_data, $diff_data );
489 }
490 }
491
492 if ( ! empty( $failed_data ) && $site_id != false ) {
493 $failed_data['plugin_slug'] = $this->plugin_name;
494 $failed_data['url'] = $site_url;
495 $failed_data['site_id'] = $site_id;
496 if ( $original_site_url != false ) {
497 $failed_data['original_url'] = $original_site_url;
498 }
499
500 $request = $this->remote_post( $failed_data );
501 if ( ! is_wp_error( $request ) ) {
502 delete_option( $site_id_data_failed_key );
503 $replaced_data = array_merge( $old_sent_data, $failed_data );
504 update_option( $site_id_data_key, $replaced_data, 'no' );
505 }
506 }
507
508 if ( ! empty( $diff_data ) && $site_id != false && empty( $failed_data ) ) {
509 $diff_data['plugin_slug'] = $this->plugin_name;
510 $diff_data['url'] = $site_url;
511 $diff_data['site_id'] = $site_id;
512 if ( $original_site_url != false ) {
513 $diff_data['original_url'] = $original_site_url;
514 }
515
516 $request = $this->remote_post( $diff_data );
517 if ( is_wp_error( $request ) ) {
518 update_option( $site_id_data_failed_key, $diff_data, 'no' );
519 } else {
520 $replaced_data = array_merge( $old_sent_data, $diff_data );
521 update_option( $site_id_data_key, $replaced_data, 'no' );
522 }
523 }
524
525 $this->set_track_time();
526
527 if ( isset( $request ) && is_wp_error( $request ) ) {
528 return $request;
529 }
530
531 if ( isset( $request ) ) {
532 return true;
533 }
534 return false;
535 }
536 /**
537 * WP_REMOTE_POST method responsible for send data to the API_URL
538 *
539 * @param array $data
540 * @param array $args
541 * @return \WP_Error|array|null
542 */
543 protected function remote_post( $data = array(), $args = array() ) {
544 if ( empty( $data ) ) {
545 return;
546 }
547
548 $args = wp_parse_args(
549 $args,
550 array(
551 'method' => 'POST',
552 'timeout' => 30,
553 'redirection' => 5,
554 'httpversion' => '1.1',
555 'blocking' => true,
556 'body' => $data,
557 'user-agent' => 'PUT/1.0.0; ' . get_bloginfo( 'url' ),
558 )
559 );
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
566 return $request;
567 }
568 /**
569 * Difference between old and new data
570 *
571 * @param array $new_data
572 * @param array $old_data
573 * @return array
574 */
575 protected function diff( $new_data, $old_data ) {
576 $data = [];
577 if ( ! empty( $new_data ) ) {
578 foreach ( $new_data as $key => $value ) {
579 if ( isset( $old_data[ $key ] ) ) {
580 if ( $old_data[ $key ] == $value ) {
581 continue;
582 }
583 }
584 $data[ $key ] = $value;
585 }
586 }
587 return $data;
588 }
589 /**
590 * Display the admin notice to users to allow them to opt in
591 *
592 * @since 2.5.0
593 */
594 public function notice() {
595 /**
596 * Return if notice is not set.
597 */
598 if ( ! isset( $this->notice_options['notice'] ) ) {
599 return;
600 }
601 /**
602 * Check is allowed or blocked for notice.
603 */
604 $block_notice = get_option( 'wpins_block_notice' );
605 if ( isset( $block_notice[ $this->plugin_name ] ) ) {
606 return;
607 }
608 if ( ! current_user_can( 'manage_options' ) ) {
609 return;
610 }
611
612 $this->has_notice = true;
613
614 $url_yes = add_query_arg(
615 [
616 'plugin' => $this->plugin_name,
617 'plugin_action' => 'yes',
618 ]
619 );
620
621 $url_no = add_query_arg(
622 [
623 'plugin' => $this->plugin_name,
624 'plugin_action' => 'no',
625 ]
626 );
627
628 $url_yes = wp_nonce_url( $url_yes, '_wpnonce_optin_' . $this->plugin_name );
629 $url_no = wp_nonce_url( $url_no, '_wpnonce_optin_' . $this->plugin_name );
630
631 // Decide on notice text
632 $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-' . esc_attr( $this->plugin_name ) . '-collect" >' . $this->notice_options['consent_button_text'] . '</a>';
633 $extra_notice_text = $this->notice_options['extra_notice'];
634
635 ?>
636
637 <div class="nx-optin">
638 <p><?php echo wp_kses_post( $notice_text ); ?></p>
639 <div class="wpinsights-data" style="display: none;">
640 <p><?php echo wp_kses_post( $extra_notice_text ); ?></p>
641 </div>
642 <p>
643 <a href="<?php echo esc_url( $url_yes ); ?>" class="button-primary">
644 <?php echo esc_html( $this->notice_options['yes'] ); ?>
645 </a>&nbsp;
646 <a href="<?php echo esc_url( $url_no ); ?>" class="button-secondary">
647 <?php echo esc_html( $this->notice_options['no'] ); ?>
648 </a>
649 </p>
650 </div>
651
652 <?php
653 }
654
655 public function notice_script() {
656 if ( $this->has_notice ) {
657 echo "<script type='text/javascript'>jQuery('.wpinsights-" . esc_attr( $this->plugin_name ) . "-collect').on('click', function(e) {e.preventDefault();jQuery('.wpinsights-data').slideToggle('fast');});</script>";
658 }
659 }
660 /**
661 * Set all notice options to customized notice.
662 *
663 * @since 2.5.0
664 * @param array $options
665 * @return void
666 */
667 public function set_notice_options( $options = [] ) {
668 $default_options = [
669 'consent_button_text' => __( 'What we collect.', 'betterdocs' ),
670 'yes' => __( 'Sure, I\'d like to help', 'betterdocs' ),
671 'no' => __( 'No Thanks.', 'betterdocs' ),
672 ];
673 $options = wp_parse_args( $options, $default_options );
674 $this->notice_options = $options;
675 }
676 /**
677 * Responsible for track the click from Notice.
678 *
679 * @return void
680 */
681 public function clicked( $notice = null ) {
682 if ( isset( $_GET['_wpnonce'] ) && isset( $_GET['plugin'] ) && isset( $_GET['plugin_action'] ) ) {
683 if ( isset( $_GET['tab'] ) && $_GET['tab'] === 'plugin-information' ) {
684 return;
685 }
686
687 if( ! wp_verify_nonce( $_GET[ '_wpnonce' ], '_wpnonce_optin_' . $this->plugin_name ) ) { //phpcs:ignore -- Nonce Sanitization Is Not Needed Here, Because This Is Generated By WP Core Function
688 return;
689 }
690
691 $plugin = sanitize_text_field( $_GET['plugin'] ); //phpcs:ignore -- Text's Are Sanitized Here, Not Strings With Url's
692 $action = sanitize_text_field( $_GET['plugin_action'] ); //phpcs:ignore -- Text's Are Sanitized Here, Not Strings With Url's
693 if ( $action == 'yes' ) {
694 $this->schedule_tracking();
695 $this->set_is_tracking_allowed( true, $plugin );
696 if ( $this->do_tracking( true ) ) {
697 $this->update_block_notice( $plugin );
698 }
699 } else {
700 $this->set_is_tracking_allowed( false, $plugin );
701 $this->update_block_notice( $plugin );
702 }
703
704 if ( ! is_null( $notice ) ) {
705 $notice->dismiss->dismiss_notice();
706 }
707
708 /**
709 * Redirect User To the Current URL, but without set query arguments.
710 */
711 wp_safe_redirect( $this->redirect_to() );
712 }
713 }
714 /**
715 * Set if we should block the opt-in notice for this plugin
716 *
717 * @since 2.5.0
718 */
719 public function update_block_notice( $plugin = null ) {
720 if ( empty( $plugin ) ) {
721 $plugin = $this->plugin_name;
722 }
723 $block_notice = get_option( 'wpins_block_notice' );
724 if ( empty( $block_notice ) || ! is_array( $block_notice ) ) {
725 $block_notice = array( $plugin => $plugin );
726 } else {
727 $block_notice[ $plugin ] = $plugin;
728 }
729 update_option( 'wpins_block_notice', $block_notice, 'no' );
730 }
731 /**
732 * AJAX callback when the deactivated form is submitted.
733 *
734 * @since 2.5.0
735 */
736 public function deactivate_reasons_form_submit() {
737 check_ajax_referer( 'wpins_deactivation_nonce', 'security' );
738 if ( isset( $_POST['values'] ) ) {
739 $values = sanitize_text_field( $_POST['values'] ); //phpcs:ignore -- Text's Are Sanitized Here, Not Strings With Url's
740 update_option( 'wpins_deactivation_reason_' . $this->plugin_name, $values );
741 }
742 if ( isset( $_POST['details'] ) ) {
743 $details = sanitize_text_field( $_POST['details'] ); //phpcs:ignore -- Text's Are Sanitized Here, Not Strings With Url's
744 update_option( 'wpins_deactivation_details_' . $this->plugin_name, $details );
745 }
746 wp_die();
747 }
748 /**
749 * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
750 *
751 * @since 2.5.0
752 */
753 public function deactivate_action_links( $links ) {
754 /**
755 * Check is tracking allowed or not.
756 */
757 if ( ! $this->is_tracking_allowed() ) {
758 return $links;
759 }
760 if ( isset( $links['deactivate'] ) && $this->include_goodbye_form ) {
761 $deactivation_link = $links['deactivate'];
762 /**
763 * Change the default deactivate button link.
764 */
765 $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 );
766 $links['deactivate'] = $deactivation_link;
767 }
768 return $links;
769 }
770 /**
771 * ALL Deactivate Reasons.
772 *
773 * @since 2.5.0
774 */
775 public function deactivation_reasons() {
776 $form = array();
777 $form['heading'] = __( 'We Value Your Feedback', 'betterdocs' );
778 $form['body'] = __( "Could you please tell us why you're deactivating our plugin? Your insights will help us to improve.", 'betterdocs' );
779
780 $form['options'] = array(
781 __( 'I no longer need the plugin', 'betterdocs' ),
782 [
783 'label' => __( 'I found a better plugin', 'betterdocs' ),
784 'extra_field' => __( 'Please share which plugin', 'betterdocs' )
785 ],
786 __( "I couldn't get the plugin to work", 'betterdocs' ),
787 __( 'It\'s a temporary deactivation', 'betterdocs' ),
788 [
789 'label' => __( 'Other', 'betterdocs' ),
790 'extra_field' => __( 'Please share the reason', 'betterdocs' ),
791 'type' => 'textarea'
792 ]
793 );
794 return apply_filters( 'wpins_form_text_' . $this->plugin_name, $form );
795 }
796
797 /**
798 * Deactivate Reasons Form.
799 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
800 *
801 * @since 3.0.0
802 */
803 public function deactivate_reasons_form() {
804 $form = $this->deactivation_reasons();
805 $class_plugin_name = esc_attr( $this->plugin_name );
806 $html = '<div class="betterdocs__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="#e0fff6"/><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="#00b884" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span><h1>' . $form['heading'] . '</h1></div>';
807 $html .= '<div class="wpinsights-goodbye-form-body"><p class="wpinsights-goodbye-form-caption">' . esc_html( $form['body'] ) . '</p>';
808 if ( is_array( $form['options'] ) ) {
809 $html .= '<div id="wpinsights-goodbye-options" class="wpinsights-goodbye-options"><ul>';
810 foreach ( $form['options'] as $option ) {
811 if ( is_array( $option ) ) {
812 $id = strtolower( str_replace( ' ', '_', esc_attr( $option['label'] ) ) );
813 $id = $id . '_' . $class_plugin_name;
814 $html .= '<li class="has-goodbye-extra">';
815 $html .= '<input type="radio" name="wpinsights-' . esc_attr( $class_plugin_name ) . '-goodbye-options" id="' . esc_attr( $id ) . '" value="' . esc_attr( $option['label'] ) . '">';
816 $html .= '<div><label for="' . $id . '">' . esc_attr( $option['label'] ) . '</label>';
817 if ( isset( $option['extra_field'] ) && ! isset( $option['type'] ) ) {
818 $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'] ) . '">';
819 }
820 if ( isset( $option['extra_field'] ) && isset( $option['type'] ) ) {
821 $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'] . '>';
822 }
823 $html .= '</div></li>';
824 } else {
825 $id = strtolower( str_replace( ' ', '_', esc_attr( $option ) ) );
826 $id = $id . '_' . $class_plugin_name;
827 $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>';
828 }
829 }
830 $html .= '</ul></div><!-- .wpinsights-' . $class_plugin_name . '-goodbye-options -->';
831 }
832 $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
833 $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', 'betterdocs' ) . '</p>';
834
835 $wrapper_class = '.wpinsights-goodbye-form-wrapper-' . $class_plugin_name;
836
837 $styles = '';
838 $styles .= '<style type="text/css">';
839 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form-bg {';
840 $styles .= 'background: rgba( 0, 0, 0, .8 );position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 9;';
841 $styles .= '}';
842 $styles .= $wrapper_class . '{';
843 $styles .= 'position: relative; display: none;';
844 $styles .= '}';
845 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' ' . $wrapper_class . '{';
846 $styles .= 'display: flex !important; position: fixed;top: 0;left: 0;width: 100%;height: 100%; justify-content: center; align-items: center;';
847 $styles .= '}';
848 $styles .= $wrapper_class . ' .wpinsights-goodbye-form { display: none; }';
849 $styles .= '.wpinsights-form-active-' . $class_plugin_name . ' .wpinsights-goodbye-form {';
850 $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;';
851 $styles .= '}';
852 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-head {';
853 $styles .= 'background: #fff; color: #495157; padding: 18px; box-shadow: 0 0 8px rgba(0,0,0,.1); font-size: 15px;';
854 $styles .= '}';
855 $styles .= $wrapper_class . ' .wpinsights-goodbye-form .wpinsights-goodbye-form-head strong { font-size: 15px; }';
856 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body { padding: 8px 18px; color: #333; }';
857 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body label { padding-left: 5px; color: #6d7882; }';
858 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {';
859 $styles .= 'font-weight: 500; font-size: 15px; color: #495157; line-height: 1.4;';
860 $styles .= '}';
861 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options { padding-top: 5px; }';
862 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li { margin-bottom: 15px; }';
863 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div { display: inline; padding-left: 3px; }';
864 $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 {';
865 $styles .= 'margin: 10px 18px; padding: 8px; width: 80%;';
866 $styles .= '}';
867 $styles .= $wrapper_class . ' .deactivating-spinner { display: none; padding-bottom: 20px !important; }';
868 $styles .= $wrapper_class . ' .deactivating-spinner .spinner { float: none; margin: 4px 4px 0 18px; vertical-align: bottom; visibility: visible; }';
869 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer { padding: 8px 18px; margin-bottom: 15px; }';
870 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons { display: flex; align-items: center; justify-content: space-between; }';
871 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn {';
872 $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;';
873 $styles .= '}';
874 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn:hover {';
875 $styles .= 'background-color: #f5d0fe;';
876 $styles .= '}';
877 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {';
878 $styles .= 'font-size: 13px; color: #a4afb7; background: none; float: right; padding-right: 10px; width: auto; text-decoration: underline;';
879 $styles .= '}';
880 $styles .= $wrapper_class . ' .test {';
881 $styles .= '}';
882 $styles .= '
883
884 .wpinsights-form-active-betterdocs .wpinsights-goodbye-form-wrapper-betterdocs {
885 display: flex !important;
886 position: fixed;
887 top: 0;
888 left: 0;
889 right: 0;
890 bottom: 0;
891 width: 100%;
892 z-index: 9999;
893 height: 100%;
894 justify-content: center;
895 align-items: center;
896 }
897 .wpinsights-form-active-betterdocs .wpinsights-goodbye-form {
898 border-radius: 8px;
899 width: 563px;
900 overflow: visible;
901 position: relative;
902 }
903 .wpinsights-goodbye-form .betterdocs__modal-close-btn {
904 position: absolute;
905 top: 0;
906 right: -55px;
907 width: 40px;
908 height: 40px;
909 background: #fff;
910 border-radius: 50%;
911 display: flex;
912 justify-content: center;
913 align-items: center;
914 font-size: 12px;
915 font-weight: 500;
916 color: #475467;
917 cursor: pointer;
918 }
919 .wpinsights-goodbye-form .betterdocs__modal-close-btn svg {
920 width: 20px;
921 }
922 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-head {
923 background: #fff;
924 color: #495157;
925 padding: 24px;
926 border-radius: 8px 8px 0 0;
927 box-shadow: none;
928 border-bottom: 1px solid #EAECF0;
929 display: flex;
930 flex-direction: column;
931 gap: 16px;
932 align-items: center;
933 }
934 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-head > span {
935 display: inline-flex;
936 }
937 .wpinsights-goodbye-form-head h1 {
938 font-size: 22px;
939 font-weight: 450;
940 color: #1D2939;
941 padding: 0;
942 }
943 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body {
944 padding: 32px 40px;
945 max-height: calc(70vh - 230px);
946 overflow: auto;
947 }
948 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {
949 font-size: 18px;
950 color: #1D2939;
951 margin: 0;
952 padding-bottom: 16px;
953 font-weight: 400;
954 }
955 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body #wpinsights-goodbye-options {
956 padding-top: 0px;
957 }
958 .wpinsights-goodbye-form-wrapper-betterdocs .widefat td ul {
959 font-size: 14px;
960 margin: 0;
961 color: #475467;
962 line-height: 1.4em;
963 }
964 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li:not(:last-child) {
965 margin-bottom: 16px;
966 }
967 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li:last-child {
968 margin-bottom: 0;
969 }
970 .wpinsights-goodbye-form-wrapper-betterdocs input[type=radio] {
971 border-radius: 50%;
972 margin-right: .25rem;
973 line-height: .71428571;
974 margin: 0;
975 }
976 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body label {
977 padding-left: 4px;
978 color: #475467;
979 font-size: 14px;
980 }
981 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > input, .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > textarea {
982 padding: 10px 16px;
983 border-radius: 8px;
984 width: 100%;
985 border: 1px solid #D0D5DD;
986 margin: 0;
987 margin-top: 16px;
988 color: #1D2939;
989 font-size: 14px;
990 line-height: 1.5em;
991 resize: none;
992 max-height: 44px;
993 }
994 .wpinsights-goodbye-form-wrapper-betterdocs input[type=radio] {
995 border: 1px solid #D0D5DD;
996 box-shadow: none;
997 }
998 .wpinsights-goodbye-form-wrapper-betterdocs input[type=radio]:checked::before {
999 content: "";
1000 border-radius: 50%;
1001 width: .88rem;
1002 height: .88rem;
1003 margin: -.95px;
1004 background-color: #00b884;
1005 border: 1px solid #e0fff6;
1006 line-height: 1.14285714;
1007 outline: 0;
1008 }
1009 .wpinsights-goodbye-form-wrapper-betterdocs input[type=radio]:focus {
1010 border-color: #D0D5DD;
1011 box-shadow: none;
1012 outline: 0;
1013 }
1014 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > input::placeholder,
1015 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div > textarea::placeholder{
1016 color: #C6CBD2 !important;
1017 }
1018 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-footer {
1019 padding: 16px 36px;
1020 margin-bottom: 0;
1021 border-top: 1px solid #EAECF0;
1022 }
1023 .wpinsights-goodbye-form-wrapper-betterdocs input:focus,
1024 .wpinsights-goodbye-form-wrapper-betterdocs textarea:focus {
1025 box-shadow: none !important;
1026 outline: 0 !important;
1027 }
1028 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons {
1029 display: flex;
1030 align-items: center;
1031 justify-content: flex-start;
1032 }
1033 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-footer .wpinsights-submit-btn {
1034 background-color: #00b884;
1035 -webkit-border-radius: 8px;
1036 border-radius: 8px;
1037 color: #fff;
1038 padding: 8px 16px;
1039 font-size: 14px;
1040 font-weight: 500;
1041 line-height: 1.5em;
1042 text-transform: capitalize;
1043 transition: .3s;
1044 }
1045 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-footer .wpinsights-submit-btn:hover {
1046 background: #00b884;
1047 }
1048
1049 .wpinsights-goodbye-form-wrapper-betterdocs .wpinsights-goodbye-form-footer .wpsp-put-deactivate-btn {
1050 font-size: 14px;
1051 font-weight: 500;
1052 color: #344054;
1053 margin-left: 10px;
1054 }
1055 .wp-person a:focus .gravatar, a:focus, a:focus .media-icon img, a:focus .plugin-icon {
1056 color: #043959;
1057 box-shadow: none;
1058 outline: 0;
1059 }
1060
1061 ';
1062 $styles .= '</style>';
1063 $styles .= '';
1064
1065 echo $styles; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This is styles, which is why escaping is not needed
1066
1067 ?>
1068 <script type="text/javascript">
1069 jQuery(document).ready(function($){
1070 $("#wpinsights-goodbye-link-<?php echo esc_attr( $class_plugin_name ); ?>").on("click",function(){
1071 // We'll send the user to this deactivation link when they've completed or dismissed the form
1072 var url = document.getElementById("wpinsights-goodbye-link-<?php echo esc_attr( $class_plugin_name ); ?>");
1073 $('body').toggleClass('wpinsights-form-active-<?php echo esc_attr( $class_plugin_name ); ?>');
1074 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $class_plugin_name ); ?> #wpinsights-goodbye-form").fadeIn();
1075 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $class_plugin_name ); ?> #wpinsights-goodbye-form").html( '<?php echo $html; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This is an html, not needed to escape ?>' + '<div class="wpinsights-goodbye-form-footer"><div class="wpinsights-goodbye-form-buttons"><a id="wpinsights-submit-form-<?php echo esc_attr( $class_plugin_name ); ?>" class="wpinsights-submit-btn" href="#"><?php esc_html_e( 'Submit and Deactivate', 'betterdocs' ); ?></a>&nbsp;<a class="wpsp-put-deactivate-btn" href="'+url+'"><?php esc_html_e( 'Just Deactivate', 'betterdocs' ); ?></a></div></div>');
1076 $('#wpinsights-submit-form-<?php echo esc_attr( $class_plugin_name ); ?>').on('click', function(e){
1077 // As soon as we click, the body of the form should disappear
1078 $("#wpinsights-goodbye-form-<?php echo esc_attr( $class_plugin_name ); ?> .wpinsights-goodbye-form-body").fadeOut();
1079 $("#wpinsights-goodbye-form-<?php echo esc_attr( $class_plugin_name ); ?> .wpinsights-goodbye-form-footer").fadeOut();
1080 // Fade in spinner
1081 $("#wpinsights-goodbye-form-<?php echo esc_attr( $class_plugin_name ); ?> .deactivating-spinner").fadeIn();
1082 e.preventDefault();
1083 var checkedInput = $("input[name='wpinsights-<?php echo esc_attr( $class_plugin_name ); ?>-goodbye-options']:checked"),
1084 checkedInputVal, details;
1085 if( checkedInput.length > 0 ) {
1086 checkedInputVal = checkedInput.val();
1087 details = $('input[name="'+ checkedInput[0].id +'"], textarea[name="'+ checkedInput[0].id +'"]').val();
1088 }
1089
1090 if( typeof details === 'undefined' ) {
1091 details = '';
1092 }
1093 if( typeof checkedInputVal === 'undefined' ) {
1094 checkedInputVal = 'No Reason';
1095 }
1096
1097 var data = {
1098 'action': 'deactivation_form_<?php echo esc_attr( $class_plugin_name ); ?>',
1099 'values': checkedInputVal,
1100 'details': details,
1101 'security': "<?php echo wp_create_nonce( 'wpins_deactivation_nonce' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>",
1102 'dataType': "json"
1103 }
1104
1105 $.post(
1106 ajaxurl,
1107 data,
1108 function(response){
1109 // Redirect to original deactivation URL
1110 window.location.href = url;
1111 }
1112 );
1113 });
1114 $('#wpinsights-goodbye-options > ul ').on('click', 'li label, li > input', function( e ){
1115 var parent = $(this).parents('li');
1116 parent.siblings().find('label').next('input, textarea').css('display', 'none');
1117 parent.find('label').next('input, textarea').css('display', 'block');
1118 });
1119 // If we click outside the form, the form will close
1120 $('.wpinsights-goodbye-form-bg, #wpinsights-goodbye-form > .betterdocs__modal-close-btn').on('click',function(){
1121 $("#wpinsights-goodbye-form").fadeOut();
1122 $('body').removeClass('wpinsights-form-active-<?php echo esc_attr( $class_plugin_name ); ?>');
1123 });
1124 });
1125 });
1126 </script>
1127 <?php
1128 }
1129 }
1130