Completed
Push — branch-5.2-built ( 5c2571...11dc00 )
by
unknown
12:42 queued 04:03
created

Jetpack_Network   D

Complexity

Total Complexity 82

Size/Duplication

Total Lines 741
Duplicated Lines 3.51 %

Coupling/Cohesion

Components 2
Dependencies 5

Importance

Changes 0
Metric Value
dl 26
loc 741
rs 4.4444
c 0
b 0
f 0
wmc 82
lcom 2
cbo 5

22 Methods

Rating   Name   Duplication   Size   Complexity  
C __construct() 0 36 8
A set_auto_activated_modules() 0 11 1
A do_automatically_add_new_site() 0 3 1
A body_class() 0 3 1
A init() 0 7 3
A register_menubar() 0 3 1
B deactivate() 0 24 4
A add_to_menubar() 0 14 3
C get_url() 0 37 7
A add_network_admin_menu() 3 19 2
A admin_menu_css() 0 3 1
C jetpack_sites_list() 12 52 11
B show_jetpack_notice() 0 9 5
A do_subsitedisconnect() 0 9 3
D do_subsiteregister() 11 146 15
B network_admin_page() 0 42 3
A network_admin_page_header() 0 10 1
A network_admin_page_footer() 0 3 1
B save_network_settings_page() 0 71 5
B render_network_admin_settings_page() 0 27 3
A update_option() 0 6 1
A get_option() 0 10 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Jetpack_Network often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Jetpack_Network, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Used to manage Jetpack installation on Multisite Network installs
5
 *
6
 * SINGLETON: To use call Jetpack_Network::init()
7
 *
8
 * DO NOT USE ANY STATIC METHODS IN THIS CLASS!!!!!!
9
 *
10
 * @since 2.9
11
 */
12
class Jetpack_Network {
13
14
	/**
15
	 * Holds a static copy of Jetpack_Network for the singleton
16
	 *
17
	 * @since 2.9
18
	 * @var Jetpack_Network
19
	 */
20
	private static $instance = null;
21
22
	/**
23
	 * Name of the network wide settings
24
	 *
25
	 * @since 2.9
26
	 * @var string
27
	 */
28
	private $settings_name = 'jetpack-network-settings';
29
30
	/**
31
	 * Defaults for settings found on the Jetpack > Settings page
32
	 *
33
	 * @since 2.9
34
	 * @var array
35
	 */
36
	private $setting_defaults = array(
37
		'auto-connect'                  => 0,
38
		'sub-site-connection-override'  => 1,
39
		//'manage_auto_activated_modules' => 0,
40
	);
41
42
	/**
43
	 * Constructor
44
	 *
45
	 * @since 2.9
46
	 */
47
	private function __construct() {
48
		require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); // For the is_plugin... check
49
		require_once( JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php' ); // For managing the global whitelist
50
		/*
51
		 * Sanity check to ensure the install is Multisite and we
52
		 * are in Network Admin
53
		 */
54
		if ( is_multisite() && is_network_admin() ) {
55
			add_action( 'network_admin_menu', array( $this, 'add_network_admin_menu' ) );
56
			add_action( 'network_admin_edit_jetpack-network-settings', array( $this, 'save_network_settings_page' ), 10, 0 );
57
			add_filter( 'admin_body_class', array( $this, 'body_class' ) );
58
59
			if ( isset( $_GET['page'] ) && 'jetpack' == $_GET['page'] ) {
60
				add_action( 'admin_init', array( $this, 'jetpack_sites_list' ) );
61
			}
62
		}
63
64
		/*
65
		 * Things that should only run on multisite
66
		 */
67
		if ( is_multisite() && is_plugin_active_for_network( 'jetpack/jetpack.php' ) ) {
68
			add_action( 'wp_before_admin_bar_render', array( $this, 'add_to_menubar' ) );
69
70
			/*
71
			 * If admin wants to automagically register new sites set the hook here
72
			 *
73
			 * This is a hacky way because xmlrpc is not available on wpmu_new_blog
74
			 */
75
			if ( $this->get_option( 'auto-connect' ) == 1 ) {
76
				add_action( 'wpmu_new_blog', array( $this, 'do_automatically_add_new_site' ) );
77
			}
78
		}
79
80
		// Remove the toggles for 2.9, re-evaluate how they're done and added for a 3.0 release. They don't feel quite right yet.
81
		// add_filter( 'jetpack_get_default_modules', array( $this, 'set_auto_activated_modules' ) );
82
	}
83
84
	/**
85
	 * Sets which modules get activated by default on subsite connection.
86
	 * Modules can be set in Network Admin > Jetpack > Settings
87
	 *
88
	 * @since 2.9
89
	 *
90
	 * @param array $modules
91
	 *
92
	 * @return array
93
	 **/
94
	public function set_auto_activated_modules( $modules ) {
95
		return $modules;
96
97
		/* Remove the toggles for 2.9, re-evaluate how they're done and added for a 3.0 release. They don't feel quite right yet.
98
		if( 1 == $this->get_option( 'manage_auto_activated_modules' ) ) {
99
			return (array) $this->get_option( 'modules' );
100
		} else {
101
			return $modules;
102
		}
103
		*/
104
	}
105
106
	/**
107
	 * Registers new sites upon creation
108
	 *
109
	 * @since 2.9
110
	 * @uses  wpmu_new_blog
111
	 *
112
	 * @param int $blog_id
113
	 **/
114
	public function do_automatically_add_new_site( $blog_id ) {
115
		$this->do_subsiteregister( $blog_id );
116
	}
117
118
	/**
119
	 * Adds .network-admin class to the body tag
120
	 * Helps distinguish network admin JP styles from regular site JP styles
121
	 *
122
	 * @since 2.9
123
	 */
124
	public function body_class( $classes ) {
125
		return trim( $classes ) . ' network-admin ';
126
	}
127
128
	/**
129
	 * Provides access to an instance of Jetpack_Network
130
	 *
131
	 * This is how the Jetpack_Network object should *always* be accessed
132
	 *
133
	 * @since 2.9
134
	 * @return Jetpack_Network
135
	 */
136
	public static function init() {
137
		if ( ! self::$instance || ! is_a( self::$instance, 'Jetpack_Network' ) ) {
138
			self::$instance = new Jetpack_Network;
139
		}
140
141
		return self::$instance;
142
	}
143
144
	/**
145
	 * Registers the Multisite admin bar menu item shortcut.
146
	 * This shortcut helps users quickly and easily navigate to the Jetpack Network Admin
147
	 * menu from anywhere in their network.
148
	 *
149
	 * @since 2.9
150
	 */
151
	public function register_menubar() {
152
		add_action( 'wp_before_admin_bar_render', array( $this, 'add_to_menubar' ) );
153
	}
154
155
	/**
156
	 * Runs when Jetpack is deactivated from the network admin plugins menu.
157
	 * Each individual site will need to have Jetpack::disconnect called on it.
158
	 * Site that had Jetpack individually enabled will not be disconnected as
159
	 * on Multisite individually activated plugins are still activated when
160
	 * a plugin is deactivated network wide.
161
	 *
162
	 * @since 2.9
163
	 **/
164
	public function deactivate() {
165
		// Only fire if in network admin
166
		if ( ! is_network_admin() ) {
167
			return;
168
		}
169
170
		$sites = get_sites();
171
172
		foreach ( $sites as $s ) {
173
			switch_to_blog( $s->blog_id );
174
			$active_plugins = get_option( 'active_plugins' );
175
176
			/*
177
			 * If this plugin was activated in the subsite individually
178
			 * we do not want to call disconnect. Plugins activated
179
		 	 * individually (before network activation) stay activated
180
		 	 * when the network deactivation occurs
181
		 	 */
182
			if ( ! in_array( 'jetpack/jetpack.php', $active_plugins ) ) {
183
				Jetpack::disconnect();
184
			}
185
		}
186
		restore_current_blog();
187
	}
188
189
	/**
190
	 * Adds a link to the Jetpack Network Admin page in the network admin menu bar.
191
	 *
192
	 * @since 2.9
193
	 **/
194
	public function add_to_menubar() {
195
		global $wp_admin_bar;
196
		// Don't show for logged out users or single site mode.
197
		if ( ! is_user_logged_in() || ! is_multisite() ) {
198
			return;
199
		}
200
201
		$wp_admin_bar->add_node( array(
202
			'parent' => 'network-admin',
203
			'id'     => 'network-admin-jetpack',
204
			'title'  => __( 'Jetpack', 'jetpack' ),
205
			'href'   => $this->get_url( 'network_admin_page' ),
206
		) );
207
	}
208
209
	/**
210
	 * Returns various URL strings. Factory like
211
	 *
212
	 * $args can be a string or an array.
213
	 * If $args is an array there must be an element called name for the switch statement
214
	 *
215
	 * Currently supports:
216
	 * - subsiteregister: Pass array( 'name' => 'subsiteregister', 'site_id' => SITE_ID )
217
	 * - network_admin_page: Provides link to /wp-admin/network/JETPACK
218
	 * - subsitedisconnect: Pass array( 'name' => 'subsitedisconnect', 'site_id' => SITE_ID )
219
	 *
220
	 * @since 2.9
221
	 *
222
	 * @param Mixed $args
223
	 *
224
	 * @return String
225
	 **/
226
	public function get_url( $args ) {
227
		$url = null; // Default url value
228
229
		if ( is_string( $args ) ) {
230
			$name = $args;
231
		} else {
232
			$name = $args['name'];
233
		}
234
235
		switch ( $name ) {
236
			case 'subsiteregister':
237
				if ( ! isset( $args['site_id'] ) ) {
238
					break; // If there is not a site id present we cannot go further
239
				}
240
				$url = network_admin_url(
241
					'admin.php?page=jetpack&action=subsiteregister&site_id='
242
					. $args['site_id']
243
				);
244
				break;
245
246
			case 'network_admin_page':
247
				$url = network_admin_url( 'admin.php?page=jetpack' );
248
				break;
249
250
			case 'subsitedisconnect':
251
				if ( ! isset( $args['site_id'] ) ) {
252
					break; // If there is not a site id present we cannot go further
253
				}
254
				$url = network_admin_url(
255
					'admin.php?page=jetpack&action=subsitedisconnect&site_id='
256
					. $args['site_id']
257
				);
258
				break;
259
		}
260
261
		return $url;
262
	}
263
264
	/**
265
	 * Adds the Jetpack  menu item to the Network Admin area
266
	 *
267
	 * @since 2.9
268
	 */
269
	public function add_network_admin_menu() {
270
		add_menu_page( __( 'Jetpack', 'jetpack' ), __( 'Jetpack', 'jetpack' ), 'jetpack_network_admin_page', 'jetpack', array( $this, 'network_admin_page' ), 'div', 3 );
271
		add_submenu_page( 'jetpack', __( 'Jetpack Sites', 'jetpack' ), __( 'Sites', 'jetpack' ), 'jetpack_network_sites_page', 'jetpack', array( $this, 'network_admin_page' ) );
272
		add_submenu_page( 'jetpack', __( 'Settings', 'jetpack' ), __( 'Settings', 'jetpack' ), 'jetpack_network_settings_page', 'jetpack-settings', array( $this, 'render_network_admin_settings_page' ) );
273
274
		/**
275
		 * As jetpack_register_genericons is by default fired off a hook,
276
		 * the hook may have already fired by this point.
277
		 * So, let's just trigger it manually.
278
		 */
279
		require_once( JETPACK__PLUGIN_DIR . '_inc/genericons.php' );
280
		jetpack_register_genericons();
281
282 View Code Duplication
		if ( ! wp_style_is( 'jetpack-icons', 'registered' ) ) {
283
			wp_register_style( 'jetpack-icons', plugins_url( 'css/jetpack-icons.min.css', JETPACK__PLUGIN_FILE ), false, JETPACK__VERSION );
284
		}
285
286
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_menu_css' ) );
287
	}
288
289
	/**
290
	 * Adds JP menu icon
291
	 *
292
	 * @since 2.9
293
	 **/
294
	function admin_menu_css() {
295
		wp_enqueue_style( 'jetpack-icons' );
296
	}
297
298
	/**
299
	 * Provides functionality for the Jetpack > Sites page.
300
	 * Does not do the display!
301
	 *
302
	 * @since 2.9
303
	 */
304
	public function jetpack_sites_list() {
305
		Jetpack::init();
306
307
		if ( isset( $_GET['action'] ) ) {
308
			switch ( $_GET['action'] ) {
309
				case 'subsiteregister':
310
					/*
311
					 * @todo check_admin_referer( 'jetpack-subsite-register' );
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
312
					 */
313
					Jetpack::log( 'subsiteregister' );
314
315
					// If !$_GET['site_id'] stop registration and error
316 View Code Duplication
					if ( ! isset( $_GET['site_id'] ) || empty( $_GET['site_id'] ) ) {
317
						// Log error to state cookie for display later
318
						/**
319
						 * @todo Make state messages show on Jetpack NA pages
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
320
						 **/
321
						Jetpack::state( 'missing_site_id', esc_html__( 'Site ID must be provided to register a sub-site.', 'jetpack' ) );
322
						break;
323
					}
324
325
					// Send data to register endpoint and retrieve shadow blog details
326
					$result = $this->do_subsiteregister();
327
					$url    = $this->get_url( 'network_admin_page' );
328
329
					if ( is_wp_error( $result ) ) {
330
						$url = add_query_arg( 'action', 'connection_failed', $url );
331
					} else {
332
						$url = add_query_arg( 'action', 'connected', $url );
333
					}
334
335
					wp_safe_redirect( $url );
336
					break;
337
338
				case 'subsitedisconnect':
339
					Jetpack::log( 'subsitedisconnect' );
340
341 View Code Duplication
					if ( ! isset( $_GET['site_id'] ) || empty( $_GET['site_id'] ) ) {
342
						Jetpack::state( 'missing_site_id', esc_html__( 'Site ID must be provided to disconnect a sub-site.', 'jetpack' ) );
343
						break;
344
					}
345
346
					$this->do_subsitedisconnect();
347
					break;
348
349
				case 'connected':
350
				case 'connection_failed':
351
					add_action( 'jetpack_notices', array( $this, 'show_jetpack_notice' ) );
352
					break;
353
			}
354
		}
355
	}
356
357
	public function show_jetpack_notice() {
358
		if ( isset( $_GET['action'] ) && 'connected' == $_GET['action'] ) {
359
			$notice = __( 'Site successfully connected.', 'jetpack' );
360
		} else if ( isset( $_GET['action'] ) && 'connection_failed' == $_GET['action'] ) {
361
			$notice = __( 'Site connection <strong>failed</strong>', 'jetpack' );
362
		}
363
364
		Jetpack::init()->load_view( 'admin/network-admin-alert.php', array( 'notice' => $notice ) );
0 ignored issues
show
Bug introduced by
The variable $notice does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
365
	}
366
367
	/**
368
	 * Disconnect functionality for an individual site
369
	 *
370
	 * @since 2.9
371
	 * @see   Jetpack_Network::jetpack_sites_list()
372
	 */
373
	public function do_subsitedisconnect( $site_id = null ) {
374
		if ( ! current_user_can( 'jetpack_disconnect' ) ) {
375
			return;
376
		}
377
		$site_id = ( is_null( $site_id ) ) ? $_GET['site_id'] : $site_id;
378
		switch_to_blog( $site_id );
379
		Jetpack::disconnect();
380
		restore_current_blog();
381
	}
382
383
	/**
384
	 * Registers a subsite with the Jetpack servers
385
	 *
386
	 * @since 2.9
387
	 * @todo  Break apart into easier to manage chunks that can be unit tested
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
388
	 * @see   Jetpack_Network::jetpack_sites_list();
389
	 */
390
	public function do_subsiteregister( $site_id = null ) {
391
		if ( ! current_user_can( 'jetpack_disconnect' ) ) {
392
			return;
393
		}
394
395
		if ( Jetpack::is_development_mode() ) {
396
			return;
397
		}
398
399
		$jp = Jetpack::init();
400
401
		// Figure out what site we are working on
402
		$site_id = ( is_null( $site_id ) ) ? $_GET['site_id'] : $site_id;
403
404
		// Remote query timeout limit
405
		$timeout = $jp->get_remote_query_timeout_limit();
406
407
		// The blog id on WordPress.com of the primary network site
408
		$network_wpcom_blog_id = Jetpack_Options::get_option( 'id' );
409
410
		/*
411
		 * Here we need to switch to the subsite
412
		 * For the registration process we really only hijack how it
413
		 * works for an individual site and pass in some extra data here
414
		 */
415
		switch_to_blog( $site_id );
416
417
		// Save the secrets in the subsite so when the wpcom server does a pingback it
418
		// will be able to validate the connection
419
		$secrets = $jp->generate_secrets( 'register' );
420 View Code Duplication
		if (
421
			empty( $secrets['secret_1'] ) ||
422
			empty( $secrets['secret_2']  ) ||
423
			empty( $secrets['exp'] )
424
		) {
425
			return new Jetpack_Error( 'missing_secrets' );
426
		}
427
428
		// Gra info for gmt offset
429
		$gmt_offset = get_option( 'gmt_offset' );
430
		if ( ! $gmt_offset ) {
431
			$gmt_offset = 0;
432
		}
433
434
		/*
435
		 * Get the stats_option option from the db.
436
		 * It looks like the server strips this out so maybe it is not necessary?
437
		 * Does it match the Jetpack site with the old stats plugin id?
438
		 *
439
		 * @todo Find out if sending the stats_id is necessary
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
440
		 */
441
		$stat_options = get_option( 'stats_options' );
0 ignored issues
show
Unused Code introduced by
$stat_options is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
442
		$stat_id = $stat_options = isset( $stats_options['blog_id'] ) ? $stats_options['blog_id'] : null;
0 ignored issues
show
Bug introduced by
The variable $stats_options does not exist. Did you mean $stat_options?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
Unused Code introduced by
$stat_options is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
443
		$user_id = get_current_user_id();
444
445
		/**
446
		 * Both `state` and `user_id` need to be sent in the request, even though they are the same value.
447
		 * Connecting via the network admin combines `register()` and `authorize()` methods into one step,
448
		 * because we assume the main site is already authorized. `state` is used to verify the `register()`
449
		 * request, while `user_id()` is used to create the token in the `authorize()` request.
450
		 */
451
		$args = array(
452
			'method'  => 'POST',
453
			'body'    => array(
454
				'network_url'           => $this->get_url( 'network_admin_page' ),
455
				'network_wpcom_blog_id' => $network_wpcom_blog_id,
456
				'siteurl'               => site_url(),
457
				'home'                  => home_url(),
458
				'gmt_offset'            => $gmt_offset,
459
				'timezone_string'       => (string) get_option( 'timezone_string' ),
460
				'site_name'             => (string) get_option( 'blogname' ),
461
				'secret_1'              => $secrets['secret_1'],
462
				'secret_2'              => $secrets['secret_2'],
463
				'site_lang'             => get_locale(),
464
				'timeout'               => $timeout,
465
				'stats_id'              => $stat_id, // Is this still required?
466
				'user_id'               => $user_id,
467
				'state'                 => $user_id
468
			),
469
			'headers' => array(
470
				'Accept' => 'application/json',
471
			),
472
			'timeout' => $timeout,
473
		);
474
475
		// Attempt to retrieve shadow blog details
476
		$response = Jetpack_Client::_wp_remote_request(
477
			Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'subsiteregister' ) ), $args, true
478
		);
479
480
		/*
481
		 * $response should either be invalid or contain:
482
		 * - jetpack_id	=> id
483
		 * - jetpack_secret => blog_token
484
		 * - jetpack_public
485
		 *
486
		 * Store the wpcom site details
487
		 */
488
		$valid_response = $jp->validate_remote_register_response( $response );
489
490
		if ( is_wp_error( $valid_response ) || ! $valid_response ) {
491
			restore_current_blog();
492
			return $valid_response;
493
		}
494
495
		// Grab the response values to work with
496
		$code   = wp_remote_retrieve_response_code( $response );
497
		$entity = wp_remote_retrieve_body( $response );
498
		if ( $entity ) {
499
			$json = json_decode( $entity );
500
		} else {
501
			$json = false;
502
		}
503
504 View Code Duplication
		if ( empty( $json->jetpack_secret ) || ! is_string( $json->jetpack_secret ) ) {
505
			restore_current_blog();
506
			return new Jetpack_Error( 'jetpack_secret', '', $code );
507
		}
508
509
		if ( isset( $json->jetpack_public ) ) {
510
			$jetpack_public = (int) $json->jetpack_public;
511
		} else {
512
			$jetpack_public = false;
513
		}
514
515
		Jetpack_Options::update_options( array(
516
			'id'         => (int) $json->jetpack_id,
517
			'blog_token' => (string) $json->jetpack_secret,
518
			'public'     => $jetpack_public,
519
		) );
520
521
		/*
522
		 * Update the subsiteregister method on wpcom so that it also sends back the
523
		 * token in this same request
524
		 */
525
		$is_master_user = ! Jetpack::is_active();
526
		Jetpack::update_user_token(
527
			get_current_user_id(),
528
			sprintf( '%s.%d', $json->token->secret, get_current_user_id() ),
529
			$is_master_user
530
		);
531
532
		Jetpack::activate_default_modules();
533
534
		restore_current_blog();
535
	}
536
537
	/**
538
	 * Handles the displaying of all sites on the network that are
539
	 * dis/connected to Jetpack
540
	 *
541
	 * @since 2.9
542
	 * @see   Jetpack_Network::jetpack_sites_list()
543
	 */
544
	function network_admin_page() {
545
		global $current_site;
546
		$this->network_admin_page_header();
547
548
		$jp = Jetpack::init();
549
550
		// We should be, but ensure we are on the main blog
551
		switch_to_blog( $current_site->blog_id );
552
		$main_active = $jp->is_active();
553
		restore_current_blog();
554
555
		// If we are in dev mode, just show the notice and bail
556
		if ( Jetpack::is_development_mode() ) {
557
			Jetpack::show_development_mode_notice();
558
			return;
559
		}
560
561
		/*
562
		 * Ensure the main blog is connected as all other subsite blog
563
		 * connections will feed off this one
564
		 */
565
		if ( ! $main_active ) {
566
			$url  = $this->get_url( array(
0 ignored issues
show
Unused Code introduced by
$url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
567
				'name'    => 'subsiteregister',
568
				'site_id' => 1,
569
			) );
570
			$data = array( 'url' => $jp->build_connect_url() );
571
			Jetpack::init()->load_view( 'admin/must-connect-main-blog.php', $data );
572
573
			return;
574
		}
575
576
		require_once( 'class.jetpack-network-sites-list-table.php' );
577
		$myListTable = new Jetpack_Network_Sites_List_Table();
578
		echo '<div class="wrap"><h2>' . __( 'Sites', 'jetpack' ) . '</h2>';
579
		echo '<form method="post">';
580
		$myListTable->prepare_items();
581
		$myListTable->display();
582
		echo '</form></div>';
583
584
		$this->network_admin_page_footer();
585
	}
586
587
	/**
588
	 * Stylized JP header formatting
589
	 *
590
	 * @since 2.9
591
	 */
592
	function network_admin_page_header() {
593
		global $current_user;
594
595
		$is_connected = Jetpack::is_active();
596
597
		$data = array(
598
			'is_connected' => $is_connected
599
		);
600
		Jetpack::init()->load_view( 'admin/network-admin-header.php', $data );
601
	}
602
603
	/**
604
	 * Stylized JP footer formatting
605
	 *
606
	 * @since 2.9
607
	 */
608
	function network_admin_page_footer() {
609
		Jetpack::init()->load_view( 'admin/network-admin-footer.php' );
610
	}
611
612
	/**
613
	 * Fires when the Jetpack > Settings page is saved.
614
	 *
615
	 * @since 2.9
616
	 */
617
	public function save_network_settings_page() {
618
619
		if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'jetpack-network-settings' ) ) {
620
			// no nonce, push back to settings page
621
			wp_safe_redirect(
622
				add_query_arg(
623
					array( 'page' => 'jetpack-settings' ),
624
					network_admin_url( 'admin.php' )
625
				)
626
			);
627
			exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method save_network_settings_page() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
628
		}
629
630
		// try to save the Protect whitelist before anything else, since that action can result in errors
631
		$whitelist = str_replace( ' ', '', $_POST['global-whitelist'] );
632
		$whitelist = explode( PHP_EOL, $whitelist );
633
		$result    = jetpack_protect_save_whitelist( $whitelist, $global = true );
634
		if ( is_wp_error( $result ) ) {
635
			wp_safe_redirect(
636
				add_query_arg(
637
					array( 'page' => 'jetpack-settings', 'error' => 'jetpack_protect_whitelist' ),
638
					network_admin_url( 'admin.php' )
639
				)
640
			);
641
			exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method save_network_settings_page() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
642
		}
643
644
		/*
645
		 * Fields
646
		 *
647
		 * auto-connect - Checkbox for global Jetpack connection
648
		 * sub-site-connection-override - Allow sub-site admins to (dis)reconnect with their own Jetpack account
649
		 */
650
		$auto_connect = 0;
651
		if ( isset( $_POST['auto-connect'] ) ) {
652
			$auto_connect = 1;
653
		}
654
655
		$sub_site_connection_override = 0;
656
		if ( isset( $_POST['sub-site-connection-override'] ) ) {
657
			$sub_site_connection_override = 1;
658
		}
659
660
		/* Remove the toggles for 2.9, re-evaluate how they're done and added for a 3.0 release. They don't feel quite right yet.
661
		$manage_auto_activated_modules = 0;
662
		if ( isset( $_POST['manage_auto_activated_modules'] ) ) {
663
			$manage_auto_activated_modules = 1;
664
		}
665
666
		$modules = array();
667
		if ( isset( $_POST['modules'] ) ) {
668
			$modules = $_POST['modules'];
669
		}
670
		*/
671
672
		$data = array(
673
			'auto-connect'                  => $auto_connect,
674
			'sub-site-connection-override'  => $sub_site_connection_override,
675
			//'manage_auto_activated_modules' => $manage_auto_activated_modules,
676
			//'modules'                       => $modules,
677
		);
678
679
		update_site_option( $this->settings_name, $data );
680
		wp_safe_redirect(
681
			add_query_arg(
682
				array( 'page' => 'jetpack-settings', 'updated' => 'true' ),
683
				network_admin_url( 'admin.php' )
684
			)
685
		);
686
		exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method save_network_settings_page() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
687
	}
688
689
	public function render_network_admin_settings_page() {
690
		$this->network_admin_page_header();
691
		$options = wp_parse_args( get_site_option( $this->settings_name ), $this->setting_defaults );
692
693
		$modules = array();
694
		$module_slugs = Jetpack::get_available_modules();
695
		foreach ( $module_slugs as $slug ) {
696
			$module           = Jetpack::get_module( $slug );
697
			$module['module'] = $slug;
698
			$modules[]        = $module;
699
		}
700
701
		usort( $modules, array( 'Jetpack', 'sort_modules' ) );
702
703
		if ( ! isset( $options['modules'] ) ) {
704
			$options['modules'] = $modules;
705
		}
706
707
		$data = array(
708
			'modules' => $modules,
709
			'options' => $options,
710
			'jetpack_protect_whitelist' => jetpack_protect_format_whitelist(),
711
		);
712
713
		Jetpack::init()->load_view( 'admin/network-settings.php', $data );
714
		$this->network_admin_page_footer();
715
	}
716
717
	/**
718
	 * Updates a site wide option
719
	 *
720
	 * @since 2.9
721
	 *
722
	 * @param string $key
723
	 * @param mixed  $value
724
	 *
725
	 * @return boolean
726
	 **/
727
	public function update_option( $key, $value ) {
728
		$options  = get_site_option( $this->settings_name, $this->setting_defaults );
729
		$options[ $key ] = $value;
730
731
		return update_site_option( $this->settings_name, $options );
732
	}
733
734
	/**
735
	 * Retrieves a site wide option
736
	 *
737
	 * @since 2.9
738
	 *
739
	 * @param string $name - Name of the option in the database
740
	 **/
741
	public function get_option( $name ) {
742
		$options = get_site_option( $this->settings_name, $this->setting_defaults );
743
		$options = wp_parse_args( $options, $this->setting_defaults );
744
745
		if ( ! isset( $options[ $name ] ) ) {
746
			$options[ $name ] = null;
747
		}
748
749
		return $options[ $name ];
750
	}
751
752
}
753
754
// end class
755