summaryrefslogtreecommitdiff
blob: f37492f68add15a919a1c0fe87f66243ede11e1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
<?php
/**
 * Sync for users.
 *
 * @package automattic/jetpack-sync
 */

namespace Automattic\Jetpack\Sync;

use Automattic\Jetpack\Connection\Manager as Jetpack_Connection;
use Automattic\Jetpack\Roles;

/**
 * Class Users.
 *
 * Responsible for syncing user data changes.
 */
class Users {
	/**
	 * Roles of all users, indexed by user ID.
	 *
	 * @access public
	 * @static
	 *
	 * @var array
	 */
	public static $user_roles = array();

	/**
	 * Initialize sync for user data changes.
	 *
	 * @access public
	 * @static
	 * @todo Eventually, connection needs to be instantiated at the top level in the sync package.
	 */
	public static function init() {
		$connection = new Jetpack_Connection();
		if ( $connection->is_active() ) {
			// Kick off synchronization of user role when it changes.
			add_action( 'set_user_role', array( __CLASS__, 'user_role_change' ) );
		}
	}

	/**
	 * Synchronize connected user role changes.
	 *
	 * @access public
	 * @static
	 *
	 * @param int $user_id ID of the user.
	 */
	public static function user_role_change( $user_id ) {
		$connection = new Jetpack_Connection();
		if ( $connection->is_user_connected( $user_id ) ) {
			self::update_role_on_com( $user_id );
			// Try to choose a new master if we're demoting the current one.
			self::maybe_demote_master_user( $user_id );
		}
	}

	/**
	 * Retrieve the role of a user by their ID.
	 *
	 * @access public
	 * @static
	 *
	 * @param int $user_id ID of the user.
	 * @return string Role of the user.
	 */
	public static function get_role( $user_id ) {
		if ( isset( self::$user_roles[ $user_id ] ) ) {
			return self::$user_roles[ $user_id ];
		}

		$current_user_id = get_current_user_id();
		wp_set_current_user( $user_id );
		$roles = new Roles();
		$role  = $roles->translate_current_user_to_role();
		wp_set_current_user( $current_user_id );
		self::$user_roles[ $user_id ] = $role;

		return $role;
	}

	/**
	 * Retrieve the signed role of a user by their ID.
	 *
	 * @access public
	 * @static
	 *
	 * @param int $user_id ID of the user.
	 * @return string Signed role of the user.
	 */
	public static function get_signed_role( $user_id ) {
		$connection = new Jetpack_Connection();
		return $connection->sign_role( self::get_role( $user_id ), $user_id );
	}

	/**
	 * Retrieve the signed role and update it in WP.com for that user.
	 *
	 * @access public
	 * @static
	 *
	 * @param int $user_id ID of the user.
	 */
	public static function update_role_on_com( $user_id ) {
		$signed_role = self::get_signed_role( $user_id );
		\Jetpack::xmlrpc_async_call( 'jetpack.updateRole', $user_id, $signed_role );
	}

	/**
	 * Choose a new master user if we're demoting the current one.
	 *
	 * @access public
	 * @static
	 * @todo Disconnect if there is no user with enough capabilities to be the master user.
	 * @uses \WP_User_Query
	 *
	 * @param int $user_id ID of the user.
	 */
	public static function maybe_demote_master_user( $user_id ) {
		$master_user_id = (int) \Jetpack_Options::get_option( 'master_user' );
		$role           = self::get_role( $user_id );
		if ( $user_id === $master_user_id && 'administrator' !== $role ) {
			$query      = new \WP_User_Query(
				array(
					'fields'  => array( 'id' ),
					'role'    => 'administrator',
					'orderby' => 'id',
					'exclude' => array( $master_user_id ),
				)
			);
			$new_master = false;
			$connection = new Jetpack_Connection();
			foreach ( $query->results as $result ) {
				$found_user_id = absint( $result->id );
				if ( $found_user_id && $connection->is_user_connected( $found_user_id ) ) {
					$new_master = $found_user_id;
					break;
				}
			}

			if ( $new_master ) {
				\Jetpack_Options::update_option( 'master_user', $new_master );
			}
			// TODO: else disconnect..?
		}
	}
}