Completed
Push — update/use-identity-crisis-pac... ( d14b6d...6e141b )
by
unknown
128:58 queued 119:18
created

Jetpack_React_Page::get_initial_state()   F

Complexity

Conditions 16
Paths 18432

Size

Total Lines 151

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
nc 18432
nop 0
dl 0
loc 151
rs 1.1198
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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
use Automattic\Jetpack\Constants;
3
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
4
use Automattic\Jetpack\Connection\REST_Connector;
5
use Automattic\Jetpack\Device_Detection\User_Agent_Info;
6
use Automattic\Jetpack\Licensing;
7
use Automattic\Jetpack\Partner;
8
use Automattic\Jetpack\Status;
9
10
include_once( 'class.jetpack-admin-page.php' );
11
12
// Builds the landing page and its menu
13
class Jetpack_React_Page extends Jetpack_Admin_Page {
14
15
	protected $dont_show_if_not_active = false;
16
17
	protected $is_redirecting = false;
18
19
	function get_page_hook() {
20
		// Add the main admin Jetpack menu
21
		return add_menu_page( 'Jetpack', 'Jetpack', 'jetpack_admin_page', 'jetpack', array( $this, 'render' ), 'div', 3 );
22
	}
23
24
	function add_page_actions( $hook ) {
25
		/** This action is documented in class.jetpack.php */
26
		do_action( 'jetpack_admin_menu', $hook );
27
28
		if ( ! isset( $_GET['page'] ) || 'jetpack' !== $_GET['page'] ) {
29
			return; // No need to handle the fallback redirection if we are not on the Jetpack page
30
		}
31
32
		// Adding a redirect meta tag if the REST API is disabled
33
		if ( ! $this->is_rest_api_enabled() ) {
34
			$this->is_redirecting = true;
35
			add_action( 'admin_head', array( $this, 'add_fallback_head_meta' ) );
36
		}
37
38
		// Adding a redirect meta tag wrapped in noscript tags for all browsers in case they have JavaScript disabled
39
		add_action( 'admin_head', array( $this, 'add_noscript_head_meta' ) );
40
41
		// If this is the first time the user is viewing the admin, don't show JITMs.
42
		// This filter is added just in time because this function is called on admin_menu
43
		// and JITMs are initialized on admin_init
44
		if ( Jetpack::is_active() && ! Jetpack_Options::get_option( 'first_admin_view', false ) ) {
45
			Jetpack_Options::update_option( 'first_admin_view', true );
46
			add_filter( 'jetpack_just_in_time_msgs', '__return_false' );
47
		}
48
	}
49
50
	/**
51
	 * Add Jetpack Dashboard sub-link and point it to AAG if the user can view stats, manage modules or if Protect is active.
52
	 *
53
	 * Works in Dev Mode or when user is connected.
54
	 *
55
	 * @since 4.3.0
56
	 */
57
	function jetpack_add_dashboard_sub_nav_item() {
58 View Code Duplication
		if ( ( new Status() )->is_offline_mode() || Jetpack::is_active() ) {
59
			add_submenu_page( 'jetpack', __( 'Dashboard', 'jetpack' ), __( 'Dashboard', 'jetpack' ), 'jetpack_admin_page', 'jetpack#/dashboard', '__return_null' );
60
			remove_submenu_page( 'jetpack', 'jetpack' );
61
		}
62
	}
63
64
	/**
65
	 * If user is allowed to see the Jetpack Admin, add Settings sub-link.
66
	 *
67
	 * @since 4.3.0
68
	 */
69
	function jetpack_add_settings_sub_nav_item() {
70 View Code Duplication
		if ( ( ( new Status() )->is_offline_mode() || Jetpack::is_active() ) && current_user_can( 'edit_posts' ) ) {
71
			add_submenu_page( 'jetpack', __( 'Settings', 'jetpack' ), __( 'Settings', 'jetpack' ), 'jetpack_admin_page', 'jetpack#/settings', '__return_null' );
72
		}
73
	}
74
75
	function add_fallback_head_meta() {
76
		echo '<meta http-equiv="refresh" content="0; url=?page=jetpack_modules">';
77
	}
78
79
	function add_noscript_head_meta() {
80
		echo '<noscript>';
81
		$this->add_fallback_head_meta();
82
		echo '</noscript>';
83
	}
84
85
	/**
86
	 * Custom menu order.
87
	 *
88
	 * @deprecated since 9.2.0
89
	 * @param array $menu_order Menu order.
90
	 * @return array
91
	 */
92
	function jetpack_menu_order( $menu_order ) {
93
		_deprecated_function( __METHOD__, 'jetpack-9.2' );
94
95
		return $menu_order;
96
	}
97
98
	function page_render() {
99
		/** This action is already documented in views/admin/admin-page.php */
100
		do_action( 'jetpack_notices' );
101
102
		// Try fetching by patch
103
		$static_html = @file_get_contents( JETPACK__PLUGIN_DIR . '_inc/build/static.html' );
104
105
		if ( false === $static_html ) {
106
107
			// If we still have nothing, display an error
108
			echo '<p>';
109
			esc_html_e( 'Error fetching static.html. Try running: ', 'jetpack' );
110
			echo '<code>yarn distclean && yarn build</code>';
111
			echo '</p>';
112
		} else {
113
114
			// We got the static.html so let's display it
115
			echo $static_html;
116
		}
117
	}
118
119
	/**
120
	 * Gets array of any Jetpack notices that have been dismissed.
121
	 *
122
	 * @since 4.0.1
123
	 * @return mixed|void
124
	 */
125
	function get_dismissed_jetpack_notices() {
126
		$jetpack_dismissed_notices = get_option( 'jetpack_dismissed_notices', array() );
127
		/**
128
		 * Array of notices that have been dismissed.
129
		 *
130
		 * @since 4.0.1
131
		 *
132
		 * @param array $jetpack_dismissed_notices If empty, will not show any Jetpack notices.
133
		 */
134
		$dismissed_notices = apply_filters( 'jetpack_dismissed_notices', $jetpack_dismissed_notices );
135
		return $dismissed_notices;
136
	}
137
138
	function additional_styles() {
139
		Jetpack_Admin_Page::load_wrapper_styles();
140
	}
141
142
	function page_admin_scripts() {
143
		if ( $this->is_redirecting ) {
144
			return; // No need for scripts on a fallback page
145
		}
146
147
		$status              = new Status();
148
		$is_offline_mode     = $status->is_offline_mode();
149
		$site_suffix         = $status->get_site_suffix();
150
		$script_deps_path    = JETPACK__PLUGIN_DIR . '_inc/build/admin.asset.php';
151
		$script_dependencies = array( 'wp-polyfill' );
152
		if ( file_exists( $script_deps_path ) ) {
153
			$asset_manifest      = include $script_deps_path;
154
			$script_dependencies = $asset_manifest['dependencies'];
155
		}
156
157
		wp_enqueue_script(
158
			'react-plugin',
159
			plugins_url( '_inc/build/admin.js', JETPACK__PLUGIN_FILE ),
160
			$script_dependencies,
161
			JETPACK__VERSION,
162
			true
163
		);
164
165
		if ( ! $is_offline_mode && Jetpack::is_active() ) {
166
			// Required for Analytics.
167
			wp_enqueue_script( 'jp-tracks', '//stats.wp.com/w.js', array(), gmdate( 'YW' ), true );
168
		}
169
170
		wp_set_script_translations( 'react-plugin', 'jetpack' );
171
172
		// Add objects to be passed to the initial state of the app.
173
		// Use wp_add_inline_script instead of wp_localize_script, see https://core.trac.wordpress.org/ticket/25280.
174
		wp_add_inline_script( 'react-plugin', 'var Initial_State=JSON.parse(decodeURIComponent("' . rawurlencode( wp_json_encode( $this->get_initial_state() ) ) . '"));', 'before' );
175
176
		// This will set the default URL of the jp_redirects lib.
177
		wp_add_inline_script( 'react-plugin', 'var jetpack_redirects = { currentSiteRawUrl: "' . $site_suffix . '" };', 'before' );
178
	}
179
180
	function get_initial_state() {
181
		global $is_safari;
182
183
		// Load API endpoint base classes and endpoints for getting the module list fed into the JS Admin Page
184
		require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-xmlrpc-consumer-endpoint.php';
185
		require_once JETPACK__PLUGIN_DIR . '_inc/lib/core-api/class.jetpack-core-api-module-endpoints.php';
186
		$moduleListEndpoint = new Jetpack_Core_API_Module_List_Endpoint();
187
		$modules = $moduleListEndpoint->get_modules();
188
189
		// Preparing translated fields for JSON encoding by transforming all HTML entities to
190
		// respective characters.
191
		foreach( $modules as $slug => $data ) {
0 ignored issues
show
Bug introduced by
The expression $modules of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
192
			$modules[ $slug ]['name'] = html_entity_decode( $data['name'] );
193
			$modules[ $slug ]['description'] = html_entity_decode( $data['description'] );
194
			$modules[ $slug ]['short_description'] = html_entity_decode( $data['short_description'] );
195
			$modules[ $slug ]['long_description'] = html_entity_decode( $data['long_description'] );
196
		}
197
198
		// Collecting roles that can view site stats.
199
		$stats_roles = array();
200
		$enabled_roles = function_exists( 'stats_get_option' ) ? stats_get_option( 'roles' ) : array( 'administrator' );
201
202
		if ( ! function_exists( 'get_editable_roles' ) ) {
203
			require_once ABSPATH . 'wp-admin/includes/user.php';
204
		}
205
		foreach ( get_editable_roles() as $slug => $role ) {
206
			$stats_roles[ $slug ] = array(
207
				'name' => translate_user_role( $role['name'] ),
208
				'canView' => is_array( $enabled_roles ) ? in_array( $slug, $enabled_roles, true ) : false,
209
			);
210
		}
211
212
		// Get information about current theme.
213
		$current_theme = wp_get_theme();
214
215
		// Get all themes that Infinite Scroll provides support for natively.
216
		$inf_scr_support_themes = array();
217
		foreach ( Jetpack::glob_php( JETPACK__PLUGIN_DIR . 'modules/infinite-scroll/themes' ) as $path ) {
218
			if ( is_readable( $path ) ) {
219
				$inf_scr_support_themes[] = basename( $path, '.php' );
220
			}
221
		}
222
223
		// Get last post, to build the link to Customizer in the Related Posts module.
224
		$last_post = get_posts( array( 'posts_per_page' => 1 ) );
225
		$last_post = isset( $last_post[0] ) && $last_post[0] instanceof WP_Post
0 ignored issues
show
Bug introduced by
The class WP_Post 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...
226
			? get_permalink( $last_post[0]->ID )
227
			: get_home_url();
228
229
		$current_user_data = jetpack_current_user_data();
230
231
		/**
232
		 * Adds information to the `connectionStatus` API field that is unique to the Jetpack React dashboard.
233
		 */
234
		$connection_status = array(
235
			'isInIdentityCrisis' => Jetpack::validate_sync_error_idc_option(),
236
			'sandboxDomain'      => JETPACK__SANDBOX_DOMAIN,
237
238
			/**
239
			 * Filter to add connection errors
240
			 * Format: array( array( 'code' => '...', 'message' => '...', 'action' => '...' ), ... )
241
			 *
242
			 * @since 8.7.0
243
			 *
244
			 * @param array $errors Connection errors.
245
			 */
246
			'errors'             => apply_filters( 'react_connection_errors_initial_state', array() ),
247
		);
248
249
		$connection_status = array_merge( REST_Connector::connection_status( false ), $connection_status );
250
251
		return array(
252
			'WP_API_root'                 => esc_url_raw( rest_url() ),
253
			'WP_API_nonce'                => wp_create_nonce( 'wp_rest' ),
254
			'pluginBaseUrl'               => plugins_url( '', JETPACK__PLUGIN_FILE ),
255
			'connectionStatus'            => $connection_status,
256
			'connectUrl'                  => false == $current_user_data['isConnected'] // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
257
				? Jetpack::init()->build_connect_url( true, false, false )
258
				: '',
259
			'dismissedNotices'            => $this->get_dismissed_jetpack_notices(),
260
			'isDevVersion'                => Jetpack::is_development_version(),
261
			'currentVersion'              => JETPACK__VERSION,
262
			'is_gutenberg_available'      => true,
263
			'getModules'                  => $modules,
264
			'rawUrl'                      => ( new Status() )->get_site_suffix(),
265
			'adminUrl'                    => esc_url( admin_url() ),
266
			'siteTitle'                   => (string) htmlspecialchars_decode( get_option( 'blogname' ), ENT_QUOTES ),
267
			'stats'                       => array(
268
				// data is populated asynchronously on page load.
269
				'data'  => array(
270
					'general' => false,
271
					'day'     => false,
272
					'week'    => false,
273
					'month'   => false,
274
				),
275
				'roles' => $stats_roles,
276
			),
277
			'aff'                         => Partner::init()->get_partner_code( Partner::AFFILIATE_CODE ),
278
			'partnerSubsidiaryId'         => Partner::init()->get_partner_code( Partner::SUBSIDIARY_CODE ),
279
			'settings'                    => $this->get_flattened_settings( $modules ),
0 ignored issues
show
Bug introduced by
It seems like $modules defined by $moduleListEndpoint->get_modules() on line 187 can also be of type string; however, Jetpack_React_Page::get_flattened_settings() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
280
			'userData'                    => array(
281
				'currentUser' => $current_user_data,
282
			),
283
			'siteData'                    => array(
284
				'icon'                       => has_site_icon()
285
					? apply_filters( 'jetpack_photon_url', get_site_icon_url(), array( 'w' => 64 ) )
0 ignored issues
show
Unused Code introduced by
The call to apply_filters() has too many arguments starting with array('w' => 64).

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
286
					: '',
287
				'siteVisibleToSearchEngines' => '1' == get_option( 'blog_public' ), // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
288
				/**
289
				 * Whether promotions are visible or not.
290
				 *
291
				 * @since 4.8.0
292
				 *
293
				 * @param bool $are_promotions_active Status of promotions visibility. True by default.
294
				 */
295
				'showPromotions'             => apply_filters( 'jetpack_show_promotions', true ),
296
				'isAtomicSite'               => jetpack_is_atomic_site(),
297
				'plan'                       => Jetpack_Plan::get(),
298
				'showBackups'                => Jetpack::show_backups_ui(),
299
				'showRecommendations'        => Jetpack_Recommendations::is_enabled(),
300
				'isMultisite'                => is_multisite(),
301
				'dateFormat'                 => get_option( 'date_format' ),
302
			),
303
			'themeData'                   => array(
304
				'name'      => $current_theme->get( 'Name' ),
305
				'hasUpdate' => (bool) get_theme_update_available( $current_theme ),
306
				'support'   => array(
307
					'infinite-scroll' => current_theme_supports( 'infinite-scroll' ) || in_array( $current_theme->get_stylesheet(), $inf_scr_support_themes, true ),
308
				),
309
			),
310
			'jetpackStateNotices'         => array(
311
				'messageCode'      => Jetpack::state( 'message' ),
312
				'errorCode'        => Jetpack::state( 'error' ),
313
				'errorDescription' => Jetpack::state( 'error_description' ),
314
				'messageContent'   => Jetpack::state( 'display_update_modal' ) ? $this->get_update_modal_data() : null,
315
			),
316
			'tracksUserData'              => Jetpack_Tracks_Client::get_connected_user_tracks_identity(),
317
			'currentIp'                   => function_exists( 'jetpack_protect_get_ip' ) ? jetpack_protect_get_ip() : false,
318
			'lastPostUrl'                 => esc_url( $last_post ),
319
			'externalServicesConnectUrls' => $this->get_external_services_connect_urls(),
320
			'calypsoEnv'                  => Jetpack::get_calypso_env(),
321
			'products'                    => Jetpack::get_products_for_purchase(),
322
			'recommendationsStep'         => Jetpack_Core_Json_Api_Endpoints::get_recommendations_step()['step'],
323
			'isSafari'                    => $is_safari || User_Agent_Info::is_opera_desktop(), // @todo Rename isSafari everywhere.
324
			'doNotUseConnectionIframe'    => Constants::is_true( 'JETPACK_SHOULD_NOT_USE_CONNECTION_IFRAME' ),
325
			'licensing'                   => array(
326
				'error'           => Licensing::instance()->last_error(),
327
				'showLicensingUi' => Licensing::instance()->is_licensing_input_enabled(),
328
			),
329
		);
330
	}
331
332
	function get_external_services_connect_urls() {
333
		$connect_urls = array();
334
		jetpack_require_lib( 'class.jetpack-keyring-service-helper' );
335
		foreach ( Jetpack_Keyring_Service_Helper::$SERVICES as $service_name => $service_info ) {
336
			$connect_urls[ $service_name ] = Jetpack_Keyring_Service_Helper::connect_url( $service_name, $service_info[ 'for' ] );
337
		}
338
		return $connect_urls;
339
	}
340
341
	/**
342
	 * Returns an array of modules and settings both as first class members of the object.
343
	 *
344
	 * @param array $modules the result of an API request to get all modules.
345
	 *
346
	 * @return array flattened settings with modules.
347
	 */
348
	function get_flattened_settings( $modules ) {
349
		$core_api_endpoint = new Jetpack_Core_API_Data();
350
		$settings = $core_api_endpoint->get_all_options();
351
		return $settings->data;
352
	}
353
354
	/**
355
	 * Returns the release post content and image data as an associative array.
356
	 * This data is used to create the update modal.
357
	 */
358
	public function get_update_modal_data() {
359
		$post_data = $this->get_release_post_data();
360
361
		if ( ! isset( $post_data['posts'][0] ) ) {
362
			return;
363
		}
364
365
		$post = $post_data['posts'][0];
366
367
		if ( empty( $post['content'] ) ) {
368
			return;
369
		}
370
371
		// This allows us to embed videopress videos into the release post.
372
		add_filter( 'wp_kses_allowed_html', array( $this, 'allow_post_embed_iframe' ), 10, 2 );
373
		$content = wp_kses_post( $post['content'] );
374
		remove_filter( 'wp_kses_allowed_html', array( $this, 'allow_post_embed_iframe' ), 10, 2 );
0 ignored issues
show
Unused Code introduced by
The call to remove_filter() has too many arguments starting with 2.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
375
376
		$post_title = isset( $post['title'] ) ? $post['title'] : null;
377
		$title      = wp_kses( $post_title, array() );
378
379
		$post_thumbnail = isset( $post['post_thumbnail'] ) ? $post['post_thumbnail'] : null;
380
		if ( ! empty( $post_thumbnail ) ) {
381
			jetpack_require_lib( 'class.jetpack-photon-image' );
382
			$photon_image = new Jetpack_Photon_Image(
383
				array(
384
					'file'   => jetpack_photon_url( $post_thumbnail['URL'] ),
385
					'width'  => $post_thumbnail['width'],
386
					'height' => $post_thumbnail['height'],
387
				),
388
				$post_thumbnail['mime_type']
389
			);
390
			$photon_image->resize(
391
				array(
392
					'width'  => 600,
393
					'height' => null,
394
					'crop'   => false,
395
				)
396
			);
397
			$post_thumbnail_url = $photon_image->get_raw_filename();
398
		} else {
399
			$post_thumbnail_url = null;
400
		}
401
402
		$post_array = array(
403
			'release_post_content'        => $content,
404
			'release_post_featured_image' => $post_thumbnail_url,
405
			'release_post_title'          => $title,
406
		);
407
408
		return $post_array;
409
	}
410
411
	/**
412
	 * Temporarily allow post content to contain iframes, e.g. for videopress.
413
	 *
414
	 * @param string $tags    The tags.
415
	 * @param string $context The context.
416
	 */
417
	public function allow_post_embed_iframe( $tags, $context ) {
418
		if ( 'post' === $context ) {
419
			$tags['iframe'] = array(
420
				'src'             => true,
421
				'height'          => true,
422
				'width'           => true,
423
				'frameborder'     => true,
424
				'allowfullscreen' => true,
425
			);
426
		}
427
428
		return $tags;
429
	}
430
431
	/**
432
	 * Obtains the release post from the Jetpack release post blog. A release post will be displayed in the
433
	 * update modal when a post has a tag equal to the Jetpack version number.
434
	 *
435
	 * The response parameters for the post array can be found here:
436
	 * https://developer.wordpress.com/docs/api/1.1/get/sites/%24site/posts/%24post_ID/#apidoc-response
437
	 *
438
	 * @return array|null Returns an associative array containing the release post data at index ['posts'][0].
439
	 *                    Returns null if the release post data is not available.
440
	 */
441
	private function get_release_post_data() {
442
		if ( Constants::is_defined( 'TESTING_IN_JETPACK' ) && Constants::get_constant( 'TESTING_IN_JETPACK' ) ) {
443
			return null;
444
		}
445
446
		$release_post_src = add_query_arg(
447
			array(
448
				'order_by' => 'date',
449
				'tag'      => JETPACK__VERSION,
450
				'number'   => '1',
451
			),
452
			'https://public-api.wordpress.com/rest/v1/sites/' . JETPACK__RELEASE_POST_BLOG_SLUG . '/posts'
453
		);
454
455
		$response = wp_remote_get( $release_post_src );
456
457
		if ( ! is_array( $response ) ) {
458
			return null;
459
		}
460
461
		return json_decode( wp_remote_retrieve_body( $response ), true );
462
	}
463
}
464
465
/**
466
 * Gather data about the current user.
467
 *
468
 * @since 4.1.0
469
 *
470
 * @return array
471
 */
472
function jetpack_current_user_data() {
473
	$jetpack_connection = new Connection_Manager( 'jetpack' );
474
475
	$current_user   = wp_get_current_user();
476
	$is_master_user = $current_user->ID == Jetpack_Options::get_option( 'master_user' );
477
	$dotcom_data    = $jetpack_connection->get_connected_user_data();
478
479
	// Add connected user gravatar to the returned dotcom_data.
480
	$dotcom_data['avatar'] = ( ! empty( $dotcom_data['email'] ) ?
481
		get_avatar_url(
482
			$dotcom_data['email'],
483
			array(
484
				'size'    => 64,
485
				'default' => 'mysteryman',
486
			)
487
		)
488
		: false );
489
490
	$current_user_data = array(
491
		'isConnected' => $jetpack_connection->is_user_connected( $current_user->ID ),
492
		'isMaster'    => $is_master_user,
493
		'username'    => $current_user->user_login,
494
		'id'          => $current_user->ID,
495
		'wpcomUser'   => $dotcom_data,
496
		'gravatar'    => get_avatar_url( $current_user->ID, 64, 'mm', '', array( 'force_display' => true ) ),
497
		'permissions' => array(
498
			'admin_page'         => current_user_can( 'jetpack_admin_page' ),
499
			'connect'            => current_user_can( 'jetpack_connect' ),
500
			'connect_user'       => current_user_can( 'jetpack_connect_user' ),
501
			'disconnect'         => current_user_can( 'jetpack_disconnect' ),
502
			'manage_modules'     => current_user_can( 'jetpack_manage_modules' ),
503
			'network_admin'      => current_user_can( 'jetpack_network_admin_page' ),
504
			'network_sites_page' => current_user_can( 'jetpack_network_sites_page' ),
505
			'edit_posts'         => current_user_can( 'edit_posts' ),
506
			'publish_posts'      => current_user_can( 'publish_posts' ),
507
			'manage_options'     => current_user_can( 'manage_options' ),
508
			'view_stats'         => current_user_can( 'view_stats' ),
509
			'manage_plugins'     => current_user_can( 'install_plugins' )
510
									&& current_user_can( 'activate_plugins' )
511
									&& current_user_can( 'update_plugins' )
512
									&& current_user_can( 'delete_plugins' ),
513
		),
514
	);
515
516
	return $current_user_data;
517
}
518