Completed
Push — update/package-tracks-move-mor... ( d28e64 )
by
unknown
183:34 queued 176:59
created

Tracking::tracks_record_event()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 3
nop 4
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
/**
3
 * Nosara Tracks for Jetpack
4
 */
5
6
namespace Automattic\Jetpack;
7
8
class Tracking {
9
	static $product_name = 'jetpack';
10
11
	static function track_jetpack_usage() {
12
		if ( ! \Jetpack::jetpack_tos_agreed() ) {
13
			return;
14
		}
15
16
		// For tracking stuff via js/ajax
17
		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_tracks_scripts' ) );
18
19
		add_action( 'jetpack_activate_module', array( __CLASS__, 'track_activate_module' ), 1, 1 );
20
		add_action( 'jetpack_deactivate_module', array( __CLASS__, 'track_deactivate_module' ), 1, 1 );
21
		add_action( 'jetpack_user_authorized', array( __CLASS__, 'track_user_linked' ) );
22
		add_action( 'wp_login_failed', array( __CLASS__, 'track_failed_login_attempts' ) );
23
	}
24
25 View Code Duplication
	static function enqueue_tracks_scripts() {
26
		wp_enqueue_script( 'jptracks', plugins_url( '_inc/lib/tracks/tracks-ajax.js', JETPACK__PLUGIN_FILE ), array(), JETPACK__VERSION, true );
27
		wp_localize_script(
28
			'jptracks',
29
			'jpTracksAJAX',
30
			array(
31
				'ajaxurl'            => admin_url( 'admin-ajax.php' ),
32
				'jpTracksAJAX_nonce' => wp_create_nonce( 'jp-tracks-ajax-nonce' ),
33
			)
34
		);
35
	}
36
37
	/* User has linked their account */
38
	static function track_user_linked() {
39
		$user_id = get_current_user_id();
40
		$anon_id = get_user_meta( $user_id, 'jetpack_tracks_anon_id', true );
41
42
		if ( $anon_id ) {
43
			self::record_user_event( '_aliasUser', array( 'anonId' => $anon_id ) );
44
			delete_user_meta( $user_id, 'jetpack_tracks_anon_id' );
45
			if ( ! headers_sent() ) {
46
				setcookie( 'tk_ai', 'expired', time() - 1000 );
47
			}
48
		}
49
50
		$wpcom_user_data = Jetpack::get_connected_user_data( $user_id );
51
		update_user_meta( $user_id, 'jetpack_tracks_wpcom_id', $wpcom_user_data['ID'] );
52
53
		self::record_user_event( 'wpa_user_linked', array() );
54
	}
55
56
	/* Activated module */
57
	static function track_activate_module( $module ) {
58
		self::record_user_event( 'module_activated', array( 'module' => $module ) );
59
	}
60
61
	/* Deactivated module */
62
	static function track_deactivate_module( $module ) {
63
		self::record_user_event( 'module_deactivated', array( 'module' => $module ) );
64
	}
65
66
	/* Failed login attempts */
67
	static function track_failed_login_attempts( $login ) {
68
		require_once JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php';
69
		self::record_user_event(
70
			'failed_login',
71
			array(
72
				'origin_ip' => jetpack_protect_get_ip(),
73
				'login'     => $login,
74
			)
75
		);
76
	}
77
78
	static function record_user_event( $event_type, $data = array(), $user = null ) {
79
		if ( ! $user ) {
80
			$user = wp_get_current_user();
81
		}
82
		$site_url = get_option( 'siteurl' );
83
84
		$data['_via_ua']  = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
85
		$data['_via_ip']  = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
86
		$data['_lg']      = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : '';
87
		$data['blog_url'] = $site_url;
88
		$data['blog_id']  = \Jetpack_Options::get_option( 'id' );
89
90
		// Top level events should not be namespaced
91
		if ( '_aliasUser' != $event_type ) {
92
			$event_type = self::$product_name . '_' . $event_type;
93
		}
94
95
		$data['jetpack_version'] = defined( 'JETPACK__VERSION' ) ? JETPACK__VERSION : '0';
96
97
		return self::jetpack_tracks_record_event( $user, $event_type, $data );
0 ignored issues
show
Bug introduced by
The method jetpack_tracks_record_event() does not exist on Automattic\Jetpack\Tracking. Did you maybe mean tracks_record_event()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
98
	}
99
100
	/**
101
	 * Procedurally build a Tracks Event Object.
102
	 * NOTE: Use this only when the simpler \Automattic\Jetpack\Tracking::jetpack_tracks_record_event() function won't work for you.
103
	 *
104
	 * @param $identity WP_user object
105
	 * @param string                  $event_name The name of the event
106
	 * @param array                   $properties Custom properties to send with the event
107
	 * @param int                     $event_timestamp_millis The time in millis since 1970-01-01 00:00:00 when the event occurred
0 ignored issues
show
Documentation introduced by
Should the type for parameter $event_timestamp_millis not be false|integer?

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...
108
	 * @return \Jetpack_Tracks_Event|\WP_Error
109
	 */
110
	function tracks_build_event_obj( $user, $event_name, $properties = array(), $event_timestamp_millis = false ) {
111
112
		$tracks   = new \Automattic\Jetpack\Tracking();
113
		$identity = $tracks->tracks_get_identity( $user->ID );
114
115
		$properties['user_lang'] = $user->get( 'WPLANG' );
116
117
		$blog_details = array(
118
			'blog_lang' => isset( $properties['blog_lang'] ) ? $properties['blog_lang'] : get_bloginfo( 'language' ),
119
		);
120
121
		$timestamp        = ( $event_timestamp_millis !== false ) ? $event_timestamp_millis : round( microtime( true ) * 1000 );
122
		$timestamp_string = is_string( $timestamp ) ? $timestamp : number_format( $timestamp, 0, '', '' );
123
124
		return new \Jetpack_Tracks_Event(
125
			array_merge(
126
				$blog_details,
127
				(array) $properties,
128
				$identity,
129
				array(
130
					'_en' => $event_name,
131
					'_ts' => $timestamp_string,
132
				)
133
			)
134
		);
135
	}
136
137
	/*
138
	 * Get the identity to send to tracks.
139
	 *
140
	 * @param int $user_id The user id of the local user
141
	 * @return array $identity
142
	 */
143
	function tracks_get_identity( $user_id ) {
144
145
		// Meta is set, and user is still connected.  Use WPCOM ID
146
		$wpcom_id = get_user_meta( $user_id, 'jetpack_tracks_wpcom_id', true );
147
		if ( $wpcom_id && \Jetpack::is_user_connected( $user_id ) ) {
0 ignored issues
show
Documentation introduced by
$user_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
148
			return array(
149
				'_ut' => 'wpcom:user_id',
150
				'_ui' => $wpcom_id,
151
			);
152
		}
153
154
		// User is connected, but no meta is set yet.  Use WPCOM ID and set meta.
155
		if ( \Jetpack::is_user_connected( $user_id ) ) {
0 ignored issues
show
Documentation introduced by
$user_id is of type integer, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
156
			$wpcom_user_data = Jetpack::get_connected_user_data( $user_id );
157
			update_user_meta( $user_id, 'jetpack_tracks_wpcom_id', $wpcom_user_data['ID'] );
158
159
			return array(
160
				'_ut' => 'wpcom:user_id',
161
				'_ui' => $wpcom_user_data['ID'],
162
			);
163
		}
164
165
		// User isn't linked at all.  Fall back to anonymous ID.
166
		$anon_id = get_user_meta( $user_id, 'jetpack_tracks_anon_id', true );
167
		if ( ! $anon_id ) {
168
			$anon_id = \Jetpack_Tracks_Client::get_anon_id();
169
			add_user_meta( $user_id, 'jetpack_tracks_anon_id', $anon_id, false );
170
		}
171
172
		if ( ! isset( $_COOKIE['tk_ai'] ) && ! headers_sent() ) {
173
			setcookie( 'tk_ai', $anon_id );
174
		}
175
176
		return array(
177
			'_ut' => 'anon',
178
			'_ui' => $anon_id,
179
		);
180
181
	}
182
183
	/**
184
	 * Record an event in Tracks - this is the preferred way to record events from PHP.
185
	 *
186
	 * @param mixed  $identity username, user_id, or WP_user object
0 ignored issues
show
Bug introduced by
There is no parameter named $identity. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
187
	 * @param string $event_name The name of the event
188
	 * @param array  $properties Custom properties to send with the event
189
	 * @param int    $event_timestamp_millis The time in millis since 1970-01-01 00:00:00 when the event occurred
0 ignored issues
show
Documentation introduced by
Should the type for parameter $event_timestamp_millis not be false|integer?

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...
190
	 * @return bool true for success | \WP_Error if the event pixel could not be fired
191
	 */
192
	function tracks_record_event( $user, $event_name, $properties = array(), $event_timestamp_millis = false ) {
193
194
		// We don't want to track user events during unit tests/CI runs.
195
		if ( $user instanceof WP_User && 'wptests_capabilities' === $user->cap_key ) {
0 ignored issues
show
Bug introduced by
The class Automattic\Jetpack\WP_User does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
196
			return false;
197
		}
198
199
		$event_obj = self::tracks_build_event_obj( $user, $event_name, $properties, $event_timestamp_millis );
200
201
		if ( is_wp_error( $event_obj->error ) ) {
202
			return $event_obj->error;
203
		}
204
205
		return $event_obj->record();
206
	}
207
}
208