Completed
Push — fix/resolve-security-vulnerabi... ( 372367...c122d8 )
by Yaroslav
197:31 queued 189:03
created

packages/tracking/src/class-tracking.php (2 issues)

Severity

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
 * Nosara Tracks for Jetpack
4
 *
5
 * @package automattic/jetpack-tracking
6
 */
7
8
namespace Automattic\Jetpack;
9
10
/**
11
 * The Tracking class, used to record events in wpcom
12
 */
13
class Tracking {
14
	/**
15
	 * Slug of the product that we are tracking.
16
	 *
17
	 * @var string
18
	 */
19
	private $product_name;
20
21
	/**
22
	 * Connection manager object.
23
	 *
24
	 * @var Object
25
	 */
26
	private $connection;
27
28
	/**
29
	 * Creates the Tracking object.
30
	 *
31
	 * @param String                                $product_name the slug of the product that we are tracking.
32
	 * @param Automattic\Jetpack\Connection\Manager $connection   the connection manager object.
33
	 */
34
	public function __construct( $product_name = 'jetpack', $connection = null ) {
35
		$this->product_name = $product_name;
36
		$this->connection   = $connection;
37
		if ( is_null( $this->connection ) ) {
38
			// TODO We should always pass a Connection.
39
			$this->connection = new Connection\Manager();
40
		}
41
	}
42
43
	/**
44
	 * Enqueue script necessary for tracking.
45
	 */
46 View Code Duplication
	public function enqueue_tracks_scripts() {
47
		wp_enqueue_script( 'jptracks', plugins_url( '_inc/lib/tracks/tracks-ajax.js', JETPACK__PLUGIN_FILE ), array(), JETPACK__VERSION, true );
48
		wp_localize_script(
49
			'jptracks',
50
			'jpTracksAJAX',
51
			array(
52
				'ajaxurl'            => admin_url( 'admin-ajax.php' ),
53
				'jpTracksAJAX_nonce' => wp_create_nonce( 'jp-tracks-ajax-nonce' ),
54
			)
55
		);
56
	}
57
58
	/**
59
	 * Send an event in Tracks.
60
	 *
61
	 * @param string $event_type Type of the event.
62
	 * @param array  $data       Data to send with the event.
63
	 * @param mixed  $user       username, user_id, or WP_user object.
64
	 */
65
	public function record_user_event( $event_type, $data = array(), $user = null ) {
66
		if ( ! $user ) {
67
			$user = wp_get_current_user();
68
		}
69
		$site_url = get_option( 'siteurl' );
70
71
		$data['_via_ua']  = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
72
		$data['_via_ip']  = isset( $_SERVER['REMOTE_ADDR'] ) ? $_SERVER['REMOTE_ADDR'] : '';
73
		$data['_lg']      = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : '';
74
		$data['blog_url'] = $site_url;
75
		$data['blog_id']  = \Jetpack_Options::get_option( 'id' );
76
77
		// Top level events should not be namespaced.
78
		if ( '_aliasUser' !== $event_type ) {
79
			$event_type = $this->product_name . '_' . $event_type;
80
		}
81
82
		$data['jetpack_version'] = defined( 'JETPACK__VERSION' ) ? JETPACK__VERSION : '0';
83
84
		return $this->tracks_record_event( $user, $event_type, $data );
85
	}
86
87
	/**
88
	 * Record an event in Tracks - this is the preferred way to record events from PHP.
89
	 *
90
	 * @param mixed  $user                   username, user_id, or WP_user object.
91
	 * @param string $event_name             The name of the event.
92
	 * @param array  $properties             Custom properties to send with the event.
93
	 * @param int    $event_timestamp_millis The time in millis since 1970-01-01 00:00:00 when the event occurred.
94
	 *
95
	 * @return bool true for success | \WP_Error if the event pixel could not be fired
96
	 */
97
	public function tracks_record_event( $user, $event_name, $properties = array(), $event_timestamp_millis = false ) {
98
99
		// We don't want to track user events during unit tests/CI runs.
100
		if ( $user instanceof \WP_User && 'wptests_capabilities' === $user->cap_key ) {
101
			return false;
102
		}
103
		$terms_of_service = new Terms_Of_Service();
104
		$status           = new Status();
105
		// Don't track users who have not agreed to our TOS.
106
		if ( ! $this->should_enable_tracking( $terms_of_service, $status ) ) {
0 ignored issues
show
$terms_of_service is of type object<Automattic\Jetpack\Terms_Of_Service>, but the function expects a object<Automattic\Jetpac...tpack\Terms_Of_Service>.

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...
$status is of type object<Automattic\Jetpack\Status>, but the function expects a object<Automattic\Jetpac...omattic\Jetpack\Status>.

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...
107
			return false;
108
		}
109
110
		$event_obj = $this->tracks_build_event_obj( $user, $event_name, $properties, $event_timestamp_millis );
111
112
		if ( is_wp_error( $event_obj->error ) ) {
113
			return $event_obj->error;
114
		}
115
116
		return $event_obj->record();
117
	}
118
119
	/**
120
	 * Determines whether tracking should be enabled.
121
	 *
122
	 * @param Automattic\Jetpack\Terms_Of_Service $terms_of_service A Terms_Of_Service object.
123
	 * @param Automattic\Jetpack\Status           $status A Status object.
124
	 *
125
	 * @return boolean True if tracking should be enabled, else false.
126
	 */
127
	public function should_enable_tracking( $terms_of_service, $status ) {
128
		if ( $status->is_offline_mode() ) {
129
			return false;
130
		}
131
132
		return $terms_of_service->has_agreed() || $this->connection->is_user_connected();
133
	}
134
135
	/**
136
	 * Procedurally build a Tracks Event Object.
137
	 * NOTE: Use this only when the simpler Automattic\Jetpack\Tracking->jetpack_tracks_record_event() function won't work for you.
138
	 *
139
	 * @param WP_user $user                   WP_user object.
140
	 * @param string  $event_name             The name of the event.
141
	 * @param array   $properties             Custom properties to send with the event.
142
	 * @param int     $event_timestamp_millis The time in millis since 1970-01-01 00:00:00 when the event occurred.
143
	 *
144
	 * @return \Jetpack_Tracks_Event|\WP_Error
145
	 */
146
	private function tracks_build_event_obj( $user, $event_name, $properties = array(), $event_timestamp_millis = false ) {
147
		$identity = $this->tracks_get_identity( $user->ID );
148
149
		$properties['user_lang'] = $user->get( 'WPLANG' );
150
151
		$blog_details = array(
152
			'blog_lang' => isset( $properties['blog_lang'] ) ? $properties['blog_lang'] : get_bloginfo( 'language' ),
153
		);
154
155
		$timestamp        = ( false !== $event_timestamp_millis ) ? $event_timestamp_millis : round( microtime( true ) * 1000 );
156
		$timestamp_string = is_string( $timestamp ) ? $timestamp : number_format( $timestamp, 0, '', '' );
157
158
		return new \Jetpack_Tracks_Event(
159
			array_merge(
160
				$blog_details,
161
				(array) $properties,
162
				$identity,
163
				array(
164
					'_en' => $event_name,
165
					'_ts' => $timestamp_string,
166
				)
167
			)
168
		);
169
	}
170
171
	/**
172
	 * Get the identity to send to tracks.
173
	 *
174
	 * @param int $user_id The user id of the local user.
175
	 *
176
	 * @return array $identity
177
	 */
178
	public function tracks_get_identity( $user_id ) {
179
180
		// Meta is set, and user is still connected.  Use WPCOM ID.
181
		$wpcom_id = get_user_meta( $user_id, 'jetpack_tracks_wpcom_id', true );
182
		if ( $wpcom_id && $this->connection->is_user_connected( $user_id ) ) {
183
			return array(
184
				'_ut' => 'wpcom:user_id',
185
				'_ui' => $wpcom_id,
186
			);
187
		}
188
189
		// User is connected, but no meta is set yet.  Use WPCOM ID and set meta.
190
		if ( $this->connection->is_user_connected( $user_id ) ) {
191
			$wpcom_user_data = $this->connection->get_connected_user_data( $user_id );
192
			update_user_meta( $user_id, 'jetpack_tracks_wpcom_id', $wpcom_user_data['ID'] );
193
194
			return array(
195
				'_ut' => 'wpcom:user_id',
196
				'_ui' => $wpcom_user_data['ID'],
197
			);
198
		}
199
200
		// User isn't linked at all.  Fall back to anonymous ID.
201
		$anon_id = get_user_meta( $user_id, 'jetpack_tracks_anon_id', true );
202
		if ( ! $anon_id ) {
203
			$anon_id = \Jetpack_Tracks_Client::get_anon_id();
204
			add_user_meta( $user_id, 'jetpack_tracks_anon_id', $anon_id, false );
205
		}
206
207
		if ( ! isset( $_COOKIE['tk_ai'] ) && ! headers_sent() ) {
208
			setcookie( 'tk_ai', $anon_id );
209
		}
210
211
		return array(
212
			'_ut' => 'anon',
213
			'_ui' => $anon_id,
214
		);
215
216
	}
217
}
218