Completed
Push — branch-5.8-built ( 327068...93ad53 )
by
unknown
83:37 queued 74:56
created

Jetpack_Tracks_Client::record_event()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 7
nop 1
dl 0
loc 20
rs 8.8571
c 0
b 0
f 0
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 = 'https://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 ( ! Jetpack::is_active() ) {
57
			return false;
58
		}
59
		
60
		if ( ! $event instanceof Jetpack_Tracks_Event ) {
61
			$event = new Jetpack_Tracks_Event( $event );
62
		}
63
		if ( is_wp_error( $event ) ) {
64
			return $event;
65
		}
66
67
		$pixel = $event->build_pixel_url( $event );
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Tracks_Event::build_pixel_url() has too many arguments starting with $event.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
68
69
		if ( ! $pixel ) {
70
			return new WP_Error( 'invalid_pixel', 'cannot generate tracks pixel for given input', 400 );
71
		}
72
73
		return self::record_pixel( $pixel );
74
	}
75
76
	/**
77
	 * Synchronously request the pixel
78
	 */
79
	static function record_pixel( $pixel ) {
80
		// Add the Request Timestamp and URL terminator just before the HTTP request.
81
		$pixel .= '&_rt=' . self::build_timestamp() . '&_=_';
82
83
		$response = wp_remote_get( $pixel, array(
84
			'blocking'    => true, // The default, but being explicit here :)
85
			'timeout'     => 1,
86
			'redirection' => 2,
87
			'httpversion' => '1.1',
88
			'user-agent'  => self::get_user_agent(),
89
		) );
90
91
		if ( is_wp_error( $response ) ) {
92
			return $response;
93
		}
94
95
		$code = isset( $response['response']['code'] ) ? $response['response']['code'] : 0;
96
97
		if ( $code !== 200 ) {
98
			return new WP_Error( 'request_failed', 'Tracks pixel request failed', $code );
99
		}
100
101
		return true;
102
	}
103
104
	static function get_user_agent() {
105
		return Jetpack_Tracks_Client::USER_AGENT_SLUG . '-v' . Jetpack_Tracks_Client::VERSION;
106
	}
107
108
	/**
109
	 * Build an event and return its tracking URL
110
	 * @deprecated          Call the `build_pixel_url` method on a Jetpack_Tracks_Event object instead.
111
	 * @param  array $event Event keys and values
112
	 * @return string       URL of a tracking pixel
113
	 */
114
	static function build_pixel_url( $event ) {
115
		$_event = new Jetpack_Tracks_Event( $event );
116
		return $_event->build_pixel_url();
117
	}
118
119
	/**
120
	 * Validate input for a tracks event.
121
	 * @deprecated          Instantiate a Jetpack_Tracks_Event object instead
122
	 * @param  array $event Event keys and values
123
	 * @return mixed        Validated keys and values or WP_Error on failure
124
	 */
125
	private static function validate_and_sanitize( $event ) {
126
		$_event = new Jetpack_Tracks_Event( $event );
127
		if ( is_wp_error( $_event ) ) {
128
			return $_event;
129
		}
130
		return get_object_vars( $_event );
131
	}
132
133
	// Milliseconds since 1970-01-01
134
	static function build_timestamp() {
135
		$ts = round( microtime( true ) * 1000 );
136
		return number_format( $ts, 0, '', '' );
137
	}
138
139
	/**
140
	 * Grabs the user's anon id from cookies, or generates and sets a new one
141
	 *
142
	 * @return string An anon id for the user
143
	 */
144
	static function get_anon_id() {
145
		static $anon_id = null;
146
147
		if ( ! isset( $anon_id ) ) {
148
149
			// Did the browser send us a cookie?
150
			if ( isset( $_COOKIE[ 'tk_ai' ] ) && preg_match( '#^[A-Za-z0-9+/=]{24}$#', $_COOKIE[ 'tk_ai' ] ) ) {
151
				$anon_id = $_COOKIE[ 'tk_ai' ];
152
			} else {
153
154
				$binary = '';
155
156
				// Generate a new anonId and try to save it in the browser's cookies
157
				// Note that base64-encoding an 18 character string generates a 24-character anon id
158
				for ( $i = 0; $i < 18; ++$i ) {
159
					$binary .= chr( mt_rand( 0, 255 ) );
160
				}
161
162
				$anon_id = 'jetpack:' . base64_encode( $binary );
163
164
				if ( ! headers_sent()
165
					&& ! ( defined( 'REST_REQUEST' ) && REST_REQUEST )
166
					&& ! ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST )
167
				) {
168
					setcookie( 'tk_ai', $anon_id );
169
				}
170
			}
171
		}
172
173
		return $anon_id;
174
	}
175
176
	/**
177
	 * Gets the WordPress.com user's Tracks identity, if connected.
178
	 *
179
	 * @return array|bool
180
	 */
181
	static function get_connected_user_tracks_identity() {
182
		if ( ! $user_data = Jetpack::get_connected_user_data() ) {
183
			return false;
184
		}
185
186
		return array(
187
			'userid' => $user_data['ID'],
188
			'username' => $user_data['login'],
189
		);
190
	}
191
}
192