PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 1.0.1
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v1.0.1
2.4.1 2.4.0 2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 All 68 releases
better-payment / includes / Classes / Better_Payment_Plugin_Usage_Tracker.php

Better_Payment_Plugin_Usage_Tracker.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 1.0.1, at includes/Classes/Better_Payment_Plugin_Usage_Tracker.php

949 lines 38.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Better_Payment\Lite\Classes;
4
5 use Better_Payment\Lite\Traits\Helper;
6
7 /**
8 * Exit if accessed directly
9 */
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 /**
15 * Plugin_Usage_Tracker
16 * This class is responsible for data sending to insights.
17 * @version 0.0.2
18 */
19
20 /**
21 * Main SDK for Plugin_Usage_Tracker.
22 */
23 class Better_Payment_Plugin_Usage_Tracker
24 {
25 use Helper;
26
27 /**
28 * WP Insights Version
29 */
30 const WPINS_VERSION = '3.0.3';
31 /**
32 * API URL
33 */
34 const API_URL = 'https://send.wpinsight.com/process-plugin-data';
35 /**
36 * Installed Plugin File
37 *
38 * @var string
39 */
40 private $plugin_file = null;
41 /**
42 * Installed Plugin Name
43 *
44 * @var string
45 */
46 private $plugin_name = null;
47 /**
48 * How often the event should subsequently
49 * @var string
50 */
51 public $recurrence = 'daily';
52 private $event_hook = null;
53 /**
54 * Instace of Plugin_Usage_Tracker
55 * @var Plugin_Usage_Tracker
56 */
57 private static $_instance = null;
58 /**
59 * Get Instance of Plugin_Usage_Tracker
60 * @return Plugin_Usage_Tracker
61 */
62 public static function get_instance($plugin_file, $args = [])
63 {
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 {
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 {
103 if ($this->disabled_wp_cron) {
104 return;
105 }
106 if (!wp_next_scheduled($this->event_hook)) {
107 wp_schedule_event(time(), $this->recurrence, $this->event_hook);
108 }
109 }
110 /**
111 * Add the schedule event if the plugin is tracked.
112 *
113 * @return void
114 */
115 public function activate_this_plugin()
116 {
117 $allow_tracking = $this->is_tracking_allowed();
118 if (!$allow_tracking) {
119 return;
120 }
121 $this->schedule_tracking();
122 }
123 /**
124 * Remove the schedule event when plugin is deactivated and send the deactivated reason to inishghts if user submitted.
125 * @since 3.0.0
126 */
127 public function deactivate_this_plugin()
128 {
129 /**
130 * Check tracking is allowed or not.
131 */
132 $allow_tracking = $this->is_tracking_allowed();
133 if (!$allow_tracking) {
134 return;
135 }
136 $body = $this->get_data();
137 $body['status'] = 'Deactivated';
138 $body['deactivated_date'] = time();
139
140 // Check deactivation reason and add for insights data.
141 if (false !== get_option('wpins_deactivation_reason_' . $this->plugin_name)) {
142 $body['deactivation_reason'] = get_option('wpins_deactivation_reason_' . $this->plugin_name);
143 }
144 if (false !== get_option('wpins_deactivation_details_' . $this->plugin_name)) {
145 $body['deactivation_details'] = get_option('wpins_deactivation_details_' . $this->plugin_name);
146 }
147
148 $this->send_data($body);
149 delete_option('wpins_deactivation_reason_' . $this->plugin_name);
150 delete_option('wpins_deactivation_details_' . $this->plugin_name);
151 /**
152 * Clear the event schedule.
153 */
154 if (!$this->disabled_wp_cron) {
155 wp_clear_scheduled_hook($this->event_hook);
156 }
157 }
158 /**
159 * Initial Method to Hook Everything.
160 * @return void
161 */
162 public function init()
163 {
164 // $this->clicked();
165 add_action('wpdeveloper_notice_clicked_for_' . $this->plugin_name, array($this, 'clicked'));
166 add_action($this->event_hook, array($this, 'do_tracking'));
167 // For Test
168 // add_action( 'admin_init', array( $this, 'force_tracking' ) );
169 // add_action( 'admin_notices', array( $this, 'notice' ) );
170 add_action('wpdeveloper_optin_notice_for_' . $this->plugin_name, array($this, 'notice'));
171 /**
172 * Deactivation Reason Form and Submit Data to Insights.
173 */
174 add_filter('plugin_action_links_' . plugin_basename($this->plugin_file), array($this, 'deactivate_action_links'));
175 add_action('admin_footer-plugins.php', array($this, 'deactivate_reasons_form'));
176 add_action('wp_ajax_deactivation_form_' . esc_attr($this->plugin_name), array($this, 'deactivate_reasons_form_submit'));
177 }
178 /**
179 * For Redirecting Current Page without Arguments!
180 *
181 * @return void
182 */
183 private function redirect_to()
184 {
185 $request_uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
186 $query_string = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);
187 parse_str($query_string, $current_url);
188
189 $unset_array = array('dismiss', 'plugin', '_wpnonce', 'later', 'plugin_action', 'marketing_optin');
190
191 foreach ($unset_array as $value) {
192 if (isset($current_url[$value])) {
193 unset($current_url[$value]);
194 }
195 }
196
197 $current_url = http_build_query($current_url);
198 $redirect_url = $request_uri . '?' . $current_url;
199 return $redirect_url;
200 }
201 /**
202 * This method forcing the do_tracking method to execute instant.
203 * @return void
204 */
205 public function force_tracking()
206 {
207 $this->do_tracking(true);
208 }
209 /**
210 * This method is responsible for all the magic from the front of the plugin.
211 * @since 3.0.0
212 * @param $force Force tracking if it's not the correct time to track/
213 */
214 public function do_tracking($force = false)
215 {
216 /**
217 * Check URL is set or not.
218 */
219 if (empty(self::API_URL)) {
220 return;
221 }
222 /**
223 * Check is tracking allowed or not.
224 */
225 if (!$this->is_tracking_allowed()) {
226 return;
227 }
228 /**
229 * Check is this the correct time to track or not.
230 * or Force to track.
231 */
232 if (!$this->is_time_to_track() && !$force) {
233 return;
234 }
235 /**
236 * Get All Data.
237 */
238 $body = $this->get_data();
239 /**
240 * Send all data.
241 */
242 return $this->send_data($body);
243 }
244 /**
245 * Is tracking allowed?
246 * @since 1.0.0
247 */
248 private function is_tracking_allowed()
249 {
250 // First, check if the user has changed their mind and opted out of tracking
251 if ($this->has_user_opted_out()) {
252 $this->set_is_tracking_allowed(false, $this->plugin_name);
253 return false;
254 }
255 // The wpins_allow_tracking option is an array of plugins that are being tracked
256 $allow_tracking = get_option('wpins_allow_tracking');
257 // If this plugin is in the array, then tracking is allowed
258 if (isset($allow_tracking[$this->plugin_name])) {
259 return true;
260 }
261 return false;
262 }
263 /**
264 * Set a flag in DB If tracking is allowed.
265 *
266 * @since 3.0.0
267 * @param $is_allowed Boolean true if is allowed.
268 */
269 public function set_is_tracking_allowed($is_allowed, $plugin = null)
270 {
271 if (empty($plugin)) {
272 $plugin = $this->plugin_name;
273 }
274 /**
275 * Get All Tracked Plugin List using this Tracker.
276 */
277 $allow_tracking = get_option('wpins_allow_tracking');
278 /**
279 * Check user is opted out for tracking or not.
280 */
281 if ($this->has_user_opted_out()) {
282 if (isset($allow_tracking[$plugin])) {
283 unset($allow_tracking[$plugin]);
284 }
285 } else if ($is_allowed || !$this->require_optin) {
286 /**
287 * If user has agreed to allow tracking
288 */
289 if (empty($allow_tracking) || !is_array($allow_tracking)) {
290 $allow_tracking = array($plugin => $plugin);
291 } else {
292 $allow_tracking[$plugin] = $plugin;
293 }
294 } else {
295 if (isset($allow_tracking[$plugin])) {
296 unset($allow_tracking[$plugin]);
297 }
298 }
299 update_option('wpins_allow_tracking', $allow_tracking);
300 }
301
302 /**
303 * Check the user has opted out or not.
304 *
305 * @since 3.0.0
306 * @return Boolean
307 */
308 protected function has_user_opted_out()
309 {
310 if (!empty($this->options)) {
311 foreach ($this->options as $option_name) {
312 $options = get_option($option_name);
313 if (!empty($options['wpins_opt_out'])) {
314 return true;
315 }
316 }
317 }
318 return false;
319 }
320 /**
321 * Check if it's time to track
322 *
323 * @since 3.0.0
324 */
325 public function is_time_to_track()
326 {
327 $track_times = get_option('wpins_last_track_time', array());
328 return !isset($track_times[$this->plugin_name]) ? true : ((isset($track_times[$this->plugin_name]) && $track_times[$this->plugin_name]) < strtotime('-1 day') ? true : false);
329 }
330 /**
331 * Set tracking time.
332 *
333 * @since 3.0.0
334 */
335 public function set_track_time()
336 {
337 $track_times = get_option('wpins_last_track_time', array());
338 $track_times[$this->plugin_name] = time();
339 update_option('wpins_last_track_time', $track_times);
340 }
341 /**
342 * This method is responsible for collecting all data.
343 *
344 * @since 3.0.0
345 */
346 public function get_data()
347 {
348 $body = array(
349 'plugin_slug' => sanitize_text_field($this->plugin_name),
350 'url' => get_bloginfo('url'),
351 'site_name' => get_bloginfo('name'),
352 'site_version' => get_bloginfo('version'),
353 'site_language' => get_bloginfo('language'),
354 'charset' => get_bloginfo('charset'),
355 'wpins_version' => self::WPINS_VERSION,
356 'php_version' => phpversion(),
357 'multisite' => is_multisite(),
358 'file_location' => __FILE__
359 );
360
361 // Collect the email if the correct option has been set
362 if ($this->marketing) {
363 if (!function_exists('wp_get_current_user')) {
364 include ABSPATH . 'wp-includes/pluggable.php';
365 }
366 $current_user = wp_get_current_user();
367 $email = $current_user->user_email;
368 if (is_email($email)) {
369 $body['email'] = $email;
370 } else {
371 $email = get_option('admin_email');
372 if (is_email($email)) {
373 $body['email'] = $email;
374 }
375 }
376 }
377 $body['marketing_method'] = $this->marketing;
378 $body['server'] = isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : '';
379
380 /**
381 * Collect all active and inactive plugins
382 */
383 if (!function_exists('get_plugins')) {
384 include ABSPATH . '/wp-admin/includes/plugin.php';
385 }
386 $plugins = array_keys(get_plugins());
387 $active_plugins = is_network_admin() ? array_keys(get_site_option('active_sitewide_plugins', array())) : get_option('active_plugins', array());
388 foreach ($plugins as $key => $plugin) {
389 if (in_array($plugin, $active_plugins)) {
390 unset($plugins[$key]);
391 }
392 }
393 $body['active_plugins'] = $active_plugins;
394 $body['inactive_plugins'] = $plugins;
395
396 /**
397 * Text Direction.
398 */
399 $body['text_direction'] = (function_exists('is_rtl') ? (is_rtl() ? 'RTL' : 'LTR') : 'NOT SET');
400 /**
401 * Get Our Plugin Data.
402 * @since 3.0.0
403 */
404 $plugin = $this->plugin_data();
405 if (empty($plugin)) {
406 $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.', 'better-payment');
407 $body['status'] = 'NOT FOUND';
408 } else {
409 if (isset($plugin['Name'])) {
410 $body['plugin'] = sanitize_text_field($plugin['Name']);
411 }
412 if (isset($plugin['Version'])) {
413 $body['version'] = sanitize_text_field($plugin['Version']);
414 }
415 $body['status'] = 'Active';
416 }
417
418 /**
419 * Get our plugin options
420 * @since 1.0.0
421 */
422 // $options = $this->options;
423 // $plugin_options = array();
424 // if( ! empty( $options ) && is_array( $options ) ) {
425 // foreach( $options as $option ) {
426 // $fields = get_option( $option );
427 // // Check for permission to send this option
428 // if( isset( $fields['wpins_registered_setting'] ) ) {
429 // foreach( $fields as $key=>$value ) {
430 // $plugin_options[$key] = $value;
431 // }
432 // }
433 // }
434 // }
435 // $body['plugin_options'] = $this->options; // Returns array
436 // $body['plugin_options_fields'] = $plugin_options; // Returns object
437
438 /**
439 * Get active theme name and version
440 * @since 3.0.0
441 */
442 $theme = wp_get_theme();
443 if ($theme->Name) {
444 $body['theme'] = sanitize_text_field($theme->Name);
445 }
446 if ($theme->Version) {
447 $body['theme_version'] = sanitize_text_field($theme->Version);
448 }
449 return $body;
450 }
451
452 /**
453 * Collect plugin data,
454 * Retrieve current plugin information
455 *
456 * @since 3.0.0
457 */
458 public function plugin_data()
459 {
460 if (!function_exists('get_plugin_data')) {
461 include ABSPATH . '/wp-admin/includes/plugin.php';
462 }
463 $plugin = get_plugin_data($this->plugin_file);
464 return $plugin;
465 }
466 /**
467 * Send the data to insights.
468 * @since 3.0.0
469 */
470 public function send_data($body)
471 {
472 /**
473 * Get SITE ID
474 */
475 $site_id_key = "wpins_{$this->plugin_name}_site_id";
476 $site_id = get_option($site_id_key, false);
477 $failed_data = [];
478 $site_url = get_bloginfo('url');
479 $original_site_url = get_option("wpins_{$this->plugin_name}_original_url", false);
480
481 if (($original_site_url === false || $original_site_url != $site_url) && version_compare($body['wpins_version'], '3.0.1', '>=')) {
482 $site_id = false;
483 }
484 /**
485 * Send Initial Data to API
486 */
487 if ($site_id == false && $this->item_id !== false) {
488 if (isset($_SERVER['REMOTE_ADDR']) && !empty($_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1')) {
489 $country_request = wp_remote_get('http://ip-api.com/json/' . $_SERVER['REMOTE_ADDR'] . '?fields=country');
490 if (!is_wp_error($country_request) && $country_request['response']['code'] == 200) {
491 $ip_data = json_decode($country_request["body"]);
492 $body['country'] = isset($ip_data->country) ? $ip_data->country : 'NOT SET';
493 }
494 }
495
496 $body['plugin_slug'] = $this->plugin_name;
497 $body['url'] = $site_url;
498 $body['item_id'] = $this->item_id;
499
500 $request = $this->remote_post($body);
501 if (!is_wp_error($request) && $request['response']['code'] == 200) {
502 $retrieved_body = json_decode(wp_remote_retrieve_body($request), true);
503 if (is_array($retrieved_body) && isset($retrieved_body['siteId'])) {
504 update_option($site_id_key, $retrieved_body['siteId']);
505 update_option("wpins_{$this->plugin_name}_original_url", $site_url);
506 update_option("wpins_{$this->plugin_name}_{$retrieved_body['siteId']}", $body);
507 }
508 } else {
509 $failed_data = $body;
510 }
511 }
512
513 $site_id_data_key = "wpins_{$this->plugin_name}_{$site_id}";
514 $site_id_data_failed_key = "wpins_{$this->plugin_name}_{$site_id}_send_failed";
515
516 if ($site_id != false) {
517 $old_sent_data = get_option($site_id_data_key, []);
518 $diff_data = $this->diff($body, $old_sent_data);
519 $failed_data = get_option($site_id_data_failed_key, []);
520 if (!empty($failed_data) && $diff_data != $failed_data) {
521 $failed_data = array_merge($failed_data, $diff_data);
522 }
523 }
524
525 if (!empty($failed_data) && $site_id != false) {
526 $failed_data['plugin_slug'] = $this->plugin_name;
527 $failed_data['url'] = $site_url;
528 $failed_data['site_id'] = $site_id;
529 if ($original_site_url != false) {
530 $failed_data['original_url'] = $original_site_url;
531 }
532
533 $request = $this->remote_post($failed_data);
534 if (!is_wp_error($request)) {
535 delete_option($site_id_data_failed_key);
536 $replaced_data = array_merge($old_sent_data, $failed_data);
537 update_option($site_id_data_key, $replaced_data);
538 }
539 }
540
541 if (!empty($diff_data) && $site_id != false && empty($failed_data)) {
542 $diff_data['plugin_slug'] = $this->plugin_name;
543 $diff_data['url'] = $site_url;
544 $diff_data['site_id'] = $site_id;
545 if ($original_site_url != false) {
546 $diff_data['original_url'] = $original_site_url;
547 }
548
549 $request = $this->remote_post($diff_data);
550 if (is_wp_error($request)) {
551 update_option($site_id_data_failed_key, $diff_data);
552 } else {
553 $replaced_data = array_merge($old_sent_data, $diff_data);
554 update_option($site_id_data_key, $replaced_data);
555 }
556 }
557
558 $this->set_track_time();
559
560 if (isset($request) && is_wp_error($request)) {
561 return $request;
562 }
563
564 if (isset($request)) {
565 return true;
566 }
567 return false;
568 }
569 /**
570 * WP_REMOTE_POST method responsible for send data to the API_URL
571 *
572 * @param array $data
573 * @param array $args
574 * @return void
575 */
576 protected function remote_post($data = array(), $args = array())
577 {
578 if (empty($data)) {
579 return;
580 }
581
582 $args = wp_parse_args($args, array(
583 'method' => 'POST',
584 'timeout' => 30,
585 'redirection' => 5,
586 'httpversion' => '1.1',
587 'blocking' => true,
588 'body' => $data,
589 'user-agent' => 'PUT/1.0.0; ' . get_bloginfo('url')
590 ));
591 $request = wp_remote_post(esc_url(self::API_URL), $args);
592 if (is_wp_error($request) || (isset($request['response'], $request['response']['code']) && $request['response']['code'] != 200)) {
593 return new \WP_Error(500, 'Something went wrong.');
594 }
595 return $request;
596 }
597 /**
598 * Difference between old and new data
599 *
600 * @param array $new_data
601 * @param array $old_data
602 * @return void
603 */
604 protected function diff($new_data, $old_data)
605 {
606 $data = [];
607 if (!empty($new_data)) {
608 foreach ($new_data as $key => $value) {
609 if (isset($old_data[$key])) {
610 if ($old_data[$key] == $value) {
611 continue;
612 }
613 }
614 $data[$key] = $value;
615 }
616 }
617 return $data;
618 }
619 /**
620 * Display the admin notice to users to allow them to opt in
621 *
622 * @since 3.0.0
623 */
624 public function notice()
625 {
626 /**
627 * Return if notice is not set.
628 */
629 if (!isset($this->notice_options['notice'])) {
630 return;
631 }
632 /**
633 * Check is allowed or blocked for notice.
634 */
635 $block_notice = get_option('wpins_block_notice');
636 if (isset($block_notice[$this->plugin_name])) {
637 return;
638 }
639 if (!current_user_can('manage_options')) {
640 return;
641 }
642
643 $url_yes = add_query_arg([
644 'plugin' => $this->plugin_name,
645 'plugin_action' => 'yes',
646 ]);
647 $url_no = add_query_arg(array(
648 'plugin' => $this->plugin_name,
649 'plugin_action' => 'no'
650 ));
651
652 // Decide on notice text
653 $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-' . $this->plugin_name . '-collect">' . $this->notice_options['consent_button_text'] . '</a>';
654 $extra_notice_text = $this->notice_options['extra_notice'];
655
656 $output = '';
657 $output .= '<div class="notice notice-info updated put-dismiss-notice">';
658 $output .= '<p>' . $notice_text . '</p>';
659 $output .= '<div class="wpinsights-data" style="display: none;">';
660 $output .= '<p>' . $extra_notice_text . '</p>';
661 $output .= '</div>';
662 $output .= '<p>';
663 $output .= '<a href="' . esc_url($url_yes) . '" class="button-primary">' . $this->notice_options['yes'] . '</a>&nbsp;';
664 $output .= '<a href="' . esc_url($url_no) . '" class="button-secondary">' . $this->notice_options['no'] . '</a>';
665 $output .= '</p>';
666 $output .= "<script type='text/javascript'>jQuery('.wpinsights-" . $this->plugin_name . "-collect').on('click', function(e) {e.preventDefault();jQuery('.wpinsights-data').slideToggle('fast');});</script>";
667 $output .= '</div>';
668
669 echo $output;
670 }
671 /**
672 * Set all notice options to customized notice.
673 *
674 * @since 3.0.0
675 * @param array $options
676 * @return void
677 */
678 public function set_notice_options($options = [])
679 {
680 $default_options = [
681 'consent_button_text' => esc_html__('What we collect.', 'disable-comments'),
682 'yes' => esc_html__('Sure, I\'d like to help', 'disable-comments'),
683 'no' => esc_html__('No Thanks.', 'disable-comments'),
684 ];
685 $options = wp_parse_args($options, $default_options);
686 $this->notice_options = $options;
687 }
688 /**
689 * Responsible for track the click from Notice.
690 * @return void
691 */
692 public function clicked()
693 {
694 if (isset($_GET['plugin']) && trim($_GET['plugin']) === $this->plugin_name && isset($_GET['plugin_action'])) {
695 if (isset($_GET['tab']) && $_GET['tab'] === 'plugin-information') {
696 return;
697 }
698 $plugin = sanitize_text_field($_GET['plugin']);
699 $action = sanitize_text_field($_GET['plugin_action']);
700 if ($action == 'yes') {
701 $this->schedule_tracking();
702 $this->set_is_tracking_allowed(true, $plugin);
703 if ($this->do_tracking(true)) {
704 $this->update_block_notice($plugin);
705 }
706 /**
707 * Redirect User To the Current URL, but without set query arguments.
708 */
709 wp_safe_redirect($this->redirect_to());
710 } else {
711 $this->set_is_tracking_allowed(false, $plugin);
712 $this->update_block_notice($plugin);
713 }
714 }
715 }
716 /**
717 * Set if we should block the opt-in notice for this plugin
718 *
719 * @since 3.0.0
720 */
721 public function update_block_notice($plugin = null)
722 {
723 if (empty($plugin)) {
724 $plugin = $this->plugin_name;
725 }
726 $block_notice = get_option('wpins_block_notice');
727 if (empty($block_notice) || !is_array($block_notice)) {
728 $block_notice = array($plugin => $plugin);
729 } else {
730 $block_notice[$plugin] = $plugin;
731 }
732 update_option('wpins_block_notice', $block_notice);
733 }
734 /**
735 * AJAX callback when the deactivated form is submitted.
736 * @since 3.0.0
737 */
738 public function deactivate_reasons_form_submit()
739 {
740 check_ajax_referer('wpins_deactivation_nonce', 'security');
741 if (isset($_POST['values'])) {
742 $values = $_POST['values'];
743 update_option('wpins_deactivation_reason_' . $this->plugin_name, $values);
744 }
745 if (isset($_POST['details'])) {
746 $details = sanitize_text_field($_POST['details']);
747 update_option('wpins_deactivation_details_' . $this->plugin_name, $details);
748 }
749 echo 'success';
750 wp_die();
751 }
752 /**
753 * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
754 * @since 3.0.0
755 */
756 public function deactivate_action_links($links)
757 {
758 /**
759 * Check is tracking allowed or not.
760 */
761 if (!$this->is_tracking_allowed()) {
762 return $links;
763 }
764 if (isset($links['deactivate']) && $this->include_goodbye_form) {
765 $deactivation_link = $links['deactivate'];
766 /**
767 * Change the default deactivate button link.
768 */
769 $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);
770 $links['deactivate'] = $deactivation_link;
771 }
772 return $links;
773 }
774 /**
775 * ALL Deactivate Reasons.
776 * @since 3.0.0
777 */
778 public function deactivation_reasons()
779 {
780 $form = array();
781 $form['heading'] = esc_html__('Sorry to see you go', 'disable-comments');
782 $form['body'] = esc_html__('Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'disable-comments');
783
784 $form['options'] = array(
785 esc_html__('I no longer need the plugin', 'disable-comments'),
786 [
787 'label' => esc_html__('I found a better plugin', 'disable-comments'),
788 'extra_field' => esc_html__('Please share which plugin', 'disable-comments')
789 ],
790 esc_html__("I couldn't get the plugin to work", 'disable-comments'),
791 esc_html__('It\'s a temporary deactivation', 'disable-comments'),
792 [
793 'label' => esc_html__('Other', 'disable-comments'),
794 'extra_field' => esc_html__('Please share the reason', 'disable-comments'),
795 'type' => 'textarea'
796 ]
797 );
798 return apply_filters('wpins_form_text_' . $this->plugin_name, $form);
799 }
800 /**
801 * Deactivate Reasons Form.
802 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
803 *
804 * @since 3.0.0
805 */
806 public function deactivate_reasons_form()
807 {
808 $form = $this->deactivation_reasons();
809 $class_plugin_name = esc_attr( $this->plugin_name );
810 $html = '<div class="wpinsights-goodbye-form-head"><strong>' . esc_html($form['heading']) . '</strong></div>';
811 $html .= '<div class="wpinsights-goodbye-form-body"><p class="wpinsights-goodbye-form-caption">' . esc_html($form['body']) . '</p>';
812 if (is_array($form['options'])) {
813 $html .= '<div id="wpinsights-goodbye-options" class="wpinsights-goodbye-options"><ul>';
814 foreach ($form['options'] as $option) {
815 if (is_array($option)) {
816 $id = strtolower(str_replace(" ", "_", esc_attr($option['label'])));
817 $id = $id . '_' . esc_attr( $class_plugin_name );
818 $html .= '<li class="has-goodbye-extra">';
819 $html .= '<input type="radio" name="wpinsights-' . esc_attr( $class_plugin_name ) . '-goodbye-options" id="' . $id . '" value="' . esc_attr($option['label']) . '">';
820 $html .= '<div><label for="' . $id . '">' . esc_attr($option['label']) . '</label>';
821 if (isset($option['extra_field']) && !isset($option['type'])) {
822 $html .= '<input type="text" style="display: none" name="' . $id . '" id="' . str_replace(" ", "", esc_attr($option['extra_field'])) . '" placeholder="' . esc_attr($option['extra_field']) . '">';
823 }
824 if (isset($option['extra_field']) && isset($option['type'])) {
825 $html .= '<' . $option['type'] . ' style="display: none" type="text" name="' . $id . '" id="' . str_replace(" ", "", esc_attr($option['extra_field'])) . '" placeholder="' . esc_attr($option['extra_field']) . '"></' . $option['type'] . '>';
826 }
827 $html .= '</div></li>';
828 } else {
829 $id = strtolower(str_replace(" ", "_", esc_attr($option)));
830 $id = $id . '_' . esc_attr( $class_plugin_name );
831 $html .= '<li><input type="radio" name="wpinsights-' . esc_attr( $class_plugin_name ) . '-goodbye-options" id="' . $id . '" value="' . esc_attr($option) . '"> <label for="' . $id . '">' . esc_attr($option) . '</label></li>';
832 }
833 }
834 $html .= '</ul></div><!-- .wpinsights-' . esc_attr( $class_plugin_name ) . '-goodbye-options -->';
835 }
836 $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
837 $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . esc_html__('Submitting form', 'disable-comments') . '</p>';
838
839 $wrapper_class = '.wpinsights-goodbye-form-wrapper-' . esc_attr( $class_plugin_name );
840
841 $styles = '';
842 $styles .= '<style type="text/css">';
843 $styles .= '.wpinsights-form-active-' . esc_attr( $class_plugin_name ) . ' .wpinsights-goodbye-form-bg {';
844 $styles .= 'background: rgba( 0, 0, 0, .8 );position: fixed;top: 0;left: 0;width: 100%;height: 100%;z-index: 9;';
845 $styles .= '}';
846 $styles .= $wrapper_class . '{';
847 $styles .= 'position: relative; display: none;';
848 $styles .= '}';
849 $styles .= '.wpinsights-form-active-' . esc_attr( $class_plugin_name ) . ' ' . $wrapper_class . '{';
850 $styles .= 'display: flex !important; position: fixed;top: 0;left: 0;width: 100%;height: 100%; justify-content: center; align-items: center;';
851 $styles .= '}';
852 $styles .= $wrapper_class . ' .wpinsights-goodbye-form { display: none; }';
853 $styles .= '.wpinsights-form-active-' . esc_attr( $class_plugin_name ) . ' .wpinsights-goodbye-form {';
854 $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;';
855 $styles .= '}';
856 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-head {';
857 $styles .= 'background: #fff; color: #495157; padding: 18px; box-shadow: 0 0 8px rgba(0,0,0,.1); font-size: 15px;';
858 $styles .= '}';
859 $styles .= $wrapper_class . ' .wpinsights-goodbye-form .wpinsights-goodbye-form-head strong { font-size: 15px; }';
860 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body { padding: 8px 18px; color: #333; }';
861 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body label { padding-left: 5px; color: #6d7882; }';
862 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {';
863 $styles .= 'font-weight: 500; font-size: 15px; color: #495157; line-height: 1.4;';
864 $styles .= '}';
865 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options { padding-top: 5px; }';
866 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li { margin-bottom: 15px; }';
867 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul > li > div { display: inline; padding-left: 3px; }';
868 $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 {';
869 $styles .= 'margin: 10px 18px; padding: 8px; width: 80%;';
870 $styles .= '}';
871 $styles .= $wrapper_class . ' .deactivating-spinner { display: none; padding-bottom: 20px !important; }';
872 $styles .= $wrapper_class . ' .deactivating-spinner .spinner { float: none; margin: 4px 4px 0 18px; vertical-align: bottom; visibility: visible; }';
873 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer { padding: 8px 18px; margin-bottom: 15px; }';
874 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer > .wpinsights-goodbye-form-buttons { display: flex; align-items: center; justify-content: space-between; }';
875 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-submit-btn {';
876 $styles .= 'background-color: #d30c5c; -webkit-border-radius: 3px; border-radius: 3px; color: #fff; line-height: 1; padding: 15px 20px; font-size: 13px;';
877 $styles .= '}';
878 $styles .= $wrapper_class . ' .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {';
879 $styles .= 'font-size: 13px; color: #a4afb7; background: none; float: right; padding-right: 10px; width: auto; text-decoration: underline;';
880 $styles .= '}';
881 $styles .= $wrapper_class . ' .test {';
882 $styles .= '}';
883 $styles .= '</style>';
884 $styles .= '';
885
886 echo $styles;
887 ?>
888 <script type="text/javascript">
889 jQuery(document).ready(function($) {
890 $("#wpinsights-goodbye-link-<?php echo esc_attr( $class_plugin_name ); ?>").on("click", function() {
891 // We'll send the user to this deactivation link when they've completed or dismissed the form
892 var url = document.getElementById("wpinsights-goodbye-link-<?php echo esc_attr( $class_plugin_name ); ?>");
893 $('body').toggleClass('wpinsights-form-active-<?php echo esc_attr( $class_plugin_name ); ?>');
894 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $class_plugin_name ); ?> #wpinsights-goodbye-form").fadeIn();
895 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $class_plugin_name ); ?> #wpinsights-goodbye-form").html('<?php echo $html; ?>' + '<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', 'disable-comments'); ?></a>&nbsp;<a class="wpsp-put-deactivate-btn" href="' + url + '"><?php esc_html_e('Just Deactivate', 'disable-comments'); ?></a></div></div>');
896 $('#wpinsights-submit-form-<?php echo esc_attr( $class_plugin_name ); ?>').on('click', function(e) {
897 // As soon as we click, the body of the form should disappear
898 $("#wpinsights-goodbye-form-<?php echo esc_attr( $class_plugin_name ); ?> .wpinsights-goodbye-form-body").fadeOut();
899 $("#wpinsights-goodbye-form-<?php echo esc_attr( $class_plugin_name ); ?> .wpinsights-goodbye-form-footer").fadeOut();
900 // Fade in spinner
901 $("#wpinsights-goodbye-form-<?php echo esc_attr( $class_plugin_name ); ?> .deactivating-spinner").fadeIn();
902 e.preventDefault();
903 var checkedInput = $("input[name='wpinsights-<?php echo esc_attr( $class_plugin_name ); ?>-goodbye-options']:checked"),
904 checkedInputVal, details;
905 if (checkedInput.length > 0) {
906 checkedInputVal = checkedInput.val();
907 details = $('input[name="' + checkedInput[0].id + '"], textarea[name="' + checkedInput[0].id + '"]').val();
908 }
909
910 if (typeof details === 'undefined') {
911 details = '';
912 }
913 if (typeof checkedInputVal === 'undefined') {
914 checkedInputVal = 'No Reason';
915 }
916
917 var data = {
918 'action': 'deactivation_form_<?php echo esc_attr( $class_plugin_name ); ?>',
919 'values': checkedInputVal,
920 'details': details,
921 'security': "<?php echo esc_attr( wp_create_nonce('wpins_deactivation_nonce') ); ?>",
922 'dataType': "json"
923 }
924
925 $.post(
926 ajaxurl,
927 data,
928 function(response) {
929 // Redirect to original deactivation URL
930 window.location.href = url;
931 }
932 );
933 });
934 $('#wpinsights-goodbye-options > ul ').on('click', 'li label, li > input', function(e) {
935 var parent = $(this).parents('li');
936 parent.siblings().find('label').next('input, textarea').css('display', 'none');
937 parent.find('label').next('input, textarea').css('display', 'block');
938 });
939 // If we click outside the form, the form will close
940 $('.wpinsights-goodbye-form-bg').on('click', function() {
941 $("#wpinsights-goodbye-form").fadeOut();
942 $('body').removeClass('wpinsights-form-active-<?php echo esc_attr( $class_plugin_name ); ?>');
943 });
944 });
945 });
946 </script>
947 <?php }
948 }
949