/includes/admin/tracking.php

  1. <?php 
  2. /** 
  3. * Tracking functions for reporting plugin usage to the MonsterInsights site for users that have opted in 
  4. * 
  5. * @package MonsterInsights 
  6. * @subpackage Admin 
  7. * @copyright Copyright (c) 2016, Chris Christoff 
  8. * @since 6.0.0 
  9. */ 
  10.  
  11. // Exit if accessed directly 
  12. if ( ! defined( 'ABSPATH' ) ) { 
  13. exit; 
  14.  
  15. /** 
  16. * Usage tracking 
  17. * 
  18. * @access public 
  19. * @since 6.0.0 
  20. * @return void 
  21. */ 
  22. class MonsterInsights_Tracking { 
  23.  
  24. /** 
  25. * The data to send to the EDD site 
  26. * 
  27. * @access private 
  28. */ 
  29. private $data; 
  30.  
  31. /** 
  32. * Get things going 
  33. * 
  34. * @access public 
  35. */ 
  36. public function __construct() { 
  37.  
  38. add_action( 'init', array( $this, 'schedule_send' ) ); 
  39. add_action( 'monsterinsights_settings_save_general_end', array( $this, 'check_for_settings_optin' ) ); 
  40. add_action( 'admin_head', array( $this, 'check_for_optin' ) ); 
  41. add_action( 'admin_head', array( $this, 'check_for_optout' ) ); 
  42. add_action( 'admin_notices', array( $this, 'monsterinsights_admin_notice' ) ); 
  43. add_filter( 'cron_schedules', array( $this, 'add_schedules' ) ); 
  44. add_action( 'monsterinsights_daily_cron', array( $this, 'send_checkin' ) ); 
  45.  
  46. /** 
  47. * Check if the user has opted into tracking 
  48. * 
  49. * @access private 
  50. * @return bool 
  51. */ 
  52. private function tracking_allowed() { 
  53. return (bool) monsterinsights_get_option( 'anonymous_data', false ); 
  54.  
  55. /** 
  56. * Setup the data that is going to be tracked 
  57. * 
  58. * @access private 
  59. * @return void 
  60. */ 
  61. private function setup_data() { 
  62. $data = array(); 
  63.  
  64. // Retrieve current theme info 
  65. $theme_data = wp_get_theme(); 
  66. $theme = $theme_data->Name . ' ' . $theme_data->Version; 
  67. $tracking_mode = monsterinsights_get_option( 'tracking_mode', 'analytics' ); 
  68. $events_mode = monsterinsights_get_option( 'events_mode', 'none' ); 
  69.  
  70. if ( $tracking_mode === false ) { 
  71. $tracking_mode = 'analytics'; 
  72.  
  73. if ( $events_mode === false ) { 
  74. $events_mode = 'none'; 
  75.  
  76. $data['php_version'] = phpversion(); 
  77. $data['mi_version'] = MONSTERINSIGHTS_VERSION; 
  78. $data['wp_version'] = get_bloginfo( 'version' ); 
  79. $data['server'] = isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : ''; 
  80. $data['over_time'] = get_option( 'monsterinsights_over_time', array() ); 
  81. $data['multisite'] = is_multisite(); 
  82. $data['url'] = home_url(); 
  83. $data['theme'] = $theme; 
  84. $data['email'] = get_bloginfo( 'admin_email' ); 
  85. $data['key'] = monsterinsights_get_license(); 
  86. $data['sas'] = monsterinsights_get_shareasale_id(); 
  87. $data['setttings'] = monsterinsights_get_options(); 
  88. $data['tracking_mode'] = $tracking_mode; 
  89. $data['events_mode'] = $events_mode; 
  90.  
  91. // Retrieve current plugin information 
  92. if( ! function_exists( 'get_plugins' ) ) { 
  93. include ABSPATH . '/wp-admin/includes/plugin.php'; 
  94.  
  95. $plugins = array_keys( get_plugins() ); 
  96. $active_plugins = get_option( 'active_plugins', array() ); 
  97.  
  98. foreach ( $plugins as $key => $plugin ) { 
  99. if ( in_array( $plugin, $active_plugins ) ) { 
  100. // Remove active plugins from list so we can show active and inactive separately 
  101. unset( $plugins[ $key ] ); 
  102.  
  103. $data['active_plugins'] = $active_plugins; 
  104. $data['inactive_plugins'] = $plugins; 
  105. $data['locale'] = get_locale(); 
  106.  
  107. $this->data = $data; 
  108.  
  109. /** 
  110. * Send the data to the EDD server 
  111. * 
  112. * @access private 
  113. * @return void 
  114. */ 
  115. public function send_checkin( $override = false, $ignore_last_checkin = false ) { 
  116.  
  117. if( ! $this->tracking_allowed() && ! $override ) { 
  118. return false; 
  119.  
  120. // Send a maximum of once per day 
  121. $last_send = $this->get_last_send(); 
  122. if( is_numeric( $last_send ) && $last_send > strtotime( '-1 day' ) && ! $ignore_last_checkin ) { 
  123. return false; 
  124.  
  125. $this->setup_data(); 
  126.  
  127. $request = wp_remote_post( 'https://www.monsterinsights.com/?edd_action=checkin', array( 
  128. 'method' => 'POST',  
  129. 'timeout' => 20,  
  130. 'redirection' => 5,  
  131. 'httpversion' => '1.1',  
  132. 'blocking' => true,  
  133. 'body' => $this->data,  
  134. 'user-agent' => 'MI/' . MONSTERINSIGHTS_VERSION . '; ' . get_bloginfo( 'url' ) 
  135. ) ); 
  136.  
  137. if( is_wp_error( $request ) ) { 
  138. return $request; 
  139.  
  140. update_option( 'mi_tracking_last_send', time() ); 
  141.  
  142. return true; 
  143.  
  144.  
  145. /** 
  146. * Check for a new opt-in on settings save 
  147. * 
  148. * This runs during the sanitation of General settings, thus the return 
  149. * 
  150. * @access public 
  151. * @return array 
  152. */ 
  153. public function check_for_settings_optin() { 
  154. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  155. return; 
  156.  
  157. // Send an intial check in on settings save 
  158. $anonymous_data = isset( $_POST['anonymous_data'] ) ? 1 : 0; 
  159. if ( $anonymous_data ) { 
  160. $this->send_checkin( true ); 
  161.  
  162.  
  163. /** 
  164. * Check for a new opt-in via the admin notice 
  165. * 
  166. * @access public 
  167. * @return void 
  168. */ 
  169. public function check_for_optin() { 
  170. if ( ! ( ! empty( $_REQUEST['mi_action'] ) && 'opt_into_tracking' === $_REQUEST['mi_action'] ) ) { 
  171. return; 
  172.  
  173. if ( monsterinsights_get_option( 'anonymous_data', false ) ) { 
  174. return; 
  175.  
  176. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  177. return; 
  178.  
  179. monsterinsights_update_option( 'anonymous_data', 1 ); 
  180. $this->send_checkin( true ); 
  181. update_option( 'monsterinsights_tracking_notice', 1 ); 
  182.  
  183. /** 
  184. * Check for a new opt-in via the admin notice 
  185. * 
  186. * @access public 
  187. * @return void 
  188. */ 
  189. public function check_for_optout() { 
  190. if ( ! ( ! empty( $_REQUEST['mi_action'] ) && 'opt_out_of_tracking' === $_REQUEST['mi_action'] ) ) { 
  191. return; 
  192.  
  193. if ( monsterinsights_get_option( 'anonymous_data', false ) ) { 
  194. return; 
  195.  
  196. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  197. return; 
  198.  
  199. monsterinsights_update_option( 'anonymous_data', 0 ); 
  200. update_option( 'monsterinsights_tracking_notice', 1 ); 
  201.  
  202. /** 
  203. * Get the last time a checkin was sent 
  204. * 
  205. * @access private 
  206. * @return false|string 
  207. */ 
  208. private function get_last_send() { 
  209. return get_option( 'monsterinsights_tracking_last_send' ); 
  210.  
  211. /** 
  212. * Schedule a weekly checkin 
  213. * 
  214. * @access public 
  215. * @return void 
  216. */ 
  217. public function schedule_send() { 
  218. // We send once a day (while tracking is allowed) to check in, which can be used to determine active sites 
  219. if ( ! wp_next_scheduled( 'monsterinsights_daily_cron' ) ) { 
  220. // Set the next event of fetching data 
  221. wp_schedule_event( strtotime( date( 'Y-m-d', strtotime( 'tomorrow' ) ) . ' 00:01:00 ' ), 'daily', 'monsterinsights_daily_cron' ); 
  222.  
  223. /** 
  224. * Display the admin notice to users that have not opted-in or out 
  225. * 
  226. * @access public 
  227. * @return void 
  228. */ 
  229. public function monsterinsights_admin_notice() { 
  230.  
  231. $hide_notice = get_option( 'monsterinsights_tracking_notice' ); 
  232.  
  233. if ( $hide_notice ) { 
  234. return; 
  235.  
  236. if ( monsterinsights_get_option( 'anonymous_data', false ) ) { 
  237. return; 
  238.  
  239. if ( ! current_user_can( 'monsterinsights_save_settings' ) ) { 
  240. return; 
  241.  
  242. if ( 
  243. stristr( network_site_url( '/' ), 'dev' ) !== false || 
  244. stristr( network_site_url( '/' ), 'localhost' ) !== false || 
  245. stristr( network_site_url( '/' ), ':8888' ) !== false // This is common with MAMP on OS X 
  246. ) { 
  247. update_option( 'monsterinsights_tracking_notice', '1' ); 
  248. } else { 
  249. $optin_url = add_query_arg( 'mi_action', 'opt_into_tracking' ); 
  250. $optout_url = add_query_arg( 'mi_action', 'opt_out_of_tracking' ); 
  251. echo '<div class="updated"><p>'; 
  252. echo esc_html__( 'Allow MonsterInsights to track plugin usage? Opt-in to tracking and our newsletter to stay informed of the latest changes to MonsterInsights and help us ensure compatibility.', 'google-analytics-for-wordpress' ); 
  253. echo ' <a href="' . esc_url( $optin_url ) . '" class="button-secondary">' . __( 'Allow', 'google-analytics-for-wordpress' ) . '</a>'; 
  254. echo ' <a href="' . esc_url( $optout_url ) . '" class="button-secondary">' . __( 'Do not allow', 'google-analytics-for-wordpress' ) . '</a>'; 
  255. echo '</p></div>'; 
  256.  
  257. /** 
  258. * Registers new cron schedules 
  259. * 
  260. * @since 6.0.0 
  261. * 
  262. * @param array $schedules 
  263. * @return array 
  264. */ 
  265. public function add_schedules( $schedules = array() ) { 
  266. // Adds once weekly to the existing schedules. 
  267. $schedules['weekly'] = array( 
  268. 'interval' => 604800,  
  269. 'display' => __( 'Once Weekly', 'google-analytics-for-wordpress' ) 
  270. ); 
  271. return $schedules; 
  272.  
  273. new MonsterInsights_Tracking(); 
.