PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.2.11
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.2.11
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.11, at includes/Admin/PluginInsights.php

1,056 lines 41.4 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') && 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
421 /**
422 * Allow plugin-specific usage data to be merged into the tracking
423 * payload (e.g. NotificationX notification type & source breakdown).
424 *
425 * @see \NotificationX\Core\UsageTracker
426 * @since 3.3.0
427 * @param array $body Collected tracking data.
428 * @param PluginInsights $this Current insights instance.
429 */
430 $body = apply_filters( 'nx_plugin_usage_tracker_data', $body, $this );
431
432 return $body;
433 }
434
435 /**
436 * Collect plugin data,
437 * Retrieve current plugin information
438 *
439 * @since 3.0.0
440 */
441 public function plugin_data() {
442 if ( ! function_exists( 'get_plugin_data' ) ) {
443 include ABSPATH . '/wp-admin/includes/plugin.php';
444 }
445 $plugin = get_plugin_data( $this->plugin_file );
446 return $plugin;
447 }
448 /**
449 * Send the data to insights.
450 *
451 * @since 3.0.0
452 */
453 public function send_data( $body ) {
454 /**
455 * Get SITE ID
456 */
457 $site_id_key = "wpins_{$this->plugin_name}_site_id";
458 $site_id = get_option( $site_id_key, false );
459 $failed_data = [];
460 $site_url = get_bloginfo( 'url' );
461 $original_site_url = get_option( "wpins_{$this->plugin_name}_original_url", false );
462 if ( $original_site_url === false && version_compare( $body['wpins_version'], '3.0.1', '==' ) ) {
463 $site_id = false;
464 }
465 /**
466 * Send Initial Data to API
467 */
468 if ( $site_id == false && $this->item_id !== false && $original_site_url === false ) {
469 if ( isset( $_SERVER['REMOTE_ADDR'] ) && ! empty( $_SERVER['REMOTE_ADDR'] && $_SERVER['REMOTE_ADDR'] != '127.0.0.1' ) ) {
470 $country_request = wp_remote_get( 'http://ip-api.com/json/' . $_SERVER['REMOTE_ADDR'] . '?fields=country' );
471 if ( ! is_wp_error( $country_request ) && $country_request['response']['code'] == 200 ) {
472 $ip_data = json_decode( $country_request['body'] );
473 $body['country'] = isset( $ip_data->country ) ? $ip_data->country : 'NOT SET';
474 }
475 }
476
477 $body['plugin_slug'] = $this->plugin_name;
478 $body['url'] = $site_url;
479 $body['item_id'] = $this->item_id;
480
481 $request = $this->remote_post( $body );
482 if ( ! is_wp_error( $request ) && $request['response']['code'] == 200 ) {
483 $retrieved_body = json_decode( wp_remote_retrieve_body( $request ), true );
484 if ( is_array( $retrieved_body ) && isset( $retrieved_body['siteId'] ) ) {
485 update_option( $site_id_key, $retrieved_body['siteId'], 'no' );
486 update_option( "wpins_{$this->plugin_name}_original_url", $site_url, 'no' );
487 update_option( "wpins_{$this->plugin_name}_{$retrieved_body['siteId']}", $body, 'no' );
488 }
489 } else {
490 $failed_data = $body;
491 }
492 }
493
494 $site_id_data_key = "wpins_{$this->plugin_name}_{$site_id}";
495 $site_id_data_failed_key = "wpins_{$this->plugin_name}_{$site_id}_send_failed";
496
497 if ( $site_id != false ) {
498 $old_sent_data = get_option( $site_id_data_key, [] );
499 $diff_data = $this->diff( $body, $old_sent_data );
500 $failed_data = get_option( $site_id_data_failed_key, [] );
501 if ( ! empty( $failed_data ) && $diff_data != $failed_data ) {
502 $failed_data = array_merge( $failed_data, $diff_data );
503 }
504 }
505
506 if ( ! empty( $failed_data ) && $site_id != false ) {
507 $failed_data['plugin_slug'] = $this->plugin_name;
508 $failed_data['url'] = $site_url;
509 $failed_data['site_id'] = $site_id;
510 if ( $original_site_url != false ) {
511 $failed_data['original_url'] = $original_site_url;
512 }
513
514 $request = $this->remote_post( $failed_data );
515 if ( ! is_wp_error( $request ) ) {
516 delete_option( $site_id_data_failed_key );
517 $replaced_data = array_merge( $old_sent_data, $failed_data );
518 update_option( $site_id_data_key, $replaced_data, 'no' );
519 }
520 }
521
522 if ( ! empty( $diff_data ) && $site_id != false && empty( $failed_data ) ) {
523 $diff_data['plugin_slug'] = $this->plugin_name;
524 $diff_data['url'] = $site_url;
525 $diff_data['site_id'] = $site_id;
526 if ( $original_site_url != false ) {
527 $diff_data['original_url'] = $original_site_url;
528 }
529
530 $request = $this->remote_post( $diff_data );
531 if ( is_wp_error( $request ) ) {
532 update_option( $site_id_data_failed_key, $diff_data, 'no' );
533 } else {
534 $replaced_data = array_merge( $old_sent_data, $diff_data );
535 update_option( $site_id_data_key, $replaced_data, 'no' );
536 }
537 }
538
539 $this->set_track_time();
540
541 if ( isset( $request ) && is_wp_error( $request ) ) {
542 return $request;
543 }
544
545 if ( isset( $request ) ) {
546 return true;
547 }
548 return false;
549 }
550 /**
551 * WP_REMOTE_POST method responsible for send data to the API_URL
552 *
553 * @param array $data
554 * @param array $args
555 * @return void
556 */
557 protected function remote_post( $data = array(), $args = array() ) {
558 if ( empty( $data ) ) {
559 return;
560 }
561
562 $args = wp_parse_args( $args, array(
563 'method' => 'POST',
564 'timeout' => 30,
565 'redirection' => 5,
566 'httpversion' => '1.1',
567 'blocking' => true,
568 'body' => $data,
569 'user-agent' => 'PUT/1.0.0; ' . get_bloginfo( 'url' ),
570 )
571 );
572
573 $request = wp_remote_post( esc_url( self::API_URL ), $args );
574 if ( is_wp_error( $request ) || ( isset( $request['response'], $request['response']['code'] ) && $request['response']['code'] != 200 ) ) {
575 return new \WP_Error( 500, 'Something went wrong.' );
576 }
577 return $request;
578 }
579 /**
580 * Difference between old and new data
581 *
582 * @param array $new_data
583 * @param array $old_data
584 * @return void
585 */
586 protected function diff( $new_data, $old_data ) {
587 $data = [];
588 if ( ! empty( $new_data ) ) {
589 foreach ( $new_data as $key => $value ) {
590 if ( isset( $old_data[ $key ] ) ) {
591 if ( $old_data[ $key ] == $value ) {
592 continue;
593 }
594 }
595 $data[ $key ] = $value;
596 }
597 }
598 return $data;
599 }
600 /**
601 * Display the admin notice to users to allow them to opt in
602 *
603 * @since 3.0.0
604 */
605 public function notice() {
606 /**
607 * Return if notice is not set.
608 */
609 if ( ! isset( $this->notice_options['notice'] ) ) {
610 return;
611 }
612 /**
613 * Check is allowed or blocked for notice.
614 */
615 $block_notice = get_option( 'wpins_block_notice' );
616 if ( isset( $block_notice[ $this->plugin_name ] ) ) {
617 return;
618 }
619 if ( ! current_user_can( 'manage_options' ) ) {
620 return;
621 }
622
623 $this->has_notice = true;
624
625 $url_yes = add_query_arg( [
626 'plugin' => $this->plugin_name,
627 'plugin_action' => 'yes',
628 ]
629 );
630 $url_no = add_query_arg( array(
631 'plugin' => $this->plugin_name,
632 'plugin_action' => 'no',
633 )
634 );
635
636 $url_yes = wp_nonce_url( $url_yes, '_wpnonce_optin_' . $this->plugin_name );
637 $url_no = wp_nonce_url( $url_no, '_wpnonce_optin_' . $this->plugin_name );
638
639 // Decide on notice text
640 $notice_text = $this->notice_options['notice'] . ' <a href="#" class="wpinsights-' . esc_attr( $this->plugin_name ) . '-collect" >' . $this->notice_options['consent_button_text'] . '</a>';
641 $extra_notice_text = $this->notice_options['extra_notice'];
642
643 ?>
644
645 <div class="nx-optin">
646 <p><?php echo wp_kses_post( $notice_text ); ?></p>
647 <div class="wpinsights-data" style="display: none;">
648 <p><?php echo wp_kses_post( $extra_notice_text ); ?></p>
649 </div>
650 <p>
651 <a href="<?php echo esc_url( $url_yes ); ?>" class="button-primary">
652 <?php echo esc_html( $this->notice_options['yes'] ); ?>
653 </a>&nbsp;
654 <a href="<?php echo esc_url( $url_no ); ?>" class="button-secondary">
655 <?php echo esc_html( $this->notice_options['no'] ); ?>
656 </a>
657 </p>
658 </div>
659
660 <?php
661 }
662
663 public function notice_script() {
664 if ( $this->has_notice ) {
665 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>";
666 }
667 }
668 /**
669 * Set all notice options to customized notice.
670 *
671 * @since 3.0.0
672 * @param array $options
673 * @return void
674 */
675 public function set_notice_options( $options = [] ) {
676 $default_options = [
677 'consent_button_text' => __( 'What we collect.', 'wpinsight' ),
678 'yes' => __( 'Sure, I\'d like to help', 'wpinsight' ),
679 'no' => __( 'No Thanks.', 'wpinsight' ),
680 ];
681 $options = wp_parse_args( $options, $default_options );
682 $this->notice_options = $options;
683 }
684 /**
685 * Responsible for track the click from Notice.
686 *
687 * @return void
688 */
689 public function clicked( $notice = null ) {
690 if ( isset( $_GET[ '_wpnonce' ] ) && isset( $_GET['plugin'] ) && isset( $_GET['plugin_action'] ) ) {
691 if ( isset( $_GET['tab'] ) && $_GET['tab'] === 'plugin-information' ) {
692 return;
693 }
694
695 if( ! wp_verify_nonce( $_GET[ '_wpnonce' ], '_wpnonce_optin_' . $this->plugin_name ) ) {
696 return;
697 }
698
699 $plugin = sanitize_text_field( $_GET['plugin'] );
700 $action = sanitize_text_field( $_GET['plugin_action'] );
701 if ( $action == 'yes' ) {
702 $this->schedule_tracking();
703 $this->set_is_tracking_allowed( true, $plugin );
704 if ( $this->do_tracking( true ) ) {
705 $this->update_block_notice( $plugin );
706 }
707 } else {
708 $this->set_is_tracking_allowed( false, $plugin );
709 $this->update_block_notice( $plugin );
710 }
711
712 if( ! is_null ( $notice ) ) {
713 $notice->dismiss->dismiss_notice();
714 }
715
716 /**
717 * Redirect User To the Current URL, but without set query arguments.
718 */
719 wp_safe_redirect( $this->redirect_to() );
720 }
721 }
722 /**
723 * Set if we should block the opt-in notice for this plugin
724 *
725 * @since 3.0.0
726 */
727 public function update_block_notice( $plugin = null ) {
728 if ( empty( $plugin ) ) {
729 $plugin = $this->plugin_name;
730 }
731 $block_notice = get_option( 'wpins_block_notice' );
732 if ( empty( $block_notice ) || ! is_array( $block_notice ) ) {
733 $block_notice = array( $plugin => $plugin );
734 } else {
735 $block_notice[ $plugin ] = $plugin;
736 }
737 update_option( 'wpins_block_notice', $block_notice, 'no' );
738 }
739 /**
740 * AJAX callback when the deactivated form is submitted.
741 *
742 * @since 3.0.0
743 */
744 public function deactivate_reasons_form_submit() {
745 check_ajax_referer( 'wpins_deactivation_nonce', 'security' );
746 if ( isset( $_POST['values'] ) ) {
747 $values = sanitize_text_field( $_POST['values'] );
748 update_option( 'wpins_deactivation_reason_' . $this->plugin_name, $values, 'no' );
749 }
750 if ( isset( $_POST['details'] ) ) {
751 $details = sanitize_text_field( $_POST['details'] );
752 update_option( 'wpins_deactivation_details_' . $this->plugin_name, $details, 'no' );
753 }
754 echo 'success';
755 wp_die();
756 }
757 /**
758 * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
759 *
760 * @since 3.0.0
761 */
762 public function deactivate_action_links( $links ) {
763 /**
764 * Check is tracking allowed or not.
765 */
766 if ( ! $this->is_tracking_allowed() ) {
767 return $links;
768 }
769 if ( isset( $links['deactivate'] ) && $this->include_goodbye_form ) {
770 $deactivation_link = $links['deactivate'];
771 /**
772 * Change the default deactivate button link.
773 */
774 $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 );
775 $links['deactivate'] = $deactivation_link;
776 }
777 return $links;
778 }
779 /**
780 * ALL Deactivate Reasons.
781 *
782 * @since 3.0.0
783 */
784 public function deactivation_reasons() {
785 $form = array();
786 $form['heading'] = __( 'Sorry to see you go', 'wpinsight' );
787 $form['body'] = __( 'Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'wpinsight' );
788
789 $form['options'] = array(
790 __( 'I no longer need the plugin', 'wpinsight' ),
791 [
792 'label' => __( 'I found a better plugin', 'wpinsight' ),
793 'extra_field' => __( 'Please share which plugin', 'wpinsight' ),
794 ],
795 __( "I couldn't get the plugin to work", 'wpinsight' ),
796 __( 'It\'s a temporary deactivation', 'wpinsight' ),
797 [
798 'label' => __( 'Other', 'wpinsight' ),
799 'extra_field' => __( 'Please share the reason', 'wpinsight' ),
800 'type' => 'textarea',
801 ],
802 );
803 return apply_filters( 'wpins_form_text_' . $this->plugin_name, $form );
804 }
805 /**
806 * Deactivate Reasons Form.
807 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
808 *
809 * @since 3.0.0
810 */
811 public function deactivate_reasons_form_style() {
812 ?>
813 <style type="text/css">
814 .wpinsights-form-active-notificationx .wpinsights-goodbye-form-bg {
815 background: rgba(0, 0, 0, .8);
816 position: fixed;
817 top: 0;
818 left: 0;
819 width: 100%;
820 height: 100%;
821 z-index: 9;
822 }
823
824 .wpinsights-goodbye-form-wrapper-notificationx {
825 position: relative;
826 display: none;
827 }
828
829 .wpinsights-form-active-notificationx .wpinsights-goodbye-form-wrapper-notificationx {
830 display: flex !important;
831 position: fixed;
832 top: 0;
833 left: 0;
834 width: 100%;
835 height: 100%;
836 justify-content: center;
837 align-items: center;
838 }
839
840 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form {
841 display: none;
842 }
843
844 .wpinsights-form-active-notificationx .wpinsights-goodbye-form {
845 position: relative !important;
846 width: 550px;
847 max-width: 80%;
848 background: #fff;
849 box-shadow: 2px 8px 23px 3px rgba(0, 0, 0, .2);
850 border-radius: 3px;
851 white-space: normal;
852 overflow: hidden;
853 display: block;
854 z-index: 999999;
855 }
856
857 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-head {
858 background: #fff;
859 color: #495157;
860 padding: 18px;
861 box-shadow: 0 0 8px rgba(0, 0, 0, .1);
862 font-size: 15px;
863 }
864
865 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form .wpinsights-goodbye-form-head strong {
866 font-size: 15px;
867 }
868
869 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body {
870 padding: 8px 18px;
871 color: #333;
872 }
873
874 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body label {
875 padding-left: 5px;
876 color: #6d7882;
877 }
878
879 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body .wpinsights-goodbye-form-caption {
880 font-weight: 500;
881 font-size: 15px;
882 color: #495157;
883 line-height: 1.4;
884 }
885
886 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options {
887 padding-top: 5px;
888 }
889
890 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul>li {
891 margin-bottom: 15px;
892 }
893
894 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul>li>div {
895 display: inline;
896 padding-left: 3px;
897 }
898
899 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul>li>div>input,
900 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-body #wpinsights-goodbye-options ul>li>div>textarea {
901 margin: 10px 18px;
902 padding: 8px;
903 width: 80%;
904 }
905
906 .wpinsights-goodbye-form-wrapper-notificationx .deactivating-spinner {
907 display: none;
908 padding-bottom: 20px !important;
909 }
910
911 .wpinsights-goodbye-form-wrapper-notificationx .deactivating-spinner .spinner {
912 float: none;
913 margin: 4px 4px 0 18px;
914 vertical-align: bottom;
915 visibility: visible;
916 }
917
918 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-footer {
919 padding: 8px 18px;
920 margin-bottom: 15px;
921 }
922
923 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-footer>.wpinsights-goodbye-form-buttons {
924 display: flex;
925 align-items: center;
926 justify-content: space-between;
927 }
928
929 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-footer .wpinsights-submit-btn {
930 background-color: #d30c5c;
931 -webkit-border-radius: 3px;
932 border-radius: 3px;
933 color: #fff;
934 line-height: 1;
935 padding: 15px 20px;
936 font-size: 13px;
937 }
938
939 .wpinsights-goodbye-form-wrapper-notificationx .wpinsights-goodbye-form-footer .wpinsights-deactivate-btn {
940 font-size: 13px;
941 color: #a4afb7;
942 background: none;
943 float: right;
944 padding-right: 10px;
945 width: auto;
946 text-decoration: underline;
947 }
948
949 .wpinsights-goodbye-form-wrapper-notificationx .test {}
950 </style>
951
952 <?php
953 }
954
955 /**
956 * Deactivate Reasons Form.
957 * This form will appears when user wants to deactivate the plugin to send you deactivated reasons.
958 *
959 * @since 3.0.0
960 */
961 public function deactivate_reasons_form_script() {
962 $form = $this->deactivation_reasons();
963
964 $html = '<div class="wpinsights-goodbye-form-head"><strong>' . esc_html( $form['heading'] ) . '</strong></div>';
965 $html .= '<div class="wpinsights-goodbye-form-body"><p class="wpinsights-goodbye-form-caption">' . esc_html( $form['body'] ) . '</p>';
966 if ( is_array( $form['options'] ) ) {
967 $html .= '<div id="wpinsights-goodbye-options" class="wpinsights-goodbye-options"><ul>';
968 foreach ( $form['options'] as $option ) {
969 if ( is_array( $option ) ) {
970 $id = strtolower( str_replace( ' ', '_', esc_attr( $option['label'] ) ) );
971 $id = $id . '_' . $this->plugin_name;
972 $html .= '<li class="has-goodbye-extra">';
973 $html .= '<input type="radio" name="wpinsights-' . esc_attr( $this->plugin_name ) . '-goodbye-options" id="' . esc_attr( $id ) . '" value="' . esc_attr( $option['label'] ) . '">';
974 $html .= '<div><label for="' . esc_attr( $id ) . '">' . esc_attr( $option['label'] ) . '</label>';
975 if ( isset( $option['extra_field'] ) && ! isset( $option['type'] ) ) {
976 $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'] ) . '">';
977 }
978 if ( isset( $option['extra_field'] ) && isset( $option['type'] ) ) {
979 $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'] . '>';
980 }
981 $html .= '</div></li>';
982 } else {
983 $id = strtolower( str_replace( ' ', '_', esc_attr( $option ) ) );
984 $id = $id . '_' . $this->plugin_name;
985 $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>';
986 }
987 }
988 $html .= '</ul></div><!-- .wpinsights-' . esc_attr( $this->plugin_name ) . '-goodbye-options -->';
989 }
990 $html .= '</div><!-- .wpinsights-goodbye-form-body -->';
991 $html .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . __( 'Submitting form', 'wpinsight' ) . '</p>';
992
993 ?>
994 <script type="text/javascript">
995 jQuery(document).ready(function($){
996 $("#wpinsights-goodbye-link-<?php echo esc_attr( $this->plugin_name ); ?>").on("click",function(){
997 // We'll send the user to this deactivation link when they've completed or dismissed the form
998 var url = document.getElementById("wpinsights-goodbye-link-<?php echo esc_attr( $this->plugin_name ); ?>");
999 $('body').toggleClass('wpinsights-form-active-<?php echo esc_attr( $this->plugin_name ); ?>');
1000 $(".wpinsights-goodbye-form-wrapper-<?php echo esc_attr( $this->plugin_name ); ?> #wpinsights-goodbye-form").fadeIn();
1001 $(".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>');
1002 $('#wpinsights-submit-form-<?php echo esc_attr( $this->plugin_name ); ?>').on('click', function(e){
1003 // As soon as we click, the body of the form should disappear
1004 $("#wpinsights-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .wpinsights-goodbye-form-body").fadeOut();
1005 $("#wpinsights-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .wpinsights-goodbye-form-footer").fadeOut();
1006 // Fade in spinner
1007 $("#wpinsights-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .deactivating-spinner").fadeIn();
1008 e.preventDefault();
1009 var checkedInput = $("input[name='wpinsights-<?php echo esc_attr( $this->plugin_name ); ?>-goodbye-options']:checked"),
1010 checkedInputVal, details;
1011 if( checkedInput.length > 0 ) {
1012 checkedInputVal = checkedInput.val();
1013 details = $('input[name="'+ checkedInput[0].id +'"], textarea[name="'+ checkedInput[0].id +'"]').val();
1014 }
1015
1016 if( typeof details === 'undefined' ) {
1017 details = '';
1018 }
1019 if( typeof checkedInputVal === 'undefined' ) {
1020 checkedInputVal = 'No Reason';
1021 }
1022
1023 var data = {
1024 'action': 'deactivation_form_<?php echo esc_attr( $this->plugin_name ); ?>',
1025 'values': checkedInputVal,
1026 'details': details,
1027 'security': "<?php echo wp_create_nonce( 'wpins_deactivation_nonce' ); ?>",
1028 'dataType': "json"
1029 }
1030
1031 $.post(
1032 ajaxurl,
1033 data,
1034 function(response){
1035 // Redirect to original deactivation URL
1036 window.location.href = url;
1037 }
1038 );
1039 });
1040 $('#wpinsights-goodbye-options > ul ').on('click', 'li label, li > input', function( e ){
1041 var parent = $(this).parents('li');
1042 parent.siblings().find('label').next('input, textarea').css('display', 'none');
1043 parent.find('label').next('input, textarea').css('display', 'block');
1044 });
1045 // If we click outside the form, the form will close
1046 $('.wpinsights-goodbye-form-bg').on('click',function(){
1047 $("#wpinsights-goodbye-form").fadeOut();
1048 $('body').removeClass('wpinsights-form-active-<?php echo esc_attr( $this->plugin_name ); ?>');
1049 });
1050 });
1051 });
1052 </script>
1053 <?php
1054 }
1055 }
1056