Completed
Push — move/tracking-from-xmlrpc-serv... ( 3bdc70 )
by
unknown
134:36 queued 127:37
created

Tracking::wp_ajax_jetpack_tracks()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 12
nop 0
dl 0
loc 23
rs 8.4444
c 0
b 0
f 0
1
<?php
2
namespace Automattic\Jetpack\Plugin;
3
4
use Automattic\Jetpack\Tracking as Tracks;
5
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
6
7
class Tracking {
8
	/**
9
	 * Tracking object.
10
	 *
11
	 * @var Tracks
12
	 *
13
	 * @access private
14
	 */
15
	private $tracking;
16
	/**
17
	 * Prevents the Tracking from being intialized more then once.
18
	 *
19
	 * @var bool
20
	 */
21
	private $initalized = false;
22
23
	public function init() {
24
		if ( $this->initalized ) {
25
			return;
26
		}
27
		$this->initalized = true;
28
		$this->tracking   = new Tracks( 'jetpack' );
29
30
		// For tracking stuff via js/ajax.
31
		add_action( 'admin_enqueue_scripts', array( $this->tracking, 'enqueue_tracks_scripts' ) );
32
33
		add_action( 'jetpack_activate_module', array( $this, 'jetpack_activate_module' ), 1, 1 );
34
		add_action( 'jetpack_deactivate_module', array( $this, 'jetpack_deactivate_module' ), 1, 1 );
35
		add_action( 'jetpack_user_authorized', array( $this, 'jetpack_user_authorized' ) );
36
		add_action( 'wp_login_failed', array( $this, 'wp_login_failed' ) );
37
38
		// Tracking XMLRPC server events.
39
		add_action( 'jetpack_xmlrpc_server_event', array( $this, 'jetpack_xmlrpc_server_event' ), 10, 4 );
40
41
		// Track that we've begun verifying the previously generated secret.
42
		add_action( 'jetpack_verify_secrets_begin', array( $this, 'jetpack_verify_secrets_begin' ), 10, 2 );
43
		add_action( 'jetpack_verify_secrets_success', array( $this, 'jetpack_verify_secrets_success' ), 10, 2 );
44
		add_action( 'jetpack_verify_secrets_fail', array( $this, 'jetpack_verify_secrets_fail' ), 10, 3 );
45
46
		// Universal ajax callback for all tracking events triggered via js.
47
		add_action( 'wp_ajax_jetpack_tracks', array( $this, 'wp_ajax_jetpack_tracks' ) );
48
49
		add_action( 'jetpack_verify_api_authorization_request_error_double_encode', array( $this, 'jetpack_verify_api_authorization_request_error_double_encode' ) );
50
		add_action( 'jetpack_connection_register_fail', array( $this, 'jetpack_connection_register_fail' ), 10, 2 );
51
		add_action( 'jetpack_connection_register_success', array( $this, 'jetpack_connection_register_success' ) );
52
	}
53
54
	/**
55
	 * Track that a specific module has been activated.
56
	 *
57
	 * @access public
58
	 *
59
	 * @param string $module Module slug.
60
	 */
61
	public function jetpack_activate_module( $module ) {
62
		$this->tracking->record_user_event( 'module_activated', array( 'module' => $module ) );
63
	}
64
65
	/**
66
	 * Track that a specific module has been deactivated.
67
	 *
68
	 * @access public
69
	 *
70
	 * @param string $module Module slug.
71
	 */
72
	public function jetpack_deactivate_module( $module ) {
73
		$this->tracking->record_user_event( 'module_deactivated', array( 'module' => $module ) );
74
	}
75
76
	/**
77
	 * Track that the user has successfully received an auth token.
78
	 *
79
	 * @access public
80
	 */
81
	public function jetpack_user_authorized() {
82
		$user_id = get_current_user_id();
83
		$anon_id = get_user_meta( $user_id, 'jetpack_tracks_anon_id', true );
84
85
		if ( $anon_id ) {
86
			$this->tracking->record_user_event( '_aliasUser', array( 'anonId' => $anon_id ) );
87
			delete_user_meta( $user_id, 'jetpack_tracks_anon_id' );
88
			if ( ! headers_sent() ) {
89
				setcookie( 'tk_ai', 'expired', time() - 1000 );
90
			}
91
		}
92
93
		$connection_manager = new Connection_Manager();
94
		$wpcom_user_data = $connection_manager->get_connected_user_data( $user_id );
95
		update_user_meta( $user_id, 'jetpack_tracks_wpcom_id', $wpcom_user_data['ID'] );
96
97
		$this->tracking->record_user_event( 'wpa_user_linked', array() );
98
	}
99
100
	/**
101
	 * Track that we've begun verifying the secrets.
102
	 *
103
	 * @access public
104
	 *
105
	 * @param string $action Type of secret (one of 'register', 'authorize', 'publicize').
106
	 * @param \WP_User $user The user object.
107
	 */
108
	public function jetpack_verify_secrets_begin( $action, $user ) {
109
		$this->tracking->record_user_event( "jpc_verify_{$action}_begin", array(), $user );
110
	}
111
112
	/**
113
	 * Track that we've succeeded in verifying the secrets.
114
	 *
115
	 * @access public
116
	 *
117
	 * @param string $action Type of secret (one of 'register', 'authorize', 'publicize').
118
	 * @param \WP_User $user The user object.
119
	 */
120
	public function jetpack_verify_secrets_success( $action, $user ) {
121
		$this->tracking->record_user_event( "jpc_verify_{$action}_success", array(), $user );
122
	}
123
124
	/**
125
	 * Track that we've failed verifying the secrets.
126
	 *
127
	 * @access public
128
	 *
129
	 * @param string $action Type of secret (one of 'register', 'authorize', 'publicize').
130
	 * @param \WP_User $user The user object.
131
	 * @param \WP_Error $error Error object.
132
	 */
133
	public function jetpack_verify_secrets_fail( $action, $user, $error ) {
134
		$this->tracking->record_user_event(
135
			"jpc_verify_{$action}_fail",
136
			array(
137
				'error_code'    => $error->get_error_code(),
0 ignored issues
show
Bug introduced by
The method get_error_code() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
138
				'error_message' => $error->get_error_message(),
0 ignored issues
show
Bug introduced by
The method get_error_message() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
139
			),
140
			$user
141
		);
142
	}
143
144
	/**
145
	 * Track a failed login attempt.
146
	 *
147
	 * @access public
148
	 *
149
	 * @param string $login Username or email address.
150
	 */
151
	public function wp_login_failed( $login ) {
152
		require_once JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php';
153
		$this->tracking->record_user_event(
154
			'failed_login',
155
			array(
156
				'origin_ip' => jetpack_protect_get_ip(),
157
				'login'     => $login,
158
			)
159
		);
160
	}
161
162
	/**
163
	 * Track a connection failure at the registration step.
164
	 *
165
	 * @access public
166
	 *
167
	 * @param string|int $error      The error code.
168
	 * @param \WP_Error  $registered The error object.
169
	 */
170
	function jetpack_connection_register_fail( $error, $registered ) {
171
		$this->tracking->record_user_event( 'jpc_register_fail', array(
172
			'error_code'    => $error,
173
			'error_message' => $registered->get_error_message()
0 ignored issues
show
Bug introduced by
The method get_error_message() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
174
		) );
175
	}
176
177
	/**
178
	 * Track that the registration step of the connection has been successful.
179
	 *
180
	 * @access public
181
	 *
182
	 * @param string $from The 'from' GET parameter.
183
	 */
184
	function jetpack_connection_register_success( $from ) {
185
		$this->tracking->record_user_event( 'jpc_register_success', array(
186
			'from' => $from
187
		) );
188
	}
189
190
	/**
191
	 * Handles the jetpack_xmlrpc_server_event action that combines several types of events that
192
	 * happen during request serving.
193
	 *
194
	 * @param String                   $action the action name, i.e., 'remote_authorize'.
195
	 * @param String                   $stage  the execution stage, can be 'begin', 'success', 'error', etc.
196
	 * @param Array|WP_Error|IXR_Error $parameters (optional) extra parameters to be passed to the tracked action.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $parameters not be array|WP_Error|IXR_Error|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
197
	 * @param WP_User                  $user (optional) the acting user.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $user not be WP_User|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
198
	 */
199
	public function jetpack_xmlrpc_server_event( $action, $stage, $parameters = null, $user = null ) {
200
201
		if ( is_wp_error( $parameters ) ) {
202
			$this->tracking->record_user_event(
203
				'jpc_' . $action . '_' . $stage,
204
				array(
205
					'error_code'    => $parameters->get_error_code(),
206
					'error_message' => $parameters->get_error_message(),
207
				),
208
				$user
209
			);
210
		} elseif ( is_a( $parameters, '\\IXR_Error' ) ) {
211
			$this->tracking->record_user_event(
212
				'jpc_' . $action . '_' . $stage,
213
				array(
214
					'error_code'    => $parameters->code,
215
					'error_message' => $parameters->message,
216
				),
217
				$user
218
			);
219
		} elseif ( null === $user && null === $parameters ) {
220
			$this->tracking->record_user_event( 'jpc_' . $action . '_' . $stage );
221
		} elseif ( null === $user ) {
222
			$this->tracking->record_user_event( 'jpc_' . $action . '_' . $stage, $parameters );
0 ignored issues
show
Bug introduced by
It seems like $parameters defined by parameter $parameters on line 199 can also be of type null; however, Automattic\Jetpack\Tracking::record_user_event() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
223
		} else {
224
			$this->tracking->record_user_event( 'jpc_' . $action . '_' . $stage, $parameters, $user );
0 ignored issues
show
Bug introduced by
It seems like $parameters defined by parameter $parameters on line 199 can also be of type null; however, Automattic\Jetpack\Tracking::record_user_event() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
225
		}
226
	}
227
228
	/**
229
	 * Track that the site is incorrectly double-encoding redirects from http to https.
230
	 *
231
	 * @access public
232
	 */
233
	function jetpack_verify_api_authorization_request_error_double_encode() {
234
		$this->tracking->record_user_event( 'error_double_encode' );
235
	}
236
237
	/**
238
	 * Universal method for for all tracking events triggered via the JavaScript client.
239
	 *
240
	 * @access public
241
	 */
242
	function wp_ajax_jetpack_tracks() {
243
		// Check for nonce
244
		if ( ! isset( $_REQUEST['tracksNonce'] ) || ! wp_verify_nonce( $_REQUEST['tracksNonce'], 'jp-tracks-ajax-nonce' ) ) {
245
			wp_die( 'Permissions check failed.' );
246
		}
247
248
		if ( ! isset( $_REQUEST['tracksEventName'] ) || ! isset( $_REQUEST['tracksEventType'] ) ) {
249
			wp_die( 'No valid event name or type.' );
250
		}
251
252
		$tracks_data = array();
253
		if ( 'click' === $_REQUEST['tracksEventType'] && isset( $_REQUEST['tracksEventProp'] ) ) {
254
			if ( is_array( $_REQUEST['tracksEventProp'] ) ) {
255
				$tracks_data = $_REQUEST['tracksEventProp'];
256
			} else {
257
				$tracks_data = array( 'clicked' => $_REQUEST['tracksEventProp'] );
258
			}
259
		}
260
261
		$this->tracking->record_user_event( $_REQUEST['tracksEventName'], $tracks_data );
262
		wp_send_json_success();
263
		wp_die();
264
	}
265
}
266