Skip to content

Commit

Permalink
Sync: Update User Sync Module (#8506)
Browse files Browse the repository at this point in the history
* pachanga

* beautify

* 👊 👊 👊 🚢 :shipit:

* 🎱

* Arrays are not allowed in class constants

* don't forget multisite

* @jeherve ❤️
  • Loading branch information
lezama authored Jan 12, 2018
1 parent 7d6b617 commit 47aac99
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 143 deletions.
216 changes: 78 additions & 138 deletions sync/class.jetpack-sync-module-users.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class Jetpack_Sync_Module_Users extends Jetpack_Sync_Module {
const MAX_INITIAL_SYNC_USERS = 100;

protected $previous_role = array();
protected $flags = array();

function name() {
return 'users';
Expand All @@ -19,18 +19,19 @@ public function get_object_by_id( $object_type, $id ) {
}

public function init_listeners( $callable ) {

// users
add_action( 'user_register', array( $this, 'user_register_handler' ) );
add_action( 'profile_update', array( $this, 'save_user_handler' ), 10, 2 );

add_action( 'add_user_to_blog', array( $this, 'add_user_to_blog_handler' ) );
add_action( 'jetpack_sync_add_user', $callable, 10, 2 );

add_action( 'jetpack_sync_register_user', $callable, 10, 2 );
add_action( 'jetpack_sync_save_user', $callable, 10, 2 );
add_action( 'jetpack_sync_register_user', array( $this, 'clear_flags' ), 11 );

//Edit user info, see https://github.com/WordPress/WordPress/blob/c05f1dc805bddcc0e76fd90c4aaf2d9ea76dc0fb/wp-admin/user-edit.php#L126
add_action( 'personal_options_update', array( $this, 'edited_user_handler' ) );
add_action( 'edit_user_profile_update', array( $this, 'edited_user_handler' ) );
add_action( 'jetpack_user_edited', $callable );
add_action( 'jetpack_sync_save_user', $callable, 10, 2 );
add_action( 'jetpack_sync_save_user', array( $this, 'clear_flags' ), 11 );

add_action( 'jetpack_sync_user_locale', $callable, 10, 2 );
add_action( 'jetpack_sync_user_locale_delete', $callable, 10, 1 );
Expand Down Expand Up @@ -61,24 +62,20 @@ public function init_full_sync_listeners( $callable ) {
}

public function init_before_send() {
add_filter( 'jetpack_sync_before_send_jetpack_sync_add_user', array( $this, 'expand_user' ) );
add_filter( 'jetpack_sync_before_send_jetpack_sync_register_user', array( $this, 'expand_user' ) );
add_filter( 'jetpack_sync_before_send_jetpack_sync_save_user', array( $this, 'expand_save_user' ) );
add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_add_user', array( $this, 'expand_action' ) );
add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_register_user', array( $this, 'expand_action' ) );

add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_save_user', array( $this, 'expand_action' ) );

add_filter( 'jetpack_sync_before_send_wp_login', array( $this, 'expand_login_username' ), 10, 1 );
add_filter( 'jetpack_sync_before_send_wp_logout', array( $this, 'expand_logout_username' ), 10, 2 );

// full sync
add_filter( 'jetpack_sync_before_send_jetpack_full_sync_users', array( $this, 'expand_users' ) );
}

public function sanitize_user_and_expand( $user ) {
$user = $this->get_user( $user );
$user = $this->add_to_user( $user );
return $this->sanitize_user( $user );
}

private function get_user( $user ) {
if ( $user && ! is_object( $user ) && is_numeric( $user ) ) {
if ( is_numeric( $user ) ) {
$user = get_user_by( 'id', $user );
}
if ( $user instanceof WP_User ) {
Expand All @@ -95,17 +92,15 @@ public function sanitize_user( $user ) {
if ( is_object( $user ) && is_object( $user->data ) ) {
unset( $user->data->user_pass );
}
if ( $user ) {
$user->allcaps = $this->get_real_user_capabilities( $user );
}
return $user;
}

public function add_to_user( $user ) {
public function expand_user( $user ) {
if ( ! is_object( $user ) ) {
return null;
}
$user->allowed_mime_types = get_allowed_mime_types( $user );
$user->allcaps = $this->get_real_user_capabilities( $user );

if ( function_exists( 'get_user_locale' ) ) {

Expand All @@ -131,33 +126,23 @@ public function get_real_user_capabilities( $user ) {
return $user_capabilities;
}

public function expand_user( $args ) {
public function sanitize_user_and_expand( $user ) {
$user = $this->get_user( $user );
$user = $this->expand_user( $user );
return $this->sanitize_user( $user );
}

public function expand_action( $args ) {
// the first argument is always the user
list( $user ) = $args;
if ( $user ) {
return array( $this->add_to_user( $user ) );
$args[0] = $this->sanitize_user_and_expand( $user );
return $args;
}

return false;
}

public function expand_save_user( $args ) {
$default_flags = array(
'password_changed' => false,
'role_changed' => false,
'previous_role' => false,
);

$flags = ( isset( $args[1] ) && is_array( $args[1] ) ) ? $args[1] : array();
$expanded_user = $this->expand_user( $args );

if ( $expanded_user ) {
$flags = wp_parse_args( $flags, $default_flags );
$expanded_user[] = $flags;
}

return $expanded_user;
}

public function expand_login_username( $args ) {
list( $login, $user ) = $args;
$user = $this->sanitize_user( $user );
Expand Down Expand Up @@ -195,70 +180,52 @@ public function deleted_user_handler( $deleted_user_id, $reassigned_user_id = ''
do_action( 'jetpack_deleted_user', $deleted_user_id, $reassigned_user_id, $is_multisite );
}

public function edited_user_handler( $user_id ) {
/**
* Fires when a user is edited on a site
*
* @since 5.4.0
*
* @param int $user_id - ID of the edited user
*/
do_action( 'jetpack_user_edited', $user_id );
}

function user_register_handler( $user_id, $old_user_data = null ) {
// ensure we only sync users who are members of the current blog
if ( ! is_user_member_of_blog( $user_id, get_current_blog_id() ) ) {
return;
}
$raw_user = get_user_by( 'id', $user_id );
$user = $this->sanitize_user( $raw_user );

if ( 'user_register' === current_filter() ) {
/**
* Fires when a new user is registered on a site
*
* @since 4.9.0
*
* @param object The WP_User object
*/
do_action( 'jetpack_sync_register_user', $user );

return;
}
/**
* Fires when a new user is registered on a site
*
* @since 4.9.0
*
* @param object The WP_User object
*/
do_action( 'jetpack_sync_register_user', $user_id );
}

function add_user_to_blog_handler( $user_id, $old_user_data = null ) {
// ensure we only sync users who are members of the current blog
if ( ! is_user_member_of_blog( $user_id, get_current_blog_id() ) ) {
return;
}
$raw_user = get_user_by( 'id', $user_id );
$user = $this->sanitize_user( $raw_user );

do_action( 'jetpack_sync_add_user', $user );
/**
* Fires when a user is added on a site
*
* @since 4.9.0
*
* @param object The WP_User object
*/
do_action( 'jetpack_sync_add_user', $user_id );
}

function save_user_handler( $user_id, $old_user_data = null ) {
// ensure we only sync users who are members of the current blog
if ( ! is_user_member_of_blog( $user_id, get_current_blog_id() ) ) {
return;
}
$raw_user = get_user_by( 'id', $user_id );
$user = $this->sanitize_user( $raw_user );
$user_password_changed = false;

$user = get_user_by( 'id', $user_id );

// Older versions of WP don't pass the old_user_data in ->data
if ( isset( $old_user_data->data ) ) {
$old_user = $old_user_data->data;
} else {
$old_user = $old_user_data;
}

$role_changed = isset( $this->previous_role[ $user_id ] ) ? $this->previous_role[ $user_id ] : false;

if ( $old_user !== null && $raw_user->user_pass !== $old_user->user_pass ) {
$user_password_changed = true;
if ( $old_user !== null && $user->user_pass !== $old_user->user_pass ) {
$this->flags[ $user_id ]['password_changed'] = true;
}

/**
Expand All @@ -269,89 +236,58 @@ function save_user_handler( $user_id, $old_user_data = null ) {
* @param object The WP_User object
* @param array state - New since 5.8.0
*/
do_action( 'jetpack_sync_save_user', $user, array(
'password_changed' => $user_password_changed,
'role_changed' => (bool) $role_changed,
'previous_role' => $role_changed,
) );
do_action( 'jetpack_sync_save_user', $user_id, $this->get_flags( $user_id ) );
}

function save_user_role_handler( $user_id, $role, $old_roles = null ) {
$this->add_flags( $user_id, array( 'role_changed' => true, 'previous_role' => $old_roles ) );

//The jetpack_sync_register_user payload is identical to jetpack_sync_save_user, don't send both
if ( $this->is_create_user() || $this->is_add_user_to_blog() ) {
$this->previous_role[ $user_id ] = $old_roles;
return;
}

$user = $this->sanitize_user( get_user_by( 'id', $user_id ) );
/**
* Fires when the client needs to sync an updated user
*
* @since 4.2.0
*
* @param object The WP_User object
* @param array state
* This action is documented already in this file
*/
do_action( 'jetpack_sync_save_user', $user, array(
'role_changed' => true,
'previous_role' => $old_roles ) );
do_action( 'jetpack_sync_save_user', $user_id, $this->get_flags( $user_id ) );
}

function maybe_save_user_meta( $meta_id, $user_id, $meta_key, $value ) {
if ( $meta_key === 'locale' ) {
if ( current_filter() === 'deleted_user_meta' ) {
/**
* Allow listeners to listen for user local delete changes
*
* @since 4.8.0
*
* @param int $user_id - The ID of the user whos locale is being deleted
*/
do_action( 'jetpack_sync_user_locale_delete', $user_id );
} else {
/**
* Allow listeners to listen for user local changes
*
* @since 4.8.0
*
* @param int $user_id - The ID of the user whos locale is being changed
* @param int $value - The value of the new locale
*/
do_action( 'jetpack_sync_user_locale', $user_id, $value );
}
function get_flags( $user_id ) {
if ( isset( $this->flags[ $user_id ] ) ) {
return $this->flags[ $user_id ];
}
$this->save_user_cap_handler( $meta_id, $user_id, $meta_key, $value );
return array();
}

function save_user_cap_handler( $meta_id, $user_id, $meta_key, $capabilities ) {
// if a user is currently being removed as a member of this blog, we don't fire the event
if ( current_filter() === 'deleted_user_meta' ) {
return;
function clear_flags( $user_id ) {
if ( isset( $this->flags[ $user_id ] ) ) {
unset( $this->flags[ $user_id ] );
}
}

// Since we are currently only caring about capabilities at this point don't need to save the user info at this save the user info at this point.
if ( current_filter() === 'added_user_meta' ) {
return;
}
function add_flags( $user_id, $flags ) {
$this->flags[ $user_id ] = wp_parse_args( $flags, $this->get_flags( $user_id ) );
}

//The jetpack_sync_register_user payload is identical to jetpack_sync_save_user, don't send both
if ( $this->is_create_user() || $this->is_add_user_to_blog() ) {
return;
function maybe_save_user_meta( $meta_id, $user_id, $meta_key, $value ) {
if ( $meta_key === 'locale' ) {
$this->add_flags( $user_id, array( 'locale_changed' => true ) );
}

$user = get_user_by( 'id', $user_id );
if ( $meta_key === $user->cap_key ) {
$this->add_flags( $user_id, array( 'capabilities_changed' => true ) );
}

if ( $this->is_create_user() || $this->is_add_user_to_blog() || $this->is_delete_user() ) {
return;
}

if ( isset( $this->flags[ $user_id ] ) ) {
/**
* Fires when the client needs to sync an updated user
*
* @since 4.2.0
*
* @param object The Sanitized WP_User object
* @param array state Since 5.8
* This action is documented already in this file
*/
do_action( 'jetpack_sync_save_user', $this->sanitize_user( $user ),
array( 'capabilities_action' => current_filter(), 'capabilities' => $capabilities )
);
do_action( 'jetpack_sync_save_user', $user_id, $this->get_flags( $user_id ) );
}
}

Expand Down Expand Up @@ -438,6 +374,10 @@ private function is_add_user_to_blog() {
return Jetpack::is_function_in_backtrace( 'add_user_to_blog' );
}

private function is_delete_user() {
return Jetpack::is_function_in_backtrace( array( 'wp_delete_user' , 'remove_user_from_blog' ) );
}

private function is_create_user() {
$functions = array(
'add_new_user_to_blog', // Used to suppress jetpack_sync_save_user in save_user_cap_handler when user registered on multi site
Expand Down
11 changes: 6 additions & 5 deletions tests/php/sync/test_class.jetpack-sync-users.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ public function test_user_set_role_is_synced_in_wp_update_user_context() {
$this->assertUsersEqual( $client_user, $server_user );

$events = $this->server_event_storage->get_all_events( 'jetpack_sync_save_user' );

$this->assertTrue( $events[0]->args[1]['role_changed'] );
$this->assertEquals( $events[0]->args[1]['previous_role'], array( 'subscriber') );
$this->assertTrue( empty( $events[1] ) );
Expand Down Expand Up @@ -526,7 +527,7 @@ public function test_returns_user_object_by_id() {
$this->assertEquals( $synced_user, $retrieved_user );
}

public function test_update_user_locale_is_synced() {
public function test_update_user_locale_changed_is_synced() {
global $wp_version;
if ( version_compare( $wp_version, 4.7, '<' ) ) {
$this->markTestSkipped( 'WP 4.7 and up supports user locale' );
Expand All @@ -536,8 +537,8 @@ public function test_update_user_locale_is_synced() {
update_user_meta( $this->user_id, 'locale', 'en_GB' );
$this->sender->do_sync();

$event = $this->server_event_storage->get_most_recent_event( 'jetpack_sync_user_locale' );
$this->assertNotEmpty( $event );
$event = $this->server_event_storage->get_most_recent_event( 'jetpack_sync_save_user' );
$this->assertTrue( $event->args[1]['locale_changed'] );

$server_user_local = $this->server_replica_storage->get_user_locale( $this->user_id );
$this->assertEquals( get_user_locale( $this->user_id ), $server_user_local );
Expand All @@ -553,8 +554,8 @@ public function test_delete_user_locale_is_synced() {
delete_user_meta( $this->user_id, 'locale' );
$this->sender->do_sync();

$event = $this->server_event_storage->get_most_recent_event( 'jetpack_sync_user_locale_delete' );
$this->assertNotEmpty( $event );
$event = $this->server_event_storage->get_most_recent_event( 'jetpack_sync_save_user' );
$this->assertTrue( $event->args[1]['locale_changed'] );

$server_user_local = $this->server_replica_storage->get_user_locale( $this->user_id );
$this->assertEquals( '', $server_user_local );
Expand Down

0 comments on commit 47aac99

Please sign in to comment.