Completed
Push — fix/normalize-www-in-site-url-... ( e67e76 )
by
unknown
13:13 queued 02:59
created

_inc/lib/tracks/class.tracks-client.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Jetpack_Tracks_Client
5
 * @autounit nosara tracks-client
6
 *
7
 * Send Tracks events on behalf of a user
8
 *
9
 * Example Usage:
10
```php
11
	require( dirname(__FILE__).'path/to/tracks/class.tracks-client' );
12
13
	$result = Jetpack_Tracks_Client::record_event( array(
14
		'_en'        => $event_name,       // required
15
		'_ui'        => $user_id,          // required unless _ul is provided
16
		'_ul'        => $user_login,       // required unless _ui is provided
17
18
		// Optional, but recommended
19
		'_ts'        => $ts_in_ms,         // Default: now
20
		'_via_ip'    => $client_ip,        // we use it for geo, etc.
21
22
		// Possibly useful to set some context for the event
23
		'_via_ua'    => $client_user_agent,
24
		'_via_url'   => $client_url,
25
		'_via_ref'   => $client_referrer,
26
27
		// For user-targeted tests
28
		'abtest_name'        => $abtest_name,
29
		'abtest_variation'   => $abtest_variation,
30
31
		// Your application-specific properties
32
		'custom_property'    => $some_value,
33
	) );
34
35
	if ( is_wp_error( $result ) ) {
36
		// Handle the error in your app
37
	}
38
```
39
 */
40
41
require_once( dirname(__FILE__).'/class.tracks-client.php' );
42
43
class Jetpack_Tracks_Client {
44
	const PIXEL = 'http://pixel.wp.com/t.gif';
45
	const BROWSER_TYPE = 'php-agent';
46
	const USER_AGENT_SLUG = 'tracks-client';
47
	const VERSION = '0.3';
48
49
	/**
50
	 * record_event
51
	 * @param  mixed  $event Event object to send to Tracks. An array will be cast to object. Required.
52
	 *                       Properties are included directly in the pixel query string after light validation.
53
	 * @return mixed         True on success, WP_Error on failure
54
	 */
55
	static function record_event( $event ) {
56
		if ( ! $event instanceof Jetpack_Tracks_Event ) {
57
			$event = new Jetpack_Tracks_Event( $event );
0 ignored issues
show
Consider using a different name than the parameter $event. This often makes code more readable.
Loading history...
58
		}
59
		if ( is_wp_error( $event ) ) {
60
			return $event;
61
		}
62
63
		$pixel = $event->build_pixel_url( $event );
64
65
		if ( ! $pixel ) {
66
			return new WP_Error( 'invalid_pixel', 'cannot generate tracks pixel for given input', 400 );
67
		}
68
69
		return self::record_pixel( $pixel );
70
	}
71
72
	/**
73
	 * Synchronously request the pixel
74
	 */
75
	static function record_pixel( $pixel ) {
76
		// Add the Request Timestamp and URL terminator just before the HTTP request.
77
		$pixel .= '&_rt=' . self::build_timestamp() . '&_=_';
78
79
		$response = wp_remote_get( $pixel, array(
80
			'blocking'    => true, // The default, but being explicit here :)
81
			'timeout'     => 1,
82
			'redirection' => 2,
83
			'httpversion' => '1.1',
84
			'user-agent'  => self::get_user_agent(),
85
		) );
86
87
		if ( is_wp_error( $response ) ) {
88
			return $response;
89
		}
90
91
		$code = isset( $response['response']['code'] ) ? $response['response']['code'] : 0;
92
93
		if ( $code !== 200 ) {
94
			return new WP_Error( 'request_failed', 'Tracks pixel request failed', $code );
95
		}
96
97
		return true;
98
	}
99
100
	static function get_user_agent() {
101
		return Jetpack_Tracks_Client::USER_AGENT_SLUG . '-v' . Jetpack_Tracks_Client::VERSION;
102
	}
103
104
	/**
105
	 * Build an event and return its tracking URL
106
	 * @deprecated          Call the `build_pixel_url` method on a Jetpack_Tracks_Event object instead.
107
	 * @param  array $event Event keys and values
108
	 * @return string       URL of a tracking pixel
109
	 */
110
	static function build_pixel_url( $event ) {
111
		$_event = new Jetpack_Tracks_Event( $event );
112
		return $_event->build_pixel_url();
113
	}
114
115
	/**
116
	 * Validate input for a tracks event.
117
	 * @deprecated          Instantiate a Jetpack_Tracks_Event object instead
118
	 * @param  array $event Event keys and values
119
	 * @return mixed        Validated keys and values or WP_Error on failure
120
	 */
121
	private static function validate_and_sanitize( $event ) {
122
		$_event = new Jetpack_Tracks_Event( $event );
123
		if ( is_wp_error( $_event ) ) {
124
			return $_event;
125
		}
126
		return get_object_vars( $_event );
127
	}
128
129
	// Milliseconds since 1970-01-01
130
	static function build_timestamp() {
131
		$ts = round( microtime( true ) * 1000 );
132
		return number_format( $ts, 0, '', '' );
133
	}
134
135
	/**
136
	 * Grabs the user's anon id from cookies, or generates and sets a new one
137
	 *
138
	 * @return string An anon id for the user
139
	 */
140
	static function get_anon_id() {
141
		static $anon_id = null;
142
143
		if ( ! isset( $anon_id ) ) {
144
145
			// Did the browser send us a cookie?
146
			if ( isset( $_COOKIE[ 'tk_ai' ] ) && preg_match( '#^[A-Za-z0-9+/=]{24}$#', $_COOKIE[ 'tk_ai' ] ) ) {
147
				$anon_id = $_COOKIE[ 'tk_ai' ];
148
			} else {
149
150
				$binary = '';
151
152
				// Generate a new anonId and try to save it in the browser's cookies
153
				// Note that base64-encoding an 18 character string generates a 24-character anon id
154
				for ( $i = 0; $i < 18; ++$i ) {
155
					$binary .= chr( mt_rand( 0, 255 ) );
156
				}
157
158
				$anon_id = 'jetpack:' . base64_encode( $binary );
159
160
				if ( ! headers_sent() ) {
161
					setcookie( 'tk_ai', $anon_id );
162
				}
163
			}
164
		}
165
166
		return $anon_id;
167
	}
168
}
169