client = $client;
}
}
/**
* Don't show the notice
*
* @return self
*/
public function hide_notice() {
$this->show_notice = false;
return $this;
}
/**
* Add plugin data if needed
*
* @return self
*/
public function add_plugin_data() {
$this->plugin_data = true;
return $this;
}
/**
* Add extra data if needed
*
* @param array $data Extra data.
*
* @return self
*/
public function add_extra( $data = array() ) {
$this->extra_data = $data;
return $this;
}
/**
* Set custom notice text
*
* @param string $text Custom notice text.
*
* @return self
*/
public function notice( $text = '' ) {
$this->notice = $text;
return $this;
}
/**
* Initialize insights
*
* @return void
*/
public function init() {
if ( 'plugin' === $this->client->type ) {
$this->init_plugin();
} elseif ( 'theme' === $this->client->type ) {
$this->init_theme();
}
}
/**
* Initialize theme hooks
*
* @return void
*/
public function init_theme() {
$this->init_common();
add_action( 'switch_theme', array( $this, 'deactivation_cleanup' ) );
add_action( 'switch_theme', array( $this, 'theme_deactivated' ), 12, 3 );
}
/**
* Initialize plugin hooks
*
* @return void
*/
public function init_plugin() {
add_filter( 'plugin_action_links_' . $this->client->basename, array( $this, 'plugin_action_links' ) );
add_action( 'admin_footer', array( $this, 'deactivate_scripts' ) );
$this->init_common();
register_activation_hook( $this->client->file, array( $this, 'activate_plugin' ) );
register_deactivation_hook( $this->client->file, array( $this, 'deactivation_cleanup' ) );
}
/**
* Initialize common hooks
*
* @return void
*/
protected function init_common() {
if ( $this->show_notice ) {
add_action( 'admin_notices', array( $this, 'admin_notice' ) );
}
add_action( 'admin_init', array( $this, 'handle_optin_optout' ) );
add_action( 'wp_ajax_' . $this->client->slug . '_submit-uninstall-reason', array( $this, 'uninstall_reason_submission' ) );
add_filter( 'cron_schedules', array( $this, 'add_weekly_schedule' ) );
add_action( $this->client->slug . '_tracker_send_event', array( $this, 'send_tracking_data' ) );
}
/**
* Send tracking data to AppSero server
*
* @param bool $override Whether to override the tracking allowed check.
*
* @return void
*/
public function send_tracking_data( $override = false ) {
if ( ! $this->tracking_allowed() && ! $override ) {
return;
}
// Send a maximum of once per week.
$last_send = $this->get_last_send();
if ( $last_send && $last_send > strtotime( '-1 week' ) ) {
return;
}
$tracking_data = $this->get_tracking_data();
$response = $this->client->send_request( $tracking_data, 'track' );
update_option( $this->client->slug . '_tracking_last_send', time() );
}
/**
* Get the tracking data points
*
* @return array
*/
protected function get_tracking_data() {
$all_plugins = $this->get_all_plugins();
$users = get_users(
array(
'role' => 'administrator',
'orderby' => 'ID',
'order' => 'ASC',
'number' => 1,
'paged' => 1,
)
);
$admin_user = ( is_array( $users ) && ! empty( $users ) ) ? $users[0] : false;
$first_name = '';
$last_name = '';
if ( $admin_user ) {
$first_name = $admin_user->first_name ? $admin_user->first_name : $admin_user->display_name;
$last_name = $admin_user->last_name;
}
$data = array(
'url' => esc_url( home_url() ),
'site' => $this->get_site_name(),
'admin_email' => get_option( 'admin_email' ),
'first_name' => $first_name,
'last_name' => $last_name,
'hash' => $this->client->hash,
'server' => $this->get_server_info(),
'wp' => $this->get_wp_info(),
'users' => $this->get_user_counts(),
'active_plugins' => count( $all_plugins['active_plugins'] ),
'inactive_plugins' => count( $all_plugins['inactive_plugins'] ),
'ip_address' => $this->get_user_ip_address(),
'project_version' => $this->client->project_version,
'tracking_skipped' => false,
'is_local' => $this->is_local_server(),
);
// Add Plugins.
if ( $this->plugin_data ) {
$plugins_data = array();
foreach ( $all_plugins['active_plugins'] as $slug => $plugin ) {
$slug = strstr( $slug, '/', true );
if ( ! $slug ) {
continue;
}
$plugins_data[ $slug ] = array(
'name' => isset( $plugin['name'] ) ? $plugin['name'] : '',
'version' => isset( $plugin['version'] ) ? $plugin['version'] : '',
);
}
if ( array_key_exists( $this->client->slug, $plugins_data ) ) {
unset( $plugins_data[ $this->client->slug ] );
}
$data['plugins'] = $plugins_data;
}
// Add Metadata.
$extra = $this->get_extra_data();
if ( $extra ) {
$data['extra'] = $extra;
}
// Check if tracking was previously skipped.
$skipped = get_option( $this->client->slug . '_tracking_skipped' );
if ( 'yes' === $skipped ) {
delete_option( $this->client->slug . '_tracking_skipped' );
$data['tracking_skipped'] = true;
}
return apply_filters( $this->client->slug . '_tracker_data', $data );
}
/**
* If a child class wants to send extra data
*
* @return mixed
*/
protected function get_extra_data() {
if ( is_callable( $this->extra_data ) ) {
return call_user_func( $this->extra_data );
}
if ( is_array( $this->extra_data ) ) {
return $this->extra_data;
}
return array();
}
/**
* Explain the user which data we collect
*
* @return array
*/
protected function data_we_collect() {
$data = array(
'Server environment details (php, mysql, server, WordPress versions)',
'Number of users in your site',
'Site language',
'Number of active and inactive plugins',
'Site name and URL',
'Your name and email address',
);
if ( $this->plugin_data ) {
array_splice( $data, 4, 0, array( "active plugins' name" ) );
}
return $data;
}
/**
* Check if the user has opted into tracking
*
* @return bool
*/
public function tracking_allowed() {
$allow_tracking = get_option( $this->client->slug . '_allow_tracking', 'no' );
return 'yes' === $allow_tracking;
}
/**
* Get the last time a tracking was sent
*
* @return false|string
*/
private function get_last_send() {
return get_option( $this->client->slug . '_tracking_last_send', false );
}
/**
* Check if the notice has been dismissed or enabled
*
* @return bool
*/
public function notice_dismissed() {
$hide_notice = get_option( $this->client->slug . '_tracking_notice', null );
if ( 'hide' === $hide_notice ) {
return true;
}
return false;
}
/**
* Check if the current server is localhost
*
* @return bool
*/
private function is_local_server() {
$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : 'localhost';
$ip = isset( $_SERVER['SERVER_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_ADDR'] ) ) : '127.0.0.1';
$is_local = false;
if (
in_array( $ip, array( '127.0.0.1', '::1' ), true ) ||
! strpos( $host, '.' ) ||
in_array( strrchr( $host, '.' ), array( '.test', '.testing', '.local', '.localhost', '.localdomain' ), true )
) {
$is_local = true;
}
return apply_filters( 'appsero_is_local', $is_local );
}
/**
* Schedule the event weekly
*
* @return void
*/
private function schedule_event() {
$hook_name = wp_unslash( $this->client->slug . '_tracker_send_event' );
if ( ! wp_next_scheduled( $hook_name ) ) {
wp_schedule_event( time(), 'weekly', $hook_name );
}
}
/**
* Clear any scheduled hook
*
* @return void
*/
private function clear_schedule_event() {
wp_clear_scheduled_hook( $this->client->slug . '_tracker_send_event' );
}
/**
* Display the admin notice to users that have not opted-in or out
*
* @return void
*/
public function admin_notice() {
if ( $this->notice_dismissed() ) {
return;
}
if ( $this->tracking_allowed() ) {
return;
}
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$optin_url = wp_nonce_url( add_query_arg( $this->client->slug . '_tracker_optin', 'true' ), '_wpnonce' );
$optout_url = wp_nonce_url( add_query_arg( $this->client->slug . '_tracker_optout', 'true' ), '_wpnonce' );
if ( empty( $this->notice ) ) {
$notice = sprintf(
$this->client->__trans( 'Want to help make %1$s even more awesome? Allow %1$s to collect diagnostic data and usage information.' ),
$this->client->name
);
} else {
$notice = $this->notice;
}
$policy_url = 'https://appsero.com/privacy-policy/';
$notice .= ' (' . $this->client->__trans( 'what we collect' ) . ')';
$notice .= '
' . implode( ', ', $this->data_we_collect() ) . '. ';
$notice .= 'We are using Appsero to collect your data. Learn more about how Appsero collects and handle your data.
client->__trans( 'We share your data with Appsero to troubleshoot problems & make product improvements. Learn more about how Appsero handles your data.' ),
esc_url( 'https://appsero.com/' ),
esc_url( 'https://appsero.com/privacy-policy' )
);
?>
get_template() === $this->client->slug ) {
$this->client->send_request( $this->get_tracking_data(), 'deactivate' );
}
}
/**
* Get user IP Address
*/
private function get_user_ip_address() {
$response = wp_remote_get( 'https://icanhazip.com/' );
if ( is_wp_error( $response ) ) {
return '';
}
$ip = trim( wp_remote_retrieve_body( $response ) );
if ( ! filter_var( $ip, FILTER_VALIDATE_IP ) ) {
return '';
}
return $ip;
}
/**
* Get site name
*/
private function get_site_name() {
$site_name = get_bloginfo( 'name' );
if ( empty( $site_name ) ) {
$site_name = get_bloginfo( 'description' );
$site_name = wp_trim_words( $site_name, 3, '' );
}
if ( empty( $site_name ) ) {
$site_name = esc_url( home_url() );
}
return $site_name;
}
/**
* Send request to appsero if user skip to send tracking data
*/
private function send_tracking_skipped_request() {
$skipped = get_option( $this->client->slug . '_tracking_skipped' );
$data = [
'hash' => $this->client->hash,
'previously_skipped' => false,
];
if ( $skipped === 'yes' ) {
$data['previously_skipped'] = true;
} else {
update_option( $this->client->slug . '_tracking_skipped', 'yes' );
}
$this->client->send_request( $data, 'tracking-skipped' );
}
/**
* Deactivation modal styles
*/
private function deactivation_modal_styles() {
?>