<?php

/**
 * Wisdom Tracker class for PMPro.
 *
 * Denote any modifications to this file to facilitate easier updates.
 *
 * @link https://wisdomplugin.com/
 *
 * @since 2.8
 */
class PMPro_Wisdom_Tracker {

	private $wisdom_version = '1.2.5';
	private $home_url = '';
	private $plugin_file = '';
	private $plugin_name = '';
	private $options = [];
	private $require_optin = true;
	private $include_goodbye_form = true;
	private $marketing = false;
	private $collect_email = false;
	private $what_am_i = 'plugin';
	private $theme_allows_tracking = 0;

	/**
	 * Class constructor
	 *
	 * @param $_home_url                   The URL to the site we're sending data to
	 * @param $_plugin_slug                The slug for this plugin (PMPRO MODIFICATION).
	 * @param $_plugin_file                The file path for this plugin
	 * @param $_options                    Plugin options to track
	 * @param $_require_optin              Whether user opt-in is required
	 * @param $_include_goodbye_form       Whether to include a form when the user deactivates
	 * @param $_marketing                  Marketing method:
	 *                                     0: Don't collect email addresses
	 *                                     1: Request permission same time as tracking opt-in
	 *                                     2: Request permission after opt-in
	 */
	public function __construct(
		$_plugin_file, $_plugin_slug, $_home_url, $_options, $_require_optin = true, $_include_goodbye_form = true, $_marketing = false
	) {
		$this->plugin_file = $_plugin_file;
		$this->home_url    = trailingslashit( $_home_url );

		// If the filename is 'functions' then we're tracking a theme
		if ( basename( $this->plugin_file, '.php' ) != 'functions' ) {
			$this->plugin_name = basename( $this->plugin_file, '.php' );

			// PMPRO MODIFICATION.
			if ( ! empty( $_plugin_slug ) ) {
				$this->plugin_name = $_plugin_slug;
			}
		} else {
			$this->what_am_i = 'theme';
			$theme           = wp_get_theme();
			if ( $theme->Name ) {
				$this->plugin_name = sanitize_text_field( $theme->Name );
			}
		}

		$this->options              = $_options;
		$this->require_optin        = $_require_optin;
		$this->include_goodbye_form = $_include_goodbye_form;
		$this->marketing            = $_marketing;

		// Only use this on switching theme
		$this->theme_allows_tracking = get_theme_mod( 'wisdom-allow-tracking', 0 );

		// Schedule / deschedule tracking when activated / deactivated
		if ( $this->what_am_i == 'theme' ) {
			// Need to think about scheduling for sites that have already activated the theme
			add_action( 'after_switch_theme', [ $this, 'schedule_tracking' ] );
			add_action( 'switch_theme', [ $this, 'deactivate_this_plugin' ] );
		} else {
			register_activation_hook( $this->plugin_file, [ $this, 'schedule_tracking' ] );
			register_deactivation_hook( $this->plugin_file, [ $this, 'deactivate_this_plugin' ] );
		}

		// Get it going
		$this->init();
	}

	public function init() {
		// Check marketing
		if ( $this->marketing == 3 ) {
			$this->set_can_collect_email( true, $this->plugin_name );
		}

		// Check whether opt-in is required
		// If not, then tracking is allowed
		if ( ! $this->require_optin ) {
			$this->set_can_collect_email( true, $this->plugin_name );
			$this->set_is_tracking_allowed( true );
			$this->update_block_notice();
			$this->do_tracking();
		}

		// Hook our do_tracking function to Action Scheduler
		$this->schedule_tracking();

		// Use this action for local testing
		// add_action( 'admin_init', array( $this, 'do_tracking' ) );

		// Display the admin notice on activation
		add_action( 'admin_init', [ $this, 'set_notification_time' ] );
		add_action( 'admin_notices', [ $this, 'optin_notice' ] );
		add_action( 'admin_notices', [ $this, 'marketing_notice' ] );

		// Deactivation
		add_filter( 'plugin_action_links_' . plugin_basename( $this->plugin_file ), [ $this, 'filter_action_links' ] );
		add_action( 'admin_footer-plugins.php', [ $this, 'goodbye_ajax' ] );
		add_action( 'wp_ajax_goodbye_form', [ $this, 'goodbye_form_callback' ] );
	}

	/**
	 * When the plugin is activated
	 * Create scheduled event
	 * And check if tracking is enabled - perhaps the plugin has been reactivated
	 *
	 * @since 1.0.0
	 * @modified 3.5 Now with Action Scheduler support
	 */
	public function schedule_tracking() {
		$schedule = $this->get_schedule();
		switch ( $schedule ) {
			case 'daily':
				$hook = 'pmpro_schedule_daily';
				break;
			case 'weekly':
				$hook = 'pmpro_schedule_weekly';
				break;
			case 'monthly':
				$hook = 'pmpro_schedule_monthly';
				break;
			default:
				$hook = 'pmpro_schedule_monthly';
		}
		add_action( $hook, [ $this, 'do_tracking' ] );
	}

	/**
	 * Get how frequently data is tracked back
	 *
	 * @since 1.2.3
	 */
	public function get_schedule() {
		// Could be daily, weekly or monthly
		$schedule = apply_filters( 'wisdom_filter_schedule_' . $this->plugin_name, 'monthly' );

		return $schedule;
	}

	/**
	 * This is our function to get everything going
	 * Check that user has opted in
	 * Collect data
	 * Then send it back
	 *
	 * @since 1.0.0
	 *
	 * @param $force    Force tracking if it's not time
	 */
	public function do_tracking( $force = false ) {
		// If the home site hasn't been defined, we just drop out. Nothing much we can do.
		if ( ! $this->home_url ) {
			return;
		}

		// Check to see if the user has opted in to tracking
		$allow_tracking = $this->get_is_tracking_allowed();
		if ( ! $allow_tracking ) {
			return;
		}

		// Check to see if it's time to track
		$track_time = $this->get_is_time_to_track();
		if ( ! $track_time && ! $force ) {
			return;
		}

		$this->set_admin_email();

		// Get our data
		$body = $this->get_data();

		// Send the data
		$this->send_data( $body );
	}

	/**
	 * We hook this to admin_init when the user accepts tracking
	 * Ensures the email address is available
	 *
	 * @since 1.2.1
	 */
	public function force_tracking() {
		$this->do_tracking( true ); // Run this straightaway
	}

	/**
	 * Send the data to the home site
	 *
	 * @since 1.0.0
	 */
	public function send_data( $body ) {
		$request = wp_remote_post( esc_url( $this->home_url . '?usage_tracker=hello' ), [
			'method'      => 'POST',
			'timeout'     => 20,
			'redirection' => 5,
			'httpversion' => '1.1',
			'blocking'    => true,
			'body'        => $body,
			'user-agent'  => 'PUT/1.0.0; ' . home_url(),
		] );

		$this->set_track_time();

		if ( is_wp_error( $request ) ) {
			return $request;
		}
	}

	/**
	 * Here we collect most of the data
	 *
	 * @since 1.0.0
	 */
	public function get_data() {
		// Use this to pass error messages back if necessary
		$body['message'] = '';

		// Use this array to send data back
		$body = [
			'plugin_slug'    => sanitize_text_field( $this->plugin_name ),
			'url'            => home_url(),
			'site_name'      => get_bloginfo( 'name' ),
			'site_version'   => get_bloginfo( 'version' ),
			'site_language'  => get_bloginfo( 'language' ),
			'charset'        => get_bloginfo( 'charset' ),
			'wisdom_version' => $this->wisdom_version,
			'php_version'    => phpversion(),
			'multisite'      => is_multisite(),
			'file_location'  => __FILE__,
			'product_type'   => esc_html( $this->what_am_i ),
		];

		// Collect the email if the correct option has been set
		if ( $this->get_can_collect_email() ) {
			$body['email'] = $this->get_admin_email();
		}
		$body['marketing_method'] = $this->marketing;

		$body['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( $_SERVER['SERVER_SOFTWARE'] ) : '';

		// Extra PHP fields
		$body['memory_limit']        = ini_get( 'memory_limit' );
		$body['upload_max_size']     = ini_get( 'upload_max_size' );
		$body['post_max_size']       = ini_get( 'post_max_size' );
		$body['upload_max_filesize'] = ini_get( 'upload_max_filesize' );
		$body['max_execution_time']  = ini_get( 'max_execution_time' );
		$body['max_input_time']      = ini_get( 'max_input_time' );

		// Retrieve current plugin information
		if ( ! function_exists( 'get_plugins' ) ) {
			include ABSPATH . '/wp-admin/includes/plugin.php';
		}

		$plugins        = array_keys( get_plugins() );
		$active_plugins = get_option( 'active_plugins', [] );

		foreach ( $plugins as $key => $plugin ) {
			if ( in_array( $plugin, $active_plugins, true ) ) {
				// Remove active plugins from list so we can show active and inactive separately
				unset( $plugins[ $key ] );
			}
		}

		$body['active_plugins']   = $active_plugins;
		$body['inactive_plugins'] = $plugins;

		// Check text direction
		$body['text_direction'] = 'LTR';
		if ( function_exists( 'is_rtl' ) ) {
			if ( is_rtl() ) {
				$body['text_direction'] = 'RTL';
			}
		} else {
			$body['text_direction'] = 'not set';
		}

		/**
		 * Get our plugin data
		 * Currently we grab plugin name and version
		 * Or, return a message if the plugin data is not available
		 *
		 * @since 1.0.0
		 */
		$plugin         = $this->plugin_data();
		$body['status'] = 'Active'; // Never translated
		if ( empty( $plugin ) ) {
			// We can't find the plugin data
			// Send a message back to our home site
			$body['message'] .= esc_html__( "We can't detect any product information. This is most probably because you have not included the code snippet.", 'paid-memberships-pro' );
			$body['status']  = 'Data not found'; // Never translated
		} else {
			if ( isset( $plugin['Name'] ) ) {
				$body['plugin'] = sanitize_text_field( $plugin['Name'] );
			}
			if ( isset( $plugin['Version'] ) ) {
				$body['version'] = sanitize_text_field( $plugin['Version'] );
			}
		}

		/**
		 * Get our plugin options
		 *
		 * @since 1.0.0
		 */
		$options        = $this->options;
		$plugin_options = [];
		if ( ! empty( $options ) && is_array( $options ) ) {
			foreach ( $options as $option ) {
				$fields = get_option( $option );
				// Check for permission to send this option
				if ( isset( $fields['wisdom_registered_setting'] ) ) {
					foreach ( $fields as $key => $value ) {
						$plugin_options[ $key ] = $value;
					}
				}
			}
		}
		$body['plugin_options']        = $this->options; // Returns array
		$body['plugin_options_fields'] = $plugin_options; // Returns object

		/**
		 * Get our theme data
		 * Currently we grab theme name and version
		 *
		 * @since 1.0.0
		 */
		$theme = wp_get_theme();
		if ( $theme->Name ) {
			$body['theme'] = sanitize_text_field( $theme->Name );
		}
		if ( $theme->Version ) {
			$body['theme_version'] = sanitize_text_field( $theme->Version );
		}
		if ( $theme->Template ) {
			$body['theme_parent'] = sanitize_text_field( $theme->Template );
		}

		// PMPRO MODIFICATION.
		/**
		 * Allow filtering the data to be sent to the Wisdom plugin site.
		 *
		 * @since 2.8
		 *
		 * @param array $body The data to be sent to the Wisdom plugin site.
		 */
		$body = apply_filters( "wisdom_tracker_data_{$this->plugin_name}", $body );

		// Return the data
		return $body;
	}

	/**
	 * Return plugin data
	 *
	 * @since 1.0.0
	 */
	public function plugin_data() {
		// Being cautious here
		if ( ! function_exists( 'get_plugin_data' ) ) {
			include ABSPATH . '/wp-admin/includes/plugin.php';
		}
		// Retrieve current plugin information
		$plugin = get_plugin_data( $this->plugin_file );

		return $plugin;
	}

	/**
	 * Deactivating plugin
	 *
	 * @since 1.0.0
	 */
	public function deactivate_this_plugin() {
		// Check to see if the user has opted in to tracking
		if ( $this->what_am_i == 'theme' ) {
			$allow_tracking = $this->theme_allows_tracking;
		} else {
			$allow_tracking = $this->get_is_tracking_allowed();
		}

		if ( ! $allow_tracking ) {
			return;
		}

		$body                     = $this->get_data();
		$body['status']           = 'Deactivated'; // Never translated
		$body['deactivated_date'] = time();

		// Add deactivation form data
		if ( false !== get_option( 'wisdom_deactivation_reason_' . $this->plugin_name ) ) {
			$body['deactivation_reason'] = get_option( 'wisdom_deactivation_reason_' . $this->plugin_name );
		}
		if ( false !== get_option( 'wisdom_deactivation_details_' . $this->plugin_name ) ) {
			$body['deactivation_details'] = get_option( 'wisdom_deactivation_details_' . $this->plugin_name );
		}

		$this->send_data( $body );
		// Clear scheduled update
		wp_clear_scheduled_hook( 'put_do_weekly_action' );

		// Clear the wisdom_last_track_time value for this plugin
		// @since 1.2.2
		$track_time = get_option( 'wisdom_last_track_time' );
		if ( isset( $track_time[ $this->plugin_name ] ) ) {
			unset( $track_time[ $this->plugin_name ] );
		}
		update_option( 'wisdom_last_track_time', $track_time );
	}

	/**
	 * Is tracking allowed?
	 *
	 * @since 1.0.0
	 */
	public function get_is_tracking_allowed() {
		// First, check if the user has changed their mind and opted out of tracking
		if ( $this->has_user_opted_out() ) {
			$this->set_is_tracking_allowed( false, $this->plugin_name );

			// PMPRO MODIFICATION.
			$this->set_can_collect_email( false, $this->plugin_name );

			return false;
		}

		if ( $this->what_am_i == 'theme' ) {
			$mod = get_theme_mod( 'wisdom-allow-tracking', 0 );
			if ( $mod ) {
				return true;
			}
		} else {
			// The wisdom_allow_tracking option is an array of plugins that are being tracked
			$allow_tracking = get_option( 'wisdom_allow_tracking' );
			// If this plugin is in the array, then tracking is allowed
			if ( isset( $allow_tracking[ $this->plugin_name ] ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Set if tracking is allowed
	 * Option is an array of all plugins with tracking permitted
	 * More than one plugin may be using the tracker
	 *
	 * @since 1.0.0
	 *
	 * @param $is_allowed    Boolean        true if tracking is allowed, false if not
	 */
	public function set_is_tracking_allowed( $is_allowed, $plugin = null ) {
		if ( empty( $plugin ) ) {
			$plugin = $this->plugin_name;
		}

		// The wisdom_allow_tracking option is an array of plugins that are being tracked
		$allow_tracking = get_option( 'wisdom_allow_tracking' );

		// If the user has decided to opt out
		if ( $this->has_user_opted_out() ) {
			if ( $this->what_am_i == 'theme' ) {
				set_theme_mod( 'wisdom-allow-tracking', 0 );
			} else {
				if ( isset( $allow_tracking[ $plugin ] ) ) {
					unset( $allow_tracking[ $plugin ] );
				}
			}
		} elseif ( $is_allowed || ! $this->require_optin ) {
			// If the user has agreed to allow tracking or if opt-in is not required

			if ( $this->what_am_i == 'theme' ) {
				set_theme_mod( 'wisdom-allow-tracking', 1 );
			} else {
				if ( empty( $allow_tracking ) || ! is_array( $allow_tracking ) ) {
					// If nothing exists in the option yet, start a new array with the plugin name
					$allow_tracking = [ $plugin => $plugin ];
				} else {
					// Else add the plugin name to the array
					$allow_tracking[ $plugin ] = $plugin;
				}
			}
		} else {
			if ( $this->what_am_i == 'theme' ) {
				set_theme_mod( 'wisdom-allow-tracking', 0 );
			} else {
				if ( isset( $allow_tracking[ $plugin ] ) ) {
					unset( $allow_tracking[ $plugin ] );
				}
			}
		}

		update_option( 'wisdom_allow_tracking', $allow_tracking );
	}

	/**
	 * Has the user opted out of allowing tracking?
	 * Note that themes are opt in / plugins are opt out
	 *
	 * @since 1.1.0
	 * @return Boolean
	 */
	public function has_user_opted_out() {
		// Different opt-out methods for plugins and themes
		if ( $this->what_am_i == 'theme' ) {
			// Look for the theme mod
			$mod = get_theme_mod( 'wisdom-allow-tracking', 0 );
			if ( false === $mod ) {
				// If the theme mod is not set, then return true - the user has opted out
				return true;
			}
		} else {
			// Iterate through the options that are being tracked looking for wisdom_opt_out setting
			if ( ! empty( $this->options ) ) {
				foreach ( $this->options as $option_name ) {
					// Check each option
					$options = get_option( $option_name );
					// If we find the setting, return true
					if ( ! empty( $options['wisdom_opt_out'] ) ) {
						return true;
					}
				}
			}
		}

		return false;
	}

	/**
	 * Check if it's time to track
	 *
	 * @since 1.1.1
	 */
	public function get_is_time_to_track() {
		// Let's see if we're due to track this plugin yet
		$track_times = get_option( 'wisdom_last_track_time', [] );
		if ( ! isset( $track_times[ $this->plugin_name ] ) ) {
			// If we haven't set a time for this plugin yet, then we must track it
			return true;
		} else {
			// If the time is set, let's get our schedule and check if it's time to track
			$schedule = $this->get_schedule();
			if ( $schedule == 'daily' ) {
				$period = 'day';
			} elseif ( $schedule == 'weekly' ) {
				$period = 'week';
			} else {
				$period = 'month';
			}
			if ( $track_times[ $this->plugin_name ] < strtotime( '-1 ' . $period ) ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Record the time we send tracking data
	 *
	 * @since 1.1.1
	 */
	public function set_track_time() {
		// We've tracked, so record the time
		$track_times = get_option( 'wisdom_last_track_time', [] );
		// Set different times according to plugin, in case we are tracking multiple plugins
		$track_times[ $this->plugin_name ] = time();
		update_option( 'wisdom_last_track_time', $track_times );
	}

	/**
	 * Set the time when we can display the opt-in notification
	 * Will display now unless filtered
	 *
	 * @since 1.2.4
	 */
	public function set_notification_time() {
		$notification_times = get_option( 'wisdom_notification_times', [] );
		// Set different times according to plugin, in case we are tracking multiple plugins
		if ( ! isset( $notification_times[ $this->plugin_name ] ) ) {
			$delay_notification = apply_filters( 'wisdom_delay_notification_' . $this->plugin_name, 0 );
			// We can delay the notification time
			$notification_time                        = time() + absint( $delay_notification );
			$notification_times[ $this->plugin_name ] = $notification_time;
			update_option( 'wisdom_notification_times', $notification_times );
		}
	}

	/**
	 * Get whether it's time to display the notification
	 *
	 * @since 1.2.4
	 * @return Boolean
	 */
	public function get_is_notification_time() {
		$notification_times = get_option( 'wisdom_notification_times', [] );
		$time               = time();
		// Set different times according to plugin, in case we are tracking multiple plugins
		if ( isset( $notification_times[ $this->plugin_name ] ) ) {
			$notification_time = $notification_times[ $this->plugin_name ];
			if ( $time >= $notification_time ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Set if we should block the opt-in notice for this plugin
	 * Option is an array of all plugins that have received a response from the user
	 *
	 * @since 1.0.0
	 */
	public function update_block_notice( $plugin = null ) {
		if ( empty( $plugin ) ) {
			$plugin = $this->plugin_name;
		}
		$block_notice = get_option( 'wisdom_block_notice' );
		if ( empty( $block_notice ) || ! is_array( $block_notice ) ) {
			// If nothing exists in the option yet, start a new array with the plugin name
			$block_notice = [ $plugin => $plugin ];
		} else {
			// Else add the plugin name to the array
			$block_notice[ $plugin ] = $plugin;
		}
		update_option( 'wisdom_block_notice', $block_notice );
	}

	/**
	 * Can we collect the email address?
	 *
	 * @since 1.0.0
	 */
	public function get_can_collect_email() {
		// The wisdom_collect_email option is an array of plugins that are being tracked
		$collect_email = get_option( 'wisdom_collect_email' );
		// If this plugin is in the array, then we can collect the email address
		if ( isset( $collect_email[ $this->plugin_name ] ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Set if user has allowed us to collect their email address
	 * Option is an array of all plugins with email collection permitted
	 * More than one plugin may be using the tracker
	 *
	 * @since 1.0.0
	 *
	 * @param $can_collect    Boolean        true if collection is allowed, false if not
	 */
	public function set_can_collect_email( $can_collect, $plugin = null ) {
		if ( empty( $plugin ) ) {
			$plugin = $this->plugin_name;
		}
		// The wisdom_collect_email option is an array of plugins that are being tracked
		$collect_email = get_option( 'wisdom_collect_email' );
		// If the user has agreed to allow tracking or if opt-in is not required
		if ( $can_collect ) {
			if ( empty( $collect_email ) || ! is_array( $collect_email ) ) {
				// If nothing exists in the option yet, start a new array with the plugin name
				$collect_email = [ $plugin => $plugin ];
			} else {
				// Else add the plugin name to the array
				$collect_email[ $plugin ] = $plugin;
			}
		} else {
			if ( isset( $collect_email[ $plugin ] ) ) {
				unset( $collect_email[ $plugin ] );
			}
		}
		update_option( 'wisdom_collect_email', $collect_email );
	}

	/**
	 * Get the correct email address to use
	 *
	 * @since 1.1.2
	 * @return Email address
	 */
	public function get_admin_email() {
		// The wisdom_collect_email option is an array of plugins that are being tracked
		$email = get_option( 'wisdom_admin_emails' );
		// If this plugin is in the array, then we can collect the email address
		if ( isset( $email[ $this->plugin_name ] ) ) {
			return $email[ $this->plugin_name ];
		}

		return false;
	}

	/**
	 * Set the correct email address to use
	 * There might be more than one admin on the site
	 * So we only use the first admin's email address
	 *
	 * @since 1.1.2
	 *
	 * @param $plugin    Plugin name to set email address for
	 * @param $email     Email address to set
	 */
	public function set_admin_email( $email = null, $plugin = null ) {
		if ( empty( $plugin ) ) {
			$plugin = $this->plugin_name;
		}
		// If no email address passed, try to get the current user's email
		if ( empty( $email ) ) {
			// Have to check that current user object is available
			if ( function_exists( 'wp_get_current_user' ) ) {
				$current_user = wp_get_current_user();
				$email        = $current_user->user_email;
			}
		}
		// The wisdom_admin_emails option is an array of admin email addresses
		$admin_emails = get_option( 'wisdom_admin_emails' );
		if ( empty( $admin_emails ) || ! is_array( $admin_emails ) ) {
			// If nothing exists in the option yet, start a new array with the plugin name
			$admin_emails = [ $plugin => sanitize_email( $email ) ];
		} elseif ( empty( $admin_emails[ $plugin ] ) ) {
			// Else add the email address to the array, if not already set
			$admin_emails[ $plugin ] = sanitize_email( $email );
		}
		update_option( 'wisdom_admin_emails', $admin_emails );
	}

	/**
	 * Display the admin notice to users to allow them to opt in
	 *
	 * @since 1.0.0
	 */
	public function optin_notice() {
		// Check for plugin args
		if ( isset( $_GET['plugin'] ) && isset( $_GET['plugin_action'] ) ) {
			$plugin = sanitize_text_field( $_GET['plugin'] );
			$action = sanitize_text_field( $_GET['plugin_action'] );
			if ( $action == 'yes' ) {
				$this->set_is_tracking_allowed( true, $plugin );
				// Run this straightaway
				add_action( 'admin_init', [ $this, 'force_tracking' ] );
			} else {
				$this->set_is_tracking_allowed( false, $plugin );
			}
			$this->update_block_notice( $plugin );
		}

		// Is it time to display the notification?
		$is_time = $this->get_is_notification_time();
		if ( ! $is_time ) {
			return false;
		}
		
		// Don't display on the PMPro Advanced Settings page.
		if ( ! empty( $_REQUEST['page'] ) && $_REQUEST['page'] === 'pmpro-advancedsettings' ) {
		   return false;
	   	}

		// Check whether to block the notice, e.g. because we're in a local environment
		// wisdom_block_notice works the same as wisdom_allow_tracking, an array of plugin names
		$block_notice = get_option( 'wisdom_block_notice' );

		if ( isset( $block_notice[ $this->plugin_name ] ) ) {
			return;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		// Don't bother asking user to opt in if they're in local dev
		$is_local = apply_filters( 'wisdom_is_local_' . $this->plugin_name, false );

		if ( $is_local ) {
			$this->update_block_notice();

			// PMPRO MODIFICATION.
			if ( $this->marketing ) {
				$this->set_can_collect_email( false );
			}
		} elseif ( get_option( 'pmpro_wisdom_opt_out' ) !== false ) {			
			// Option already set in PMPro Wizard or Advanced Settings page.
			$this->update_block_notice();
		} else {
			// Display the notice requesting permission to track
			// Retrieve current plugin information
			$plugin      = $this->plugin_data();
			$plugin_name = $plugin['Name'];

			// Args to add to query if user opts in to tracking
			$yes_args = [
				'plugin'        => $this->plugin_name,
				'plugin_action' => 'yes',
			];

			// Decide how to request permission to collect email addresses
			if ( $this->marketing == 1 ) {
				// Option 1 combines permissions to track and collect email
				$yes_args['marketing_optin'] = 'yes';
			} elseif ( $this->marketing == 2 ) {
				// Option 2 enables a second notice that fires after the user opts in to tracking
				$yes_args['marketing'] = 'yes';
			}
			$url_yes = add_query_arg( $yes_args );
			$url_no  = add_query_arg( [
				'plugin'        => $this->plugin_name,
				'plugin_action' => 'no',
			] );

			// Decide on notice text
			if ( $this->marketing != 1 ) {
				// Standard notice text
				$notice_text = sprintf( esc_html__( "Thank you for installing our %1\$s. We would like to track its usage on your site. We don't record any sensitive data, only information regarding the WordPress environment and %1\$s settings, which we will use to help us make improvements to the %1\$s. Tracking is completely optional.", 'paid-memberships-pro' ), $this->what_am_i );
			} else {
				// If we have option 1 for marketing, we include reference to sending product information here
				$notice_text = sprintf( esc_html__( "Thank you for installing our %1\$s. We'd like your permission to track its usage on your site and subscribe you to our newsletter. We won\'t record any sensitive data, only information regarding the WordPress environment and %1\$s settings, which we will use to help us make improvements to the %1\$s. Tracking is completely optional.", 'paid-memberships-pro' ), $this->what_am_i );
			}
			// And we allow you to filter the text anyway
			$notice_text = apply_filters( 'wisdom_notice_text_' . esc_attr( $this->plugin_name ), $notice_text ); ?>

			<div class="notice notice-info updated put-dismiss-notice">
				<h3><?php echo 'Enable Data Tracking For ' . esc_html( $plugin_name ) . '</strong>'; ?></h3>
				<p><?php echo wp_kses_post( $notice_text ); ?></p>
				<p>
					<a href="<?php echo esc_url( $url_yes ); ?>" class="button button-primary"><?php esc_html_e( 'Allow', 'paid-memberships-pro' ); ?></a>
					<a href="<?php echo esc_url( $url_no ); ?>" class="button button-secondary"><?php esc_html_e( 'Do Not Allow', 'paid-memberships-pro' ); ?></a>
				</p>
			</div>
			<?php
		}
	}

	/**
	 * Display the marketing notice to users if enabled
	 * Only displays after the user has opted in to tracking
	 *
	 * @since 1.0.0
	 */
	public function marketing_notice() {
		// Check if user has opted in to marketing
		if ( isset( $_GET['marketing_optin'] ) ) {
			// Set marketing optin
			$this->set_can_collect_email( sanitize_text_field( $_GET['marketing_optin'] ), $this->plugin_name );
			// Do tracking
			$this->do_tracking( true );
		} elseif ( isset( $_GET['marketing'] ) && $_GET['marketing'] == 'yes' ) {
			// Display the notice requesting permission to collect email address
			// Retrieve current plugin information
			$plugin      = $this->plugin_data();
			$plugin_name = $plugin['Name'];

			$url_yes = add_query_arg( [
				'plugin'          => $this->plugin_name,
				'marketing_optin' => 'yes',
			] );
			$url_no  = add_query_arg( [
				'plugin'          => $this->plugin_name,
				'marketing_optin' => 'no',
			] );

			$marketing_text = sprintf( esc_html__( 'Thank you for opting in to tracking. Would you like to receive occasional news about this %s, including details of new features and special offers?', 'paid-memberships-pro' ), $this->what_am_i );
			$marketing_text = apply_filters( 'wisdom_marketing_text_' . esc_attr( $this->plugin_name ), $marketing_text ); ?>

			<div class="notice notice-info updated put-dismiss-notice">
				<p><?php echo '<strong>' . esc_html( $plugin_name ) . '</strong>'; ?></p>
				<p><?php echo esc_html( $marketing_text ); ?></p>
				<p>
					<a href="<?php echo esc_url( $url_yes ); ?>" data-putnotice="yes" class="button-secondary"><?php esc_html_e( 'Yes Please', 'paid-memberships-pro' ); ?></a>
					<a href="<?php echo esc_url( $url_no ); ?>" data-putnotice="no" class="button-secondary"><?php esc_html_e( 'No Thank You', 'paid-memberships-pro' ); ?></a>
				</p>
			</div>
		<?php }
	}

	/**
	 * Filter the deactivation link to allow us to present a form when the user deactivates the plugin
	 *
	 * @since 1.0.0
	 */
	public function filter_action_links( $links ) {
		// Check to see if the user has opted in to tracking
		if ( ! $this->get_is_tracking_allowed() ) {
			return $links;
		}
		if ( isset( $links['deactivate'] ) && $this->include_goodbye_form ) {
			$deactivation_link = $links['deactivate'];
			// Insert an onClick action to allow form before deactivating
			$deactivation_link   = str_replace( '<a ', '<div class="put-goodbye-form-wrapper"><span class="put-goodbye-form" id="put-goodbye-form-' . esc_attr( $this->plugin_name ) . '"></span></div><a onclick="javascript:event.preventDefault();" id="put-goodbye-link-' . esc_attr( $this->plugin_name ) . '" ', $deactivation_link );
			$links['deactivate'] = $deactivation_link;
		}

		return $links;
	}

	/*
	 * Form text strings
	 * These are non-filterable and used as fallback in case filtered strings aren't set correctly
	 * @since 1.0.0
	 */
	public function form_default_text() {
		$form            = [];
		$form['heading'] = esc_html__( 'Sorry to see you go', 'paid-memberships-pro' );
		$form['body']    = esc_html__( 'Before you deactivate the plugin, would you quickly give us your reason for doing so?', 'paid-memberships-pro' );
		$form['options'] = [
			esc_html__( 'Set up is too difficult', 'paid-memberships-pro' ),
			esc_html__( 'Lack of documentation', 'paid-memberships-pro' ),
			esc_html__( 'Not the features I wanted', 'paid-memberships-pro' ),
			esc_html__( 'Found a better plugin', 'paid-memberships-pro' ),
			esc_html__( 'Installed by mistake', 'paid-memberships-pro' ),
			esc_html__( 'Only required temporarily', 'paid-memberships-pro' ),
			esc_html__( "Didn't work", 'paid-memberships-pro' ),
		];
		$form['details'] = esc_html__( 'Details (optional)', 'paid-memberships-pro' );

		return $form;
	}

	/**
	 * Form text strings
	 * These can be filtered
	 * The filter hook must be unique to the plugin
	 *
	 * @since 1.0.0
	 */
	public function form_filterable_text() {
		$form = $this->form_default_text();

		return apply_filters( 'wisdom_form_text_' . esc_attr( $this->plugin_name ), $form );
	}

	/**
	 * Form text strings
	 * These can be filtered
	 *
	 * @since 1.0.0
	 */
	public function goodbye_ajax() {
		// Get our strings for the form
		$form = $this->form_filterable_text();
		if ( ! isset( $form['heading'] ) || ! isset( $form['body'] ) || ! isset( $form['options'] ) || ! is_array( $form['options'] ) || ! isset( $form['details'] ) ) {
			// If the form hasn't been filtered correctly, we revert to the default form
			$form = $this->form_default_text();
		}
		// Build the HTML to go in the form
		$html_escaped = '<div class="put-goodbye-form-head"><strong>' . esc_html( $form['heading'] ) . '</strong></div>';
		$html_escaped .= '<div class="put-goodbye-form-body"><p>' . esc_html( $form['body'] ) . '</p>';
		if ( is_array( $form['options'] ) ) {
			$html_escaped .= '<div class="put-goodbye-options"><p>';
			foreach ( $form['options'] as $option ) {
				$html_escaped .= '<input type="checkbox" name="put-goodbye-options[]" id="' . str_replace( " ", "", esc_attr( $option ) ) . '" value="' . esc_attr( $option ) . '"> <label for="' . str_replace( " ", "", esc_attr( $option ) ) . '">' . esc_attr( $option ) . '</label><br>';
			}
			$html_escaped .= '</p><label for="put-goodbye-reasons">' . esc_html( $form['details'] ) . '</label><textarea name="put-goodbye-reasons" id="put-goodbye-reasons" rows="2" style="width:100%"></textarea>';
			$html_escaped .= '</div><!-- .put-goodbye-options -->';
		}
		$html_escaped .= '</div><!-- .put-goodbye-form-body -->';
		$html_escaped .= '<p class="deactivating-spinner"><span class="spinner"></span> ' . esc_html__( 'Submitting form', 'paid-memberships-pro' ) . '</p>';
		?>
		<div class="put-goodbye-form-bg"></div>
		<style type="text/css">
			.put-form-active .put-goodbye-form-bg {
				background: rgba(0, 0, 0, .5);
				position:   fixed;
				top:        0;
				left:       0;
				width:      100%;
				height:     100%;
			}

			.put-goodbye-form-wrapper {
				position: relative;
				z-index:  999;
				display:  none;
			}

			.put-form-active .put-goodbye-form-wrapper {
				display: block;
			}

			.put-goodbye-form {
				display: none;
			}

			.put-form-active .put-goodbye-form {
				position:    absolute;
				bottom:      30px;
				left:        0;
				max-width:   400px;
				background:  #fff;
				white-space: normal;
			}

			.put-goodbye-form-head {
				background: #0073aa;
				color:      #fff;
				padding:    8px 18px;
			}

			.put-goodbye-form-body {
				padding: 8px 18px;
				color:   #444;
			}

			.deactivating-spinner {
				display: none;
			}

			.deactivating-spinner .spinner {
				float:          none;
				margin:         4px 4px 0 18px;
				vertical-align: bottom;
				visibility:     visible;
			}

			.put-goodbye-form-footer {
				padding: 8px 18px;
			}
		</style>
		<script>
			jQuery( document ).ready( function ( $ ) {
				$( "#put-goodbye-link-<?php echo esc_attr( $this->plugin_name ); ?>" ).on( "click", function () {
					// We'll send the user to this deactivation link when they've completed or dismissed the form
					var url = document.getElementById( "put-goodbye-link-<?php echo esc_attr( $this->plugin_name ); ?>" );
					$( 'body' ).toggleClass( 'put-form-active' );
					$( "#put-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?>" ).fadeIn();
					$( "#put-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?>" ).html( '<?php echo wp_kses_post( $html_escaped ); ?>' + '<div class="put-goodbye-form-footer"><p><a id="put-submit-form" class="button primary" href="#"><?php esc_html_e( 'Submit and Deactivate', 'paid-memberships-pro' ); ?></a>&nbsp;<a class="secondary button" href="' + url + '"><?php esc_html_e( 'Just Deactivate', 'paid-memberships-pro' ); ?></a></p></div>' );
					$( '#put-submit-form' ).on( 'click', function ( e ) {
						// As soon as we click, the body of the form should disappear
						$( "#put-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .put-goodbye-form-body" ).fadeOut();
						$( "#put-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .put-goodbye-form-footer" ).fadeOut();
						// Fade in spinner
						$( "#put-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?> .deactivating-spinner" ).fadeIn();
						e.preventDefault();
						var values = new Array();
						$.each( $( "input[name='put-goodbye-options[]']:checked" ), function () {
							values.push( $( this ).val() );
						} );
						var details = $( '#put-goodbye-reasons' ).val();
						var data = {
							'action'   : 'goodbye_form',
							'values'   : values,
							'details'  : details,
							'security' : "<?php echo esc_attr( wp_create_nonce( 'wisdom_goodbye_form' ) ); ?>",
							'dataType' : "json"
						}
						$.post( ajaxurl, data, function ( response ) {
							// Redirect to original deactivation URL
							window.location.href = url;
						} );
					} );
					// If we click outside the form, the form will close
					$( '.put-goodbye-form-bg' ).on( 'click', function () {
						$( "#put-goodbye-form-<?php echo esc_attr( $this->plugin_name ); ?>" ).fadeOut();
						$( 'body' ).removeClass( 'put-form-active' );
					} );
				} );
			} );
		</script>
	<?php }

	/**
	 * AJAX callback when the form is submitted
	 *
	 * @since 1.0.0
	 */
	public function goodbye_form_callback() {
		check_ajax_referer( 'wisdom_goodbye_form', 'security' );
		if ( isset( $_POST['values'] ) ) {
			$values = json_encode( wp_unslash( sanitize_text_field( $_POST['values'] ) ) );
			update_option( 'wisdom_deactivation_reason_' . $this->plugin_name, $values );
		}
		if ( isset( $_POST['details'] ) ) {
			$details = sanitize_text_field( $_POST['details'] );
			update_option( 'wisdom_deactivation_details_' . $this->plugin_name, $details );
		}
		$this->do_tracking(); // Run this straightaway
		echo 'success';
		wp_die();
	}

}
