Completed
Push — sync/user-meta ( e1df47...21525d )
by
unknown
14:15 queued 05:39
created

Jetpack_Sync_Module_Users::save_user_handler()   B

Complexity

Conditions 7
Paths 15

Size

Total Lines 57
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 19
nc 15
nop 2
dl 0
loc 57
rs 7.6759
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
class Jetpack_Sync_Module_Users extends Jetpack_Sync_Module {
4
	const MAX_INITIAL_SYNC_USERS = 100;
5
6
	function name() {
7
		return 'users';
8
	}
9
10
	// this is here to support the backfill API
11
	public function get_object_by_id( $object_type, $id ) {
12
		if ( $object_type === 'user' && $user = get_user_by( 'id', intval( $id ) ) ) {
13
			return $this->sanitize_user_and_expand( $user );
14
		}
15
16
		return false;
17
	}
18
19
	public function init_listeners( $callable ) {
20
		// users
21
		add_action( 'user_register', array( $this, 'save_user_handler' ) );
22
		add_action( 'profile_update', array( $this, 'save_user_handler' ), 10, 2 );
23
		add_action( 'add_user_to_blog', array( $this, 'save_user_handler' ) );
24
		add_action( 'jetpack_sync_add_user', $callable, 10, 2 );
25
		add_action( 'jetpack_sync_register_user', $callable, 10, 2 );
26
		add_action( 'jetpack_sync_save_user', $callable );
27
28
		//Edit user info, see https://github.com/WordPress/WordPress/blob/c05f1dc805bddcc0e76fd90c4aaf2d9ea76dc0fb/wp-admin/user-edit.php#L126
29
		add_action( 'personal_options_update', array( $this, 'edited_user_handler' ) );
30
		add_action( 'edit_user_profile_update', array( $this, 'edited_user_handler' ) );
31
		add_action( 'jetpack_user_edited', $callable );
32
33
		add_action( 'deleted_user', array( $this, 'deleted_user_handler' ), 10, 2 );
34
		add_action( 'jetpack_deleted_user', $callable, 10, 3 );
35
		add_action( 'remove_user_from_blog', array( $this, 'remove_user_from_blog_handler' ), 10, 2 );
36
		add_action( 'jetpack_removed_user_from_blog', $callable, 10, 2 );
37
38
		// user authentication
39
		add_action( 'wp_login', $callable, 10, 2 );
40
		add_action( 'wp_login_failed', $callable, 10, 2 );
41
		add_action( 'wp_logout', $callable, 10, 0 );
42
		add_action( 'wp_masterbar_logout', $callable, 10, 0 );
43
44
		// listen for meta changes ( locale, roles and capabilities )
45
		$this->init_listeners_for_meta_type( 'user', $callable );
46
		$this->init_meta_whitelist_handler( 'user', array( $this, 'filter_meta' ) );
47
	}
48
49
	public function filter_meta( $args ) {
50
		if ( $this->is_whitelisted_user_meta( $args[2] ) ) {
51
			return $args;
52
		}
53
		return false;
54
	}
55
56
	public function is_whitelisted_user_meta( $meta_key ) {
57
		$user_meta_keys = (array) Jetpack_Sync_Settings::get_setting( 'user_meta_whitelist' );
58
		return in_array( $meta_key, 	$user_meta_keys );
59
	}
60
61
62
63
	public function init_full_sync_listeners( $callable ) {
64
		add_action( 'jetpack_full_sync_users', $callable );
65
	}
66
67
	public function init_before_send() {
68
		add_filter( 'jetpack_sync_before_send_jetpack_sync_add_user', array( $this, 'expand_user' ) );
69
		add_filter( 'jetpack_sync_before_send_jetpack_sync_register_user', array( $this, 'expand_user' ) );
70
		add_filter( 'jetpack_sync_before_send_jetpack_sync_save_user', array( $this, 'expand_user' ), 10, 2 );
71
		add_filter( 'jetpack_sync_before_send_wp_login', array( $this, 'expand_login_username' ), 10, 1 );
72
		add_filter( 'jetpack_sync_before_send_wp_logout', array( $this, 'expand_logout_username' ), 10, 2 );
73
74
		// full sync
75
		add_filter( 'jetpack_sync_before_send_jetpack_full_sync_users', array( $this, 'expand_users' ) );
76
	}
77
78
	public function sanitize_user_and_expand( $user ) {
79
		$user = $this->sanitize_user( $user );
80
81
		return $this->add_to_user( $user );
82
	}
83
84
	public function sanitize_user( $user ) {
85
		// this create a new user object and stops the passing of the object by reference.
86
		$user = unserialize( serialize( $user ) );
87
88
		if ( is_object( $user ) && is_object( $user->data ) ) {
89
			unset( $user->data->user_pass );
90
			unset( $user->cap_key ); //
91
			unset( $user->allcaps ); // We should be able to constuct this from the roles data that we have.
92
93
			if ( isset( $user->filter ) ) {
94
				unset( $user->filter );
95
			}
96
		}
97
		return $user;
98
	}
99
100
	public function add_to_user( $user ) {
101
		$user->allowed_mime_types = get_allowed_mime_types( $user );
102
		return $user;
103
	}
104
105
	public function expand_user( $args ) {
106
		list( $user ) = $args;
107
108
		if ( $user ) {
109
110
			return array( $this->sanitize_user_and_expand( $user ) );
111
		}
112
113
		return false;
114
	}
115
116
	public function expand_login_username( $args ) {
117
		list( $login, $user ) = $args;
118
		$user = $this->sanitize_user( $user );
119
120
		return array( $login, $user );
121
	}
122
123
	public function expand_logout_username( $args, $user_id ) {
124
		$user  = get_userdata( $user_id );
125
		$user  = $this->sanitize_user( $user );
126
		$login = '';
127
		if ( is_object( $user ) && is_object( $user->data ) ) {
128
			$login = $user->data->user_login;
129
		}
130
131
		return array( $login, $user );
132
	}
133
134
	public function deleted_user_handler( $deleted_user_id, $reassigned_user_id = '' ) {
135
		$is_multisite = is_multisite();
136
		/**
137
		 * Fires when a user is deleted on a site
138
		 *
139
		 * @since 5.4.0
140
		 *
141
		 * @param int $deleted_user_id - ID of the deleted user
142
		 * @param int $reassigned_user_id - ID of the user the deleted user's posts is reassigned to (if any)
143
		 * @param bool $is_multisite - Whether this site is a multisite installation
144
		 */
145
		do_action( 'jetpack_deleted_user', $deleted_user_id, $reassigned_user_id, $is_multisite );
146
	}
147
148
	public function edited_user_handler( $user_id ) {
149
		/**
150
		 * Fires when a user is edited on a site
151
		 *
152
		 * @since 5.4.0
153
		 *
154
		 * @param int $user_id - ID of the edited user
155
		 */
156
		do_action( 'jetpack_user_edited', $user_id );
157
	}
158
	
159
	function save_user_handler( $user_id, $old_user_data = null ) {
160
		// ensure we only sync users who are members of the current blog
161
		if ( ! is_user_member_of_blog( $user_id, get_current_blog_id() ) ) {
162
			return;
163
		}
164
165
		$user = $this->sanitize_user( get_user_by( 'id', $user_id ) );
166
167
		// Older versions of WP don't pass the old_user_data in ->data
168
		if ( isset( $old_user_data->data ) ) {
169
			$old_user = $old_user_data->data;
170
		} else {
171
			$old_user = $old_user_data;
172
		}
173
174
		if ( $old_user !== null ) {
175
			unset( $old_user->user_pass );
176
			if ( serialize( $old_user ) === serialize( $user->data ) ) {
177
				return;
178
			}
179
		}
180
181
		if ( 'user_register' === current_filter() ) {
182
			/**
183
			 * Fires when a new user is registered on a site
184
			 *
185
			 * @since 4.9.0
186
			 *
187
			 * @param object The WP_User object
188
			 */
189
			do_action( 'jetpack_sync_register_user', $user );
190
191
			return;
192
		}
193
		/* MU Sites add users instead of register them to sites */
194
		if ( 'add_user_to_blog' === current_filter() ) {
195
			/**
196
			 * Fires when a new user is added to a site. (WordPress Multisite)
197
			 *
198
			 * @since 4.9.0
199
			 *
200
			 * @param object The WP_User object
201
			 */
202
			do_action( 'jetpack_sync_add_user', $user );
203
204
			return;
205
		}
206
207
		/**
208
		 * Fires when the client needs to sync an updated user
209
		 *
210
		 * @since 4.2.0
211
		 *
212
		 * @param object The WP_User object
213
		 */
214
		do_action( 'jetpack_sync_save_user', $user );
215
	}
216
217
	function save_user_role_handler( $user_id, $role, $old_roles = null ) {
218
		//The jetpack_sync_register_user payload is identical to jetpack_sync_save_user, don't send both
219
		if ( $this->is_create_user() || $this->is_add_user_to_blog() ) {
220
			return;
221
		}
222
223
		$user = $this->sanitize_user( get_user_by( 'id', $user_id ) );
224
		/**
225
		 * Fires when the client needs to sync an updated user
226
		 *
227
		 * @since 4.2.0
228
		 *
229
		 * @param object The WP_User object
230
		 */
231
		do_action( 'jetpack_sync_save_user', $user );
232
	}
233
234
	public function enqueue_full_sync_actions( $config, $max_items_to_enqueue, $state ) {
235
		global $wpdb;
236
		return $this->enqueue_all_ids_as_action( 'jetpack_full_sync_users', $wpdb->usermeta, 'user_id', $this->get_where_sql( $config ), $max_items_to_enqueue, $state );
237
	}
238
239
	public function estimate_full_sync_actions( $config ) {
240
		global $wpdb;
241
242
		$query = "SELECT count(*) FROM $wpdb->usermeta";
243
244
		if ( $where_sql = $this->get_where_sql( $config ) ) {
245
			$query .= ' WHERE ' . $where_sql;
246
		}
247
248
		$count = $wpdb->get_var( $query );
249
		return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
250
	}
251
252
	private function get_where_sql( $config ) {
253
		global $wpdb;
254
		$prefix = $wpdb->get_blog_prefix();
255
		$query = "meta_key = '{$prefix}capabilities'";
256
257
		// config is a list of user IDs to sync
258
		if ( is_array( $config ) ) {
259
			$query .= ' AND user_id IN (' . implode( ',', array_map( 'intval', $config ) ) . ')';
260
		}
261
262
		return $query;
263
	}
264
265
	function get_full_sync_actions() {
266
		return array( 'jetpack_full_sync_users' );
267
	}
268
269
	function get_initial_sync_user_config() {
270
		global $wpdb;
271
		$prefix = $wpdb->get_blog_prefix();
272
		$user_ids = $wpdb->get_col( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '{$prefix}user_level' AND meta_value > 0 LIMIT " . ( self::MAX_INITIAL_SYNC_USERS + 1 ) );
273
274
		if ( count( $user_ids ) <= self::MAX_INITIAL_SYNC_USERS ) {
275
			return $user_ids;
276
		} else {
277
			return false;
278
		}
279
	}
280
281
	public function expand_users( $args ) {
282
		$user_ids = $args[0];
283
		return array(
284
			'users' => array_map( array( $this, 'sanitize_user_and_expand' ), get_users( array( 'include' => $user_ids ) ) ),
285
			'meta' => $this->get_metadata( $user_ids, 'user', Jetpack_Sync_Settings::get_setting( 'user_meta_whitelist' ) ),
286
		);
287
		return ;
0 ignored issues
show
Unused Code introduced by
return; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
288
	}
289
290
	public function remove_user_from_blog_handler( $user_id, $blog_id ) {
291
		//User is removed on add, see https://github.com/WordPress/WordPress/blob/0401cee8b36df3def8e807dd766adc02b359dfaf/wp-includes/ms-functions.php#L2114
292
		if ( $this->is_add_new_user_to_blog() ) {
293
			return;
294
		}
295
296
		$reassigned_user_id = $this->get_reassigned_network_user_id();
297
298
		//Note that we are in the context of the blog the user is removed from, see https://github.com/WordPress/WordPress/blob/473e1ba73bc5c18c72d7f288447503713d518790/wp-includes/ms-functions.php#L233
299
		/**
300
		 * Fires when a user is removed from a blog on a multisite installation
301
		 *
302
		 * @since 5.4.0
303
		 *
304
		 * @param int $user_id - ID of the removed user
305
		 * @param int $reassigned_user_id - ID of the user the removed user's posts is reassigned to (if any)
306
		 */
307
		do_action( 'jetpack_removed_user_from_blog', $user_id, $reassigned_user_id );
308
	}
309
310
	private function is_add_new_user_to_blog() {
311
		return Jetpack::is_function_in_backtrace( 'add_new_user_to_blog' );
312
	}
313
314
	private function is_add_user_to_blog() {
315
		return Jetpack::is_function_in_backtrace( 'add_user_to_blog' );
316
	}
317
318
	private function is_create_user() {
319
		$functions = array(
320
			'add_new_user_to_blog', // Used to suppress jetpack_sync_save_user in save_user_cap_handler when user registered on multi site
321
			'wp_create_user', // Used to suppress jetpack_sync_save_user in save_user_role_handler when user registered on multi site
322
			'wp_insert_user', // Used to suppress jetpack_sync_save_user in save_user_cap_handler and save_user_role_handler when user registered on single site
323
		);
324
325
		return Jetpack::is_function_in_backtrace( $functions );
326
	}
327
328
	private function get_reassigned_network_user_id() {
329
		$backtrace = debug_backtrace( false );
330
		foreach ( $backtrace as $call ) {
331
			if (
332
				'remove_user_from_blog' === $call['function'] &&
333
				3 === count( $call['args'] )
334
			) {
335
				return $call['args'][2];
336
			}
337
		}
338
339
		return false;
340
	}
341
}
342