1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* WooCommerce Tracker |
4
|
|
|
* |
5
|
|
|
* The WooCommerce tracker class adds functionality to track WooCommerce usage based on if the customer opted in. |
6
|
|
|
* No personal infomation is tracked, only general WooCommerce settings, general product, order and user counts and admin email for discount code. |
7
|
|
|
* |
8
|
|
|
* @class WC_Tracker |
9
|
|
|
* @version 2.3.0 |
10
|
|
|
* @package WooCommerce/Classes |
11
|
|
|
* @category Class |
12
|
|
|
* @author WooThemes |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
16
|
|
|
exit; |
17
|
|
|
} |
18
|
|
|
|
19
|
|
|
class WC_Tracker { |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* URL to the WooThemes Tracker API endpoint. |
23
|
|
|
* @var string |
24
|
|
|
*/ |
25
|
|
|
private static $api_url = 'https://tracking.woocommerce.com/v1/'; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Hook into cron event. |
29
|
|
|
*/ |
30
|
|
|
public static function init() { |
31
|
|
|
add_action( 'woocommerce_tracker_send_event', array( __CLASS__, 'send_tracking_data' ) ); |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Decide whether to send tracking data or not. |
36
|
|
|
* |
37
|
|
|
* @param boolean $override |
38
|
|
|
*/ |
39
|
|
|
public static function send_tracking_data( $override = false ) { |
40
|
|
|
// Dont trigger this on AJAX Requests |
41
|
|
|
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { |
42
|
|
|
return; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
if ( ! apply_filters( 'woocommerce_tracker_send_override', $override ) ) { |
46
|
|
|
// Send a maximum of once per week by default. |
47
|
|
|
$last_send = self::get_last_send_time(); |
48
|
|
|
if ( $last_send && $last_send > apply_filters( 'woocommerce_tracker_last_send_interval', strtotime( '-1 week' ) ) ) { |
49
|
|
|
return; |
50
|
|
|
} |
51
|
|
|
} else { |
52
|
|
|
// Make sure there is at least a 1 hour delay between override sends, we dont want duplicate calls due to double clicking links. |
53
|
|
|
$last_send = self::get_last_send_time(); |
54
|
|
|
if ( $last_send && $last_send > strtotime( '-1 hours' ) ) { |
55
|
|
|
return; |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
// Update time first before sending to ensure it is set |
60
|
|
|
update_option( 'woocommerce_tracker_last_send', time() ); |
61
|
|
|
|
62
|
|
|
$params = self::get_tracking_data(); |
63
|
|
|
wp_safe_remote_post( self::$api_url, array( |
64
|
|
|
'method' => 'POST', |
65
|
|
|
'timeout' => 45, |
66
|
|
|
'redirection' => 5, |
67
|
|
|
'httpversion' => '1.0', |
68
|
|
|
'blocking' => false, |
69
|
|
|
'headers' => array( 'user-agent' => 'WooCommerceTracker/' . md5( esc_url( home_url( '/' ) ) ) . ';' ), |
70
|
|
|
'body' => json_encode( $params ), |
71
|
|
|
'cookies' => array(), |
72
|
|
|
) |
73
|
|
|
); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Get the last time tracking data was sent. |
78
|
|
|
* @return int|bool |
79
|
|
|
*/ |
80
|
|
|
private static function get_last_send_time() { |
81
|
|
|
return apply_filters( 'woocommerce_tracker_last_send_time', get_option( 'woocommerce_tracker_last_send', false ) ); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Get all the tracking data. |
86
|
|
|
* @return array |
87
|
|
|
*/ |
88
|
|
|
private static function get_tracking_data() { |
89
|
|
|
$data = array(); |
90
|
|
|
|
91
|
|
|
// General site info |
92
|
|
|
$data['url'] = home_url(); |
93
|
|
|
$data['email'] = apply_filters( 'woocommerce_tracker_admin_email', get_option( 'admin_email' ) ); |
94
|
|
|
$data['theme'] = self::get_theme_info(); |
95
|
|
|
|
96
|
|
|
// WordPress Info |
97
|
|
|
$data['wp'] = self::get_wordpress_info(); |
98
|
|
|
|
99
|
|
|
// Server Info |
100
|
|
|
$data['server'] = self::get_server_info(); |
101
|
|
|
|
102
|
|
|
// Plugin info |
103
|
|
|
$all_plugins = self::get_all_plugins(); |
104
|
|
|
$data['active_plugins'] = $all_plugins['active_plugins']; |
105
|
|
|
$data['inactive_plugins'] = $all_plugins['inactive_plugins']; |
106
|
|
|
|
107
|
|
|
// Jetpack & WooCommerce Connect |
108
|
|
|
$data['jetpack_version'] = defined( 'JETPACK__VERSION' ) ? JETPACK__VERSION : 'none'; |
109
|
|
|
$data['jetpack_connected'] = ( class_exists( 'Jetpack' ) && is_callable( 'Jetpack::is_active' ) && Jetpack::is_active() ) ? 'yes' : 'no'; |
110
|
|
|
$data['jetpack_is_staging'] = ( class_exists( 'Jetpack' ) && is_callable( 'Jetpack::is_staging_site' ) && Jetpack::is_staging_site() ) ? 'yes' : 'no'; |
111
|
|
|
$data['connect_installed'] = class_exists( 'WC_Connect_Loader' ) ? 'yes' : 'no'; |
112
|
|
|
$data['connect_active'] = ( class_exists( 'WC_Connect_Loader' ) && wp_next_scheduled( 'wc_connect_fetch_service_schemas' ) ) ? 'yes' : 'no'; |
113
|
|
|
|
114
|
|
|
// Store count info |
115
|
|
|
$data['users'] = self::get_user_counts(); |
116
|
|
|
$data['products'] = self::get_product_counts(); |
117
|
|
|
$data['orders'] = self::get_order_counts(); |
118
|
|
|
|
119
|
|
|
// Payment gateway info |
120
|
|
|
$data['gateways'] = self::get_active_payment_gateways(); |
121
|
|
|
|
122
|
|
|
// Shipping method info |
123
|
|
|
$data['shipping_methods'] = self::get_active_shipping_methods(); |
124
|
|
|
|
125
|
|
|
// Get all WooCommerce options info |
126
|
|
|
$data['settings'] = self::get_all_woocommerce_options_values(); |
127
|
|
|
|
128
|
|
|
// Template overrides |
129
|
|
|
$data['template_overrides'] = self::get_all_template_overrides(); |
130
|
|
|
|
131
|
|
|
// Template overrides |
132
|
|
|
$data['admin_user_agents'] = self::get_admin_user_agents(); |
133
|
|
|
|
134
|
|
|
return apply_filters( 'woocommerce_tracker_data', $data ); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Get the current theme info, theme name and version. |
139
|
|
|
* @return array |
140
|
|
|
*/ |
141
|
|
|
public static function get_theme_info() { |
142
|
|
|
$wp_version = get_bloginfo( 'version' ); |
143
|
|
|
|
144
|
|
|
if ( version_compare( $wp_version, '3.4', '<' ) ) { |
145
|
|
|
$theme_data = get_theme_data( get_stylesheet_directory() . '/style.css' ); |
146
|
|
|
$theme_name = $theme_data['Name']; |
147
|
|
|
$theme_version = $theme_data['Version']; |
148
|
|
|
} else { |
149
|
|
|
$theme_data = wp_get_theme(); |
150
|
|
|
$theme_name = $theme_data->Name; |
151
|
|
|
$theme_version = $theme_data->Version; |
152
|
|
|
} |
153
|
|
|
$theme_child_theme = is_child_theme() ? 'Yes' : 'No'; |
154
|
|
|
$theme_wc_support = ( ! current_theme_supports( 'woocommerce' ) && ! in_array( $theme_data->template, wc_get_core_supported_themes() ) ) ? 'No' : 'Yes'; |
155
|
|
|
|
156
|
|
|
return array( 'name' => $theme_name, 'version' => $theme_version, 'child_theme' => $theme_child_theme, 'wc_support' => $theme_wc_support ); |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
/** |
160
|
|
|
* Get WordPress related data. |
161
|
|
|
* @return array |
162
|
|
|
*/ |
163
|
|
|
private static function get_wordpress_info() { |
164
|
|
|
$wp_data = array(); |
165
|
|
|
|
166
|
|
|
$memory = wc_let_to_num( WP_MEMORY_LIMIT ); |
167
|
|
|
|
168
|
|
|
if ( function_exists( 'memory_get_usage' ) ) { |
169
|
|
|
$system_memory = wc_let_to_num( @ini_get( 'memory_limit' ) ); |
170
|
|
|
$memory = max( $memory, $system_memory ); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
$wp_data['memory_limit'] = size_format( $memory ); |
174
|
|
|
$wp_data['debug_mode'] = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? 'Yes' : 'No'; |
175
|
|
|
$wp_data['locale'] = get_locale(); |
176
|
|
|
$wp_data['version'] = get_bloginfo( 'version' ); |
177
|
|
|
$wp_data['multisite'] = is_multisite() ? 'Yes' : 'No'; |
178
|
|
|
|
179
|
|
|
return $wp_data; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* Get server related info. |
184
|
|
|
* @return array |
185
|
|
|
*/ |
186
|
|
|
private static function get_server_info() { |
187
|
|
|
$server_data = array(); |
188
|
|
|
|
189
|
|
|
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) { |
190
|
|
|
$server_data['software'] = $_SERVER['SERVER_SOFTWARE']; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
if ( function_exists( 'phpversion' ) ) { |
194
|
|
|
$server_data['php_version'] = phpversion(); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
if ( function_exists( 'ini_get' ) ) { |
198
|
|
|
$server_data['php_post_max_size'] = size_format( wc_let_to_num( ini_get( 'post_max_size' ) ) ); |
199
|
|
|
$server_data['php_time_limt'] = ini_get( 'max_execution_time' ); |
200
|
|
|
$server_data['php_max_input_vars'] = ini_get( 'max_input_vars' ); |
201
|
|
|
$server_data['php_suhosin'] = extension_loaded( 'suhosin' ) ? 'Yes' : 'No'; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
global $wpdb; |
205
|
|
|
$server_data['mysql_version'] = $wpdb->db_version(); |
206
|
|
|
|
207
|
|
|
$server_data['php_max_upload_size'] = size_format( wp_max_upload_size() ); |
208
|
|
|
$server_data['php_default_timezone'] = date_default_timezone_get(); |
209
|
|
|
$server_data['php_soap'] = class_exists( 'SoapClient' ) ? 'Yes' : 'No'; |
210
|
|
|
$server_data['php_fsockopen'] = function_exists( 'fsockopen' ) ? 'Yes' : 'No'; |
211
|
|
|
$server_data['php_curl'] = function_exists( 'curl_init' ) ? 'Yes' : 'No'; |
212
|
|
|
|
213
|
|
|
return $server_data; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
/** |
217
|
|
|
* Get all plugins grouped into activated or not. |
218
|
|
|
* @return array |
219
|
|
|
*/ |
220
|
|
|
private static function get_all_plugins() { |
221
|
|
|
// Ensure get_plugins function is loaded |
222
|
|
|
if ( ! function_exists( 'get_plugins' ) ) { |
223
|
|
|
include ABSPATH . '/wp-admin/includes/plugin.php'; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
$plugins = get_plugins(); |
227
|
|
|
$active_plugins_keys = get_option( 'active_plugins', array() ); |
228
|
|
|
$active_plugins = array(); |
229
|
|
|
|
230
|
|
|
foreach ( $plugins as $k => $v ) { |
231
|
|
|
// Take care of formatting the data how we want it. |
232
|
|
|
$formatted = array(); |
233
|
|
|
$formatted['name'] = strip_tags( $v['Name'] ); |
234
|
|
|
if ( isset( $v['Version'] ) ) { |
235
|
|
|
$formatted['version'] = strip_tags( $v['Version'] ); |
236
|
|
|
} |
237
|
|
|
if ( isset( $v['Author'] ) ) { |
238
|
|
|
$formatted['author'] = strip_tags( $v['Author'] ); |
239
|
|
|
} |
240
|
|
|
if ( isset( $v['Network'] ) ) { |
241
|
|
|
$formatted['network'] = strip_tags( $v['Network'] ); |
242
|
|
|
} |
243
|
|
|
if ( isset( $v['PluginURI'] ) ) { |
244
|
|
|
$formatted['plugin_uri'] = strip_tags( $v['PluginURI'] ); |
245
|
|
|
} |
246
|
|
|
if ( in_array( $k, $active_plugins_keys ) ) { |
247
|
|
|
// Remove active plugins from list so we can show active and inactive separately |
248
|
|
|
unset( $plugins[ $k ] ); |
249
|
|
|
$active_plugins[ $k ] = $formatted; |
250
|
|
|
} else { |
251
|
|
|
$plugins[ $k ] = $formatted; |
252
|
|
|
} |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
return array( 'active_plugins' => $active_plugins, 'inactive_plugins' => $plugins ); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Get user totals based on user role. |
260
|
|
|
* @return array |
261
|
|
|
*/ |
262
|
|
|
private static function get_user_counts() { |
263
|
|
|
$user_count = array(); |
264
|
|
|
$user_count_data = count_users(); |
265
|
|
|
$user_count['total'] = $user_count_data['total_users']; |
266
|
|
|
|
267
|
|
|
// Get user count based on user role |
268
|
|
|
foreach ( $user_count_data['avail_roles'] as $role => $count ) { |
269
|
|
|
$user_count[ $role ] = $count; |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
return $user_count; |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Get product totals based on product type. |
277
|
|
|
* @return array |
278
|
|
|
*/ |
279
|
|
|
private static function get_product_counts() { |
280
|
|
|
$product_count = array(); |
281
|
|
|
$product_count_data = wp_count_posts( 'product' ); |
282
|
|
|
$product_count['total'] = $product_count_data->publish; |
283
|
|
|
|
284
|
|
|
$product_statuses = get_terms( 'product_type', array( 'hide_empty' => 0 ) ); |
285
|
|
|
foreach ( $product_statuses as $product_status ) { |
286
|
|
|
$product_count[ $product_status->name ] = $product_status->count; |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
return $product_count; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* Get order counts based on order status. |
294
|
|
|
* @return array |
295
|
|
|
*/ |
296
|
|
|
private static function get_order_counts() { |
297
|
|
|
$order_count = array(); |
298
|
|
|
$order_count_data = wp_count_posts( 'shop_order' ); |
299
|
|
|
|
300
|
|
|
foreach ( wc_get_order_statuses() as $status_slug => $status_name ) { |
301
|
|
|
$order_count[ $status_slug ] = $order_count_data->{ $status_slug }; |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
return $order_count; |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* Get a list of all active payment gateways. |
309
|
|
|
* @return array |
310
|
|
|
*/ |
311
|
|
View Code Duplication |
private static function get_active_payment_gateways() { |
|
|
|
|
312
|
|
|
$active_gateways = array(); |
313
|
|
|
$gateways = WC()->payment_gateways->payment_gateways(); |
314
|
|
|
foreach ( $gateways as $id => $gateway ) { |
315
|
|
|
if ( isset( $gateway->enabled ) && 'yes' === $gateway->enabled ) { |
316
|
|
|
$active_gateways[ $id ] = array( 'title' => $gateway->title, 'supports' => $gateway->supports ); |
317
|
|
|
} |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
return $active_gateways; |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Get a list of all active shipping methods. |
325
|
|
|
* @return array |
326
|
|
|
*/ |
327
|
|
View Code Duplication |
private static function get_active_shipping_methods() { |
|
|
|
|
328
|
|
|
$active_methods = array(); |
329
|
|
|
$shipping_methods = WC()->shipping->get_shipping_methods(); |
330
|
|
|
foreach ( $shipping_methods as $id => $shipping_method ) { |
331
|
|
|
if ( isset( $shipping_method->enabled ) && 'yes' === $shipping_method->enabled ) { |
332
|
|
|
$active_methods[ $id ] = array( 'title' => $shipping_method->title, 'tax_status' => $shipping_method->tax_status ); |
333
|
|
|
} |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
return $active_methods; |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
/** |
340
|
|
|
* Get all options starting with woocommerce_ prefix. |
341
|
|
|
* @return array |
342
|
|
|
*/ |
343
|
|
|
private static function get_all_woocommerce_options_values() { |
344
|
|
|
return array( |
345
|
|
|
'version' => WC()->version, |
346
|
|
|
'currency' => get_woocommerce_currency(), |
347
|
|
|
'base_location' => WC()->countries->get_base_country(), |
348
|
|
|
'selling_locations' => WC()->countries->get_allowed_countries(), |
349
|
|
|
'api_enabled' => get_option( 'woocommerce_api_enabled' ), |
350
|
|
|
'weight_unit' => get_option( 'woocommerce_weight_unit' ), |
351
|
|
|
'dimension_unit' => get_option( 'woocommerce_dimension_unit' ), |
352
|
|
|
'download_method' => get_option( 'woocommerce_file_download_method' ), |
353
|
|
|
'download_require_login' => get_option( 'woocommerce_downloads_require_login' ), |
354
|
|
|
'calc_taxes' => get_option( 'woocommerce_calc_taxes' ), |
355
|
|
|
'coupons_enabled' => get_option( 'woocommerce_enable_coupons' ), |
356
|
|
|
'guest_checkout' => get_option( 'woocommerce_enable_guest_checkout' ), |
357
|
|
|
'secure_checkout' => get_option( 'woocommerce_force_ssl_checkout' ), |
358
|
|
|
'enable_signup_and_login_from_checkout' => get_option( 'woocommerce_enable_signup_and_login_from_checkout' ), |
359
|
|
|
'enable_myaccount_registration' => get_option( 'woocommerce_enable_myaccount_registration' ), |
360
|
|
|
'registration_generate_username' => get_option( 'woocommerce_registration_generate_username' ), |
361
|
|
|
'registration_generate_password' => get_option( 'woocommerce_registration_generate_password' ), |
362
|
|
|
); |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
/** |
366
|
|
|
* Look for any template override and return filenames. |
367
|
|
|
* @return array |
368
|
|
|
*/ |
369
|
|
|
private static function get_all_template_overrides() { |
370
|
|
|
$override_data = array(); |
371
|
|
|
$template_paths = apply_filters( 'woocommerce_template_overrides_scan_paths', array( 'WooCommerce' => WC()->plugin_path() . '/templates/' ) ); |
372
|
|
|
$scanned_files = array(); |
373
|
|
|
|
374
|
|
|
require_once( WC()->plugin_path() . '/includes/admin/class-wc-admin-status.php' ); |
375
|
|
|
|
376
|
|
|
foreach ( $template_paths as $plugin_name => $template_path ) { |
377
|
|
|
$scanned_files[ $plugin_name ] = WC_Admin_Status::scan_template_files( $template_path ); |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
foreach ( $scanned_files as $plugin_name => $files ) { |
381
|
|
|
foreach ( $files as $file ) { |
382
|
|
|
if ( file_exists( get_stylesheet_directory() . '/' . $file ) ) { |
383
|
|
|
$theme_file = get_stylesheet_directory() . '/' . $file; |
384
|
|
|
} elseif ( file_exists( get_stylesheet_directory() . '/woocommerce/' . $file ) ) { |
385
|
|
|
$theme_file = get_stylesheet_directory() . '/woocommerce/' . $file; |
386
|
|
|
} elseif ( file_exists( get_template_directory() . '/' . $file ) ) { |
387
|
|
|
$theme_file = get_template_directory() . '/' . $file; |
388
|
|
|
} elseif ( file_exists( get_template_directory() . '/woocommerce/' . $file ) ) { |
389
|
|
|
$theme_file = get_template_directory() . '/woocommerce/' . $file; |
390
|
|
|
} else { |
391
|
|
|
$theme_file = false; |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
if ( false !== $theme_file ) { |
395
|
|
|
$override_data[] = basename( $theme_file ); |
396
|
|
|
} |
397
|
|
|
} |
398
|
|
|
} |
399
|
|
|
return $override_data; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
/** |
403
|
|
|
* When an admin user logs in, there user agent is tracked in user meta and collected here. |
404
|
|
|
* @return array |
405
|
|
|
*/ |
406
|
|
|
private static function get_admin_user_agents() { |
407
|
|
|
return array_filter( (array) get_option( 'woocommerce_tracker_ua', array() ) ); |
408
|
|
|
} |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
WC_Tracker::init(); |
412
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.