PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.2.9
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.2.9
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
notificationx / includes / Admin / PluginInsights.php

PluginInsights.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar 3.2.9, at includes/Admin/PluginInsights.php

1,044 lines 41.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace NotificationX\Admin;
4 #[\AllowDynamicProperties]
5 class PluginInsights {
6 /**
7 * WP Insights Version
8 */
9 const WPINS_VERSION = '3.0.1';
10 /**
11 * API URL
12 */
13 const API_URL = 'https://send.wpinsight.com/process-plugin-data';
14 /**
15 * Installed Plugin File
16 *
17 * @var string
18 */
19 private $plugin_file = null;
20 /**
21 * Installed Plugin Name
22 *
23 * @var string
24 */
25 private $plugin_name = null;
26 /**
27 * How often the event should subsequently
28 *
29 * @var string
30 */
31 public $recurrence = 'daily';
32 private $event_hook = null;
33 private $has_notice = false;
34 /**
35 * Instace of WPInsights_NotificationX
36 *
37 * @var WPInsights_NotificationX
38 */
39 private static $_instance = null;
40 /**
41 * Get Instance of WPInsights_NotificationX
42 *
43 * @return WPInsights_NotificationX
44 */
45 public static function get_instance( $plugin_file, $args = [] ) {
46 if ( is_null( static::$_instance ) ) {
47 static::$_instance = new static( $plugin_file, $args );
48 }
49 return static::$_instance;
50 }
51 /**
52 * Automatically Invoked when initialized.
53 *
54 * @param array $args
55 */
56 public function __construct( $plugin_file, $args = [] ) {
57 $this->plugin_file = $plugin_file;
58 $this->plugin_name = basename( $this->plugin_file, '.php' );
59 $this->disabled_wp_cron = defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON == true;
60 $this->enable_self_cron = $this->disabled_wp_cron == true ? true : false;
61
62 $this->event_hook = 'put_do_weekly_action';
63
64 $this->require_optin = isset( $args['opt_in'] ) ? $args['opt_in'] : true;
65 $this->include_goodbye_form = isset( $args['goodbye_form'] ) ? $args['goodbye_form'] : true;
66 $this->marketing = isset( $args['email_marketing'] ) ? $args['email_marketing'] : true;
67 $this->options = isset( $args['options'] ) ? $args['options'] : [];
68 $this->item_id = isset( $args['item_id'] ) ? $args['item_id'] : false;
69 /**
70 * Activation Hook
71 */
72 register_activation_hook( $this->plugin_file, array( $this, 'activate_this_plugin' ) );
73 /**
74 * Deactivation Hook
75 */
76 register_deactivation_hook( $this->plugin_file, array( $this, 'deactivate_this_plugin' ) );
77 }
78 /**
79 * When user agreed to opt-in tracking schedule is enabled.
80 *
81 * @since 3.0.0
82 */
83 public function schedule_tracking() {
84 if ( $this->disabled_wp_cron ) {
85 return;
86 }
87 if ( ! wp_next_scheduled( $this->event_hook ) ) {
88 wp_schedule_event( time(), $this->recurrence, $this->event_hook );
89 }
90 }
91 /**
92 * Add the schedule event if the plugin is tracked.
93 *
94 * @return void
95 */
96 public function activate_this_plugin() {
97 $allow_tracking = $this->is_tracking_allowed();
98 if ( ! $allow_tracking ) {
99 return;
100 }
101 $this->schedule_tracking();
102 }
103 /**
104 * Remove the schedule event when plugin is deactivated and send the deactivated reason to inishghts if user submitted.
105 *
106 * @since 3.0.0
107 */
108 public function deactivate_this_plugin() {
109 /**
110 * Check tracking is allowed or not.
111 */
112 $allow_tracking = $this->is_tracking_allowed();
113 if ( ! $allow_tracking ) {
114 return;
115 }
116 $body = $this->get_data();
117 $body['status'] = 'Deactivated';
118 $body['deactivated_date'] = time();
119
120 // Check deactivation reason and add for insights data.
121 if ( false !== get_option( 'wpins_deactivation_reason_' . $this->plugin_name ) ) {
122 $body['deactivation_reason'] = get_option( 'wpins_deactivation_reason_' . $this->plugin_name );
123 }
124 if ( false !== get_option( 'wpins_deactivation_details_' . $this->plugin_name ) ) {
125 $body['deactivation_details'] = get_option( 'wpins_deactivation_details_' . $this->plugin_name );
126 }
127
128 $this->send_data( $body );
129 delete_option( 'wpins_deactivation_reason_' . $this->plugin_name );
130 delete_option( 'wpins_deactivation_details_' . $this->plugin_name );
131 /**
132 * Clear the event schedule.
133 */
134 if ( ! $this->disabled_wp_cron ) {
135 wp_clear_scheduled_hook( $this->event_hook );
136 }
137 }
138 /**
139 * Initial Method to Hook Everything.
140 *
141 * @return void
142 */
143 public function init() {
144 // $this->clicked();
145 add_action( 'wpdeveloper_notice_clicked_for_' . $this->plugin_name, array( $this, 'clicked' ) );
146 add_action( $this->event_hook, array( $this, 'do_tracking' ) );
147 // For Test
148 // add_action( 'admin_init', array( $this, 'force_tracking' ) );
149 // add_action( 'admin_notices', array( $this, 'notice' ) );
150 add_action( 'wpdeveloper_optin_notice_for_' . $this->plugin_name, array( $this, 'notice' ) );
151 /**
152 * Deactivation Reason Form and Submit Data to Insights.
153 */
154 add_filter( 'plugin_action_links_' . plugin_basename( $this->plugin_file ), array( $this, 'deactivate_action_links' ) );
155 add_action( 'admin_print_footer_scripts', array( $this, 'notice_script' ) );
156 add_action( 'admin_print_footer_scripts-plugins.php', array( $this, 'deactivate_reasons_form_script' ) );
157 add_action( 'admin_print_styles-plugins.php', array( $this, 'deactivate_reasons_form_style' ) );
158 add_action( 'wp_ajax_deactivation_form_' . esc_attr( $this->plugin_name ), array( $this, 'deactivate_reasons_form_submit' ) );
159 }
160 /**
161 * For Redirecting Current Page without Arguments!
162 *
163 * @return void
164 */
165 private function redirect_to() {
166 $request_uri = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
167 $query_string = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY );
168 parse_str( $query_string, $current_url );
169
170 $unset_array = array( 'dismiss', 'plugin', '_wpnonce', 'later', 'plugin_action', 'marketing_optin' );
171
172 foreach ( $unset_array as $value ) {
173 if ( isset( $current_url[ $value ] ) ) {
174 unset( $current_url[ $value ] );
175 }
176 }
177
178 $current_url = http_build_query( $current_url );
179 $redirect_url = $request_uri . '?' . $current_url;
180 return $redirect_url;
181 }
182 /**
183 * This method forcing the do_tracking method to execute instant.
184 *
185 * @return void
186 */
187 public function force_tracking() {
188 $this->do_tracking( true );
189 }
190 /**
191 * Programmatically opt the site into tracking and (optionally) send the
192 * data to the insights API immediately. Used by the onboarding Setup Wizard
193 * when the user proceeds past the Welcome step (which is the consent point).
194 *
195 * @param bool $send Send the collected data right away.
196 * @return bool|\WP_Error
197 */
198 public function optin( $send = true ) {
199 $this->schedule_tracking();
200 $this->set_is_tracking_allowed( true, $this->plugin_name );
201 $this->update_block_notice( $this->plugin_name );
202 if ( $send ) {
203 return $this->do_tracking( true );
204 }
205 return true;
206 }
207 /**
208 * This method is responsible for all the magic from the front of the plugin.
209 *
210 * @since 3.0.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 ( defined('NX_DEBUG') || 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 3.0.0
265 * @param $is_allowed Boolean true if is allowed.
266 */
267 protected 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 } else {
292 if ( isset( $allow_tracking[ $plugin ] ) ) {
293 unset( $allow_tracking[ $plugin ] );
294 }
295 }
296 update_option( 'wpins_allow_tracking', $allow_tracking, 'no' );
297 }
298
299 /**
300 * Check the user has opted out or not.
301 *
302 * @since 3.0.0
303 * @return Boolean
304 */
305 protected function has_user_opted_out() {
306 if ( ! empty( $this->options ) ) {
307 foreach ( $this->options as $option_name ) {
308 $options = get_option( $option_name );
309 if ( ! empty( $options['wpins_opt_out'] ) ) {
310 return true;
311 }
312 }
313 }
314 return false;
315 }
316 /**
317 * Check if it's time to track
318 *
319 * @since 3.0.0
320 */
321 public function is_time_to_track() {
322 $track_times = get_option( 'wpins_last_track_time', array() );
323 return ! isset( $track_times[ $this->plugin_name ] ) ? true :
324 ( ( isset( $track_times[ $this->plugin_name ] ) && $track_times[ $this->plugin_name ] ) < strtotime( '-1 day' ) ? true : false );
325 }
326 /**
327 * Set tracking time.
328 *
329 * @since 3.0.0
330 */
331 public function set_track_time() {
332 $track_times = get_option( 'wpins_last_track_time', array() );
333 $track_times[ $this->plugin_name ] = time();
334 update_option( 'wpins_last_track_time', $track_times, 'no' );
335 }
336 /**
337 * This method is responsible for collecting all data.
338 *
339 * @since 3.0.0
340 */
341 public function get_data() {
342 $body = array(
343 'plugin_slug' => sanitize_text_field( $this->plugin_name ),
344 'url' => get_bloginfo( 'url' ),
345 'site_name' => get_bloginfo( 'name' ),
346 'site_version' => get_bloginfo( 'version' ),
347 'site_language' => get_bloginfo( 'language' ),
348 'charset' => get_bloginfo( 'charset' ),
349 'wpins_version' => self::WPINS_VERSION,
350 'php_version' => phpversion(),
351 'multisite' => is_multisite(),
352 'file_location' => __FILE__,
353 );
354
355 // Collect the email if the correct option has been set
356 if ( $this->marketing ) {
357 if ( ! function_exists( 'wp_get_current_user' ) ) {
358 include ABSPATH . 'wp-includes/pluggable.php';
359 }
360 $current_user = wp_get_current_user();
361 $email = $current_user->user_email;
362 if ( is_email( $email ) ) {
363 $body['email'] = $email;
364 }
365 }
366 $body['marketing_method'] = $this->marketing;
367 $body['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : '';
368
369 /**
370 * Collect all active and inactive plugins
371 */
372 if ( ! function_exists( 'get_plugins' ) ) {
373 include ABSPATH . '/wp-admin/includes/plugin.php';
374 }
375 $plugins = array_keys( get_plugins() );
376 $active_plugins = is_network_admin() ? array_keys( get_site_option( 'active_sitewide_plugins', array() ) ) : get_option( 'active_plugins', array() );
377 foreach ( $plugins as $key => $plugin ) {
378 if ( in_array( $plugin, $active_plugins ) ) {
379 unset( $plugins[ $key ] );
380 }
381 }
382 $body['active_plugins'] = $active_plugins;
383 $body['inactive_plugins'] = $plugins;
384
385 /**
386 * Text Direction.
387 */
388 $body['text_direction'] = ( function_exists( 'is_rtl' ) ? ( is_rtl() ? 'RTL' : 'LTR' ) : 'NOT SET' );
389 /**
390 * Get Our Plugin Data.
391 *
392 * @since 3.0.0
393 */
394 $plugin = $this->plugin_data();
395 if ( empty( $plugin ) ) {
396 $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.', 'plugin-usage-tracker' );
397 $body['status'] = 'NOT FOUND';
398 } else {
399 if ( isset( $plugin['Name'] ) ) {
400 $body['plugin'] = sanitize_text_field( $plugin['Name'] );
401 }
402 if ( isset( $plugin['Version'] ) ) {
403 $body['version'] = sanitize_text_field( $plugin['Version'] );
404 }
405 $body['status'] = 'Active';
406 }
407
408 /**
409 * Get active theme name and version
410 *
411 * @since 3.0.0
412 */
413 $theme = wp_get_theme();
414 if ( $theme->Name ) {
415 $body['theme'] = sanitize_text_field( $theme->Name );
416 }
417 if ( $theme->Version ) {
418 $body['theme_version'] = sanitize_text_field( $theme->Version );
419 }
420 return $body;
421 }
422
423 /**
424 * Collect plugin data,
425 * Retrieve current plugin information
426 *
427 * @since 3.0.0
428 */
429 public function plugin_data() {
430 if ( ! function_exists( 'get_plugin_data' ) ) {
431 include ABSPATH . '/wp-admin/includes/plugin.php';
432 }
433 $plugin = get_plugin_data( $this->plugin_file );
434 return $plugin;
435 }
436 /**
437 * Send the data to insights.
438 *
439 * @since 3.0.0
440 */
441 public function send_data( $body ) {
442 /**
443 * Get SITE ID
444 */
445 $site_id_key = "wpins_{$this->plugin_name}_site_id";
446 $site_id = get_option( $site_id_key, false );
447 $failed_data = [];
448 $site_url = get_bloginfo( 'url' );
449 $original_site_url = get_option( "wpins_{$this->plugin_name}_original_url", false );
450 if ( $original_site_url === false && version_compare( $body['wpins_version'], '3.0.1', '==' ) ) {
451 $site_id = false;
452 }
453 /**
454 * Send Initial Data to API
455 */
456 if ( $site_id == false && $this->item_id !== false && $original_site_url === false ) {
457 if ( isset( $_SERVER['REMOTE_ADDR'] ) && ! empty( $_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1' ) ) {
458 $country_request = wp_remote_get( 'http://ip-api.com/json/' . $_SERVER['REMOTE_ADDR'] . '?fields=country' );
459 if ( ! is_wp_error( $country_request ) && $country_request['response']['code'] == 200 ) {
460 $ip_data = json_decode( $country_request['body'] );
461 $body['country'] = isset( $ip_data->country ) ? $ip_data->country : 'NOT SET';
462 }
463 }
464
465 $body['plugin_slug'] = $this->plugin_name;
466 $body['url'] = $site_url;
467 $body['item_id'] = $this->item_id;
468
469 $request = $this->remote_post( $body );
470 if ( ! is_wp_error( $request ) && $request['response']['code'] == 200 ) {
471 $retrieved_body = json_decode( wp_remote_retrieve_body( $request ), true );
472 if ( is_array( $retrieved_body ) && isset( $retrieved_body['siteId'] ) ) {
473 update_option( $site_id_key, $retrieved_body['siteId'], 'no' );
474 update_option( "wpins_{$this->plugin_name}_original_url", $site_url, 'no' );
475 update_option( "wpins_{$this->plugin_name}_{$retrieved_body['siteId']}", $body, 'no' );
476 }
477 } else {
478 $failed_data = $body;
479 }
480 }
481
482 $site_id_data_key = "wpins_{$this->plugin_name}_{$site_id}";
483 $site_id_data_failed_key = "wpins_{$this->plugin_name}_{$site_id}_send_failed";
484
485 if ( $site_id != false ) {
486 $old_sent_data = get_option( $site_id_data_key, [] );
487 $diff_data = $this->diff( $body, $old_sent_data );
488 $failed_data = get_option( $site_id_data_failed_key, [] );
489 if ( ! empty( $failed_data ) && $diff_data != $failed_data ) {
490 $failed_data = array_merge( $failed_data, $diff_data );
491 }
492 }
493
494 if ( ! empty( $failed_data ) && $site_id != false ) {
495 $failed_data['plugin_slug'] = $this->plugin_name;
496 $failed_data['url'] = $site_url;
497 $failed_data['site_id'] = $site_id;
498 if ( $original_site_url != false ) {
499 $failed_data['original_url'] = $original_site_url;
500 }
501
502 $request = $this->remote_post( $failed_data );
503 if ( ! is_wp_error( $request ) ) {
504 delete_option( $site_id_data_failed_key );
505 $replaced_data = array_merge( $old_sent_data, $failed_data );
506 update_option( $site_id_data_key, $replaced_data, 'no' );
507 }
508 }
509
510 if ( ! empty( $diff_data ) && $site_id != false && empty( $failed_data ) ) {
511 $diff_data['plugin_slug'] = $this->plugin_name;
512 $diff_data['url'] = $site_url;
513 $diff_data['site_id'] = $site_id;
514 if ( $original_site_url != false ) {
515 $diff_data['original_url'] = $original_site_url;
516 }
517
518 $request = $this->remote_post( $diff_data );
519 if ( is_wp_error( $request ) ) {
520 update_option( $site_id_data_failed_key, $diff_data, 'no' );
521 } else {
522 $replaced_data = array_merge( $old_sent_data, $diff_data );
523 update_option( $site_id_data_key, $replaced_data, 'no' );
524 }
525 }
526
527 $this->set_track_time();
528
529 if ( isset( $request ) && is_wp_error( $request ) ) {
530 return $request;
531 }
532
533 if ( isset( $request ) ) {
534 return true;
535 }
536 return false;
537 }
538 /**
539 * WP_REMOTE_POST method responsible for send data to the API_URL
540 *
541 * @param array $data
542 * @param array $args
543 * @return void
544 */
545 protected function remote_post( $data = array(), $args = array() ) {
546 if ( empty( $data ) ) {
547 return;
548 }
549
550 $args = wp_parse_args( $args, 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 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 $this->has_notice = true;
612
613 $url_yes = add_query_arg( [
614 'plugin' => $this->plugin_name,
615 'plugin_action' => 'yes',
616 ]
617 );
618 $url_no = add_query_arg( array(
619 'plugin' => $this->plugin_name,
620 'plugin_action' => 'no',
621 )
622 );
623
624 $url_yes = wp_nonce_url( $url_yes, '_wpnonce_optin_' . $this->plugin_name );
625 $url_no = wp_nonce_url( $url_no, '_wpnonce_optin_' . $this->plugin_name );
626
627 // Decide on notice text
628 $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-' . esc_attr( $this->plugin_name ) . '-collect" >' . $this->notice_options['consent_button_text'] . '</a>';
629 $extra_notice_text = $this->notice_options['extra_notice'];
630
631 ?>
632
633 <div class="nx-optin">
634 <p><?php echo wp_kses_post( $notice_text ); ?></p>
635 <div class="wpinsights-data" style="display: none;">
636 <p><?php echo wp_kses_post( $extra_notice_text ); ?></p>
637 </div>
638 <p>
639 <a href="<?php echo esc_url( $url_yes ); ?>" class="button-primary">
640 <?php echo esc_html( $this->notice_options['yes'] ); ?>
641 </a>&nbsp;
642 <a href="<?php echo esc_url( $url_no ); ?>" class="button-secondary">
643 <?php echo esc_html( $this->notice_options['no'] ); ?>
644 </a>
645 </p>
646 </div>
647
648 <?php
649 }
650
651 public function notice_script() {
652 if ( $this->has_notice ) {
653 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>";
654 }
655 }
656 /**
657 * Set all notice options to customized notice.
658 *
659 * @since 3.0.0
660 * @param array $options
661 * @return void
662 */
663 public function set_notice_options( $options = [] ) {
664 $default_options = [
665 'consent_button_text' => __( 'What we collect.', 'wpinsight' ),
666 'yes' => __( 'Sure, I\'d like to help', 'wpinsight' ),
667 'no' => __( 'No Thanks.', 'wpinsight' ),
668 ];
669 $options = wp_parse_args( $options, $default_options );
670 $this->notice_options = $options;
671 }
672 /**
673 * Responsible for track the click from Notice.
674 *
675 * @return void
676 */
677 public function clicked( $notice = null ) {
678 if ( isset( $_GET[ '_wpnonce' ] ) && isset( $_GET['plugin'] ) && isset( $_GET['plugin_action'] ) ) {
679 if ( isset( $_GET['tab'] ) && $_GET['tab'] === 'plugin-information' ) {
680 return;
681 }
682
683 if( ! wp_verify_nonce( $_GET[ '_wpnonce' ], '_wpnonce_optin_' . $this->plugin_name ) ) {
684 return;
685 }
686
687 $plugin = sanitize_text_field( $_GET['plugin'] );
688 $action = sanitize_text_field( $_GET['plugin_action'] );
689 if ( $action == 'yes' ) {
690 $this->schedule_tracking();
691 $this->set_is_tracking_allowed( true, $plugin );
692 if ( $this->do_tracking( true ) ) {
693 $this->update_block_notice( $plugin );
694 }
695 } else {
696 $this->set_is_tracking_allowed( false, $plugin );
697 $this->update_block_notice( $plugin );
698 }
699
700 if( ! is_null ( $notice ) ) {
701 $notice->dismiss->dismiss_notice();
702 }
703
704 /**
705 * Redirect User To the Current URL, but without set query arguments.
706 */
707 wp_safe_redirect( $this->redirect_to() );
708 }
709 }
710 /**
711 * Set if we should block the opt-in notice for this plugin
712 *
713 * @since 3.0.0
714 */
715 public function update_block_notice( $plugin = null ) {
716 if ( empty( $plugin ) ) {
717 $plugin = $this->plugin_name;
718 }
719 $block_notice = get_option( 'wpins_block_notice' );
720 if ( empty( $block_notice ) || ! is_array( $block_notice ) ) {
721 $block_notice = array( $plugin => $plugin );
722 } else {
723 $block_notice[ $plugin ] = $plugin;
724 }
725 update_option( 'wpins_block_notice', $block_notice, 'no' );
726 }
727 /**
728 * AJAX callback when the deactivated form is submitted.
729 *
730 * @since 3.0.0
731 */
732 public function deactivate_reasons_form_submit() {
733 check_ajax_referer( 'wpins_deactivation_nonce', 'security' );
734 if ( isset( $_POST['values'] ) ) {
735 $values = sanitize_text_field( $_POST['values'] );
736 update_option( 'wpins_deactivation_reason_' . $this->plugin_name, $values, 'no' );
737 }
738 if ( isset( $_POST['details'] ) ) {
739 $details = sanitize_text_field( $_POST['details'] );
740 update_option( 'wpins_deactivation_details_' . $this->plugin_name, $details, 'no' );
741 }
742 echo 'success';
743 wp_die();
744 }
745 /**
746 * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
747 *
748 * @since 3.0.0
749 */
750 public function deactivate_action_links( $links ) {
751 /**
752 * Check is tracking allowed or not.
753 */
754 if ( ! $this->is_tracking_allowed() ) {
755 return $links;
756 }
757 if ( isset( $links['deactivate'] ) && $this->include_goodbye_form ) {
758 $deactivation_link = $links['deactivate'];
759 /**
760 * Change the default deactivate button link.
761 */
762 $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 );
763 $links['deactivate'] = $deactivation_link;
764 }
765 return $links;
766 }
767 /**
768 * ALL Deactivate Reasons.
769 *
770 * @since 3.0.0
771 */
772 public function deactivation_reasons() {
773 $form = array();
774 $form['heading'] = __( 'Sorry to see you go', 'wpinsight' );
775 $form['body'] = __( 'Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'wpinsight' );
776
777 $form['options'] = array(
778 __( 'I no longer need the plugin', 'wpinsight' ),
779 [
780 'label' => __( 'I found a better plugin', 'wpinsight' ),
781 'extra_field' => __( 'Please share which plugin', 'wpinsight' ),
782 ],
783 __( "I couldn't get the plugin to work", 'wpinsight' ),
784 __( 'It\'s a temporary deactivation', 'wpinsight' ),
785 [
786 'label' => __( 'Other', 'wpinsight' ),
787 'extra_field' => __( 'Please share the reason', 'wpinsight' ),
788 'type' => 'textarea',
789 ],
790 );
791 return apply_filters( 'wpins_form_text_' . $this->plugin_name, $form );
792 }
793 /**
794 * Deactivate Reasons Form.
795 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
796 *
797 * @since 3.0.0
798 */
799 public function deactivate_reasons_form_style() {
800 ?>
801 <style type="text/css">
802 .wpinsights-form-active-notificationx .wpinsights-goodbye-form-bg {
803 background: rgba(0, 0, 0, .8);
804 position: fixed;
805 top: 0;
806 left: 0;
807 width: 100%;
808 height: 100%;
809 z-index: 9;
810 }
811
812 .wpinsights-goodbye-form-wrapper-notificationx {
813 position: relative;
814 display: none;
815 }
816
817 .wpinsights-form-active-notificationx .wpinsights-goodbye-form-wrapper-notificationx {
818 display: flex !important;
819 position: fixed;
820 top: 0;
821 left: 0;
822 width: 100%;
823 height: 100%;
824 justify-content: center;
825 align-items: center;
826 }
827
828 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form {
829 display: none;
830 }
831
832 .wpinsights-form-active-notificationx .wpinsights-goodbye-form {
833 position: relative !important;
834 width: 550px;
835 max-width: 80%;
836 background: #fff;
837 box-shadow: 2px 8px 23px 3px rgba(0, 0, 0, .2);
838 border-radius: 3px;
839 white-space: normal;
840 overflow: hidden;
841 display: block;
842 z-index: 999999;
843 }
844
845 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-head {
846 background: #fff;
847 color: #495157;
848 padding: 18px;
849 box-shadow: 0 0 8px rgba(0, 0, 0, .1);
850 font-size: 15px;
851 }
852
853 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form .wpinsights-goodbye-form-head strong {
854 font-size: 15px;
855 }
856
857 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body {
858 padding: 8px 18px;
859 color: #333;
860 }
861
862 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body label {
863 padding-left: 5px;
864 color: #6d7882;
865 }
866
867 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {
868 font-weight: 500;
869 font-size: 15px;
870 color: #495157;
871 line-height: 1.4;
872 }
873
874 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options {
875 padding-top: 5px;
876 }
877
878 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul>li {
879 margin-bottom: 15px;
880 }
881
882 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul>li>div {
883 display: inline;
884 padding-left: 3px;
885 }
886
887 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul>li>div>input,
888 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul>li>div>textarea {
889 margin: 10px 18px;
890 padding: 8px;
891 width: 80%;
892 }
893
894 .wpinsights-goodbye-form-wrapper-notificationx .deactivating-spinner {
895 display: none;
896 padding-bottom: 20px !important;
897 }
898
899 .wpinsights-goodbye-form-wrapper-notificationx .deactivating-spinner .spinner {
900 float: none;
901 margin: 4px 4px 0 18px;
902 vertical-align: bottom;
903 visibility: visible;
904 }
905
906 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-footer {
907 padding: 8px 18px;
908 margin-bottom: 15px;
909 }
910
911 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-footer>.wpinsights-goodbye-form-buttons {
912 display: flex;
913 align-items: center;
914 justify-content: space-between;
915 }
916
917 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-footer .wpinsights-submit-btn {
918 background-color: #d30c5c;
919 -webkit-border-radius: 3px;
920 border-radius: 3px;
921 color: #fff;
922 line-height: 1;
923 padding: 15px 20px;
924 font-size: 13px;
925 }
926
927 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {
928 font-size: 13px;
929 color: #a4afb7;
930 background: none;
931 float: right;
932 padding-right: 10px;
933 width: auto;
934 text-decoration: underline;
935 }
936
937 .wpinsights-goodbye-form-wrapper-notificationx .test {}
938 </style>
939
940 <?php
941 }
942
943 /**
944 * Deactivate Reasons Form.
945 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
946 *
947 * @since 3.0.0
948 */
949 public function deactivate_reasons_form_script() {
950 $form = $this->deactivation_reasons();
951
952 $html = '<div class="wpinsights-goodbye-form-head"><strong>' . esc_html( $form['heading'] ) . '</strong></div>';
953 $html .= '<div class="wpinsights-goodbye-form-body"><p class="wpinsights-goodbye-form-caption">' . esc_html( $form['body'] ) . '</p>';
954 if ( is_array( $form['options'] ) ) {
955 $html .= '<div id="wpinsights-goodbye-options" class="wpinsights-goodbye-options"><ul>';
956 foreach ( $form['options'] as $option ) {
957 if ( is_array( $option ) ) {
958 $id = strtolower( str_replace( ' ', '_', esc_attr( $option['label'] ) ) );
959 $id = $id . '_' . $this->plugin_name;
960 $html .= '<li class="has-goodbye-extra">';
961 $html .= '<input type="radio" name="wpinsights-' . esc_attr( $this->plugin_name ) . '-goodbye-options" id="' . esc_attr( $id ) . '" value="' . esc_attr( $option['label'] ) . '">';
962 $html .= '<div><label for="' . esc_attr( $id ) . '">' . esc_attr( $option['label'] ) . '</label>';
963 if ( isset( $option['extra_field'] ) && ! isset( $option['type'] ) ) {
964 $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'] ) . '">';
965 }
966 if ( isset( $option['extra_field'] ) && isset( $option['type'] ) ) {
967 $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'] . '>';
968 }
969 $html .= '</div></li>';
970 } else {
971 $id = strtolower( str_replace( ' ', '_', esc_attr( $option ) ) );
972 $id = $id . '_' . $this->plugin_name;
973 $html .= '<li><input type="radio" name="wpinsights-' . esc_attr( $this->plugin_name ) . '-goodbye-options" id="' . esc_attr( $id ) . '" value="' . esc_attr( $option ) . '"> <label for="' . esc_attr( $id ) . '">' . esc_attr( $option ) . '</label></li>';
974 }
975 }
976 $html .= '</ul></div><!-- .wpinsights-' . esc_attr( $this->plugin_name ) . '-goodbye-options -->';
977 }
978 $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
979 $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', 'wpinsight' ) . '</p>';
980
981 ?>
982 <script type="text/javascript">
983 jQuery(document).ready(function($){
984 $("#wpinsights-goodbye-link-<?php echo esc_attr( $this->plugin_name ); ?>").on("click",function(){
985 // We'll send the user to this deactivation link when they've completed or dismissed the form
986 var url = document.getElementById("wpinsights-goodbye-link-<?php echo esc_attr( $this->plugin_name ); ?>");
987 $('body').toggleClass('wpinsights-form-active-<?php echo esc_attr( $this->plugin_name ); ?>');
988 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $this->plugin_name ); ?> #wpinsights-goodbye-form").fadeIn();
989 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $this->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( $this->plugin_name ); ?>" class="wpinsights-submit-btn" href="#"><?php esc_html_e( 'Submit and Deactivate', 'wpinsight' ); ?></a>&nbsp;<a class="wpsp-put-deactivate-btn" href="'+url+'"><?php esc_html_e( 'Just Deactivate', 'wpinsight' ); ?></a></div></div>');
990 $('#wpinsights-submit-form-<?php echo esc_attr( $this->plugin_name ); ?>').on('click', function(e){
991 // As soon as we click, the body of the form should disappear
992 $("#wpinsights-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .wpinsights-goodbye-form-body").fadeOut();
993 $("#wpinsights-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .wpinsights-goodbye-form-footer").fadeOut();
994 // Fade in spinner
995 $("#wpinsights-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .deactivating-spinner").fadeIn();
996 e.preventDefault();
997 var checkedInput = $("input[name='wpinsights-<?php echo esc_attr( $this->plugin_name ); ?>-goodbye-options']:checked"),
998 checkedInputVal, details;
999 if( checkedInput.length > 0 ) {
1000 checkedInputVal = checkedInput.val();
1001 details = $('input[name="'+ checkedInput[0].id +'"], textarea[name="'+ checkedInput[0].id +'"]').val();
1002 }
1003
1004 if( typeof details === 'undefined' ) {
1005 details = '';
1006 }
1007 if( typeof checkedInputVal === 'undefined' ) {
1008 checkedInputVal = 'No Reason';
1009 }
1010
1011 var data = {
1012 'action': 'deactivation_form_<?php echo esc_attr( $this->plugin_name ); ?>',
1013 'values': checkedInputVal,
1014 'details': details,
1015 'security': "<?php echo wp_create_nonce( 'wpins_deactivation_nonce' ); ?>",
1016 'dataType': "json"
1017 }
1018
1019 $.post(
1020 ajaxurl,
1021 data,
1022 function(response){
1023 // Redirect to original deactivation URL
1024 window.location.href = url;
1025 }
1026 );
1027 });
1028 $('#wpinsights-goodbye-options > ul ').on('click', 'li label, li > input', function( e ){
1029 var parent = $(this).parents('li');
1030 parent.siblings().find('label').next('input, textarea').css('display', 'none');
1031 parent.find('label').next('input, textarea').css('display', 'block');
1032 });
1033 // If we click outside the form, the form will close
1034 $('.wpinsights-goodbye-form-bg').on('click',function(){
1035 $("#wpinsights-goodbye-form").fadeOut();
1036 $('body').removeClass('wpinsights-form-active-<?php echo esc_attr( $this->plugin_name ); ?>');
1037 });
1038 });
1039 });
1040 </script>
1041 <?php
1042 }
1043 }
1044