Completed
Push — renovate/history-4.x ( 8706da...6c1ea7 )
by
unknown
17:57 queued 11:18
created

class.jetpack-network.php (2 issues)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFilename
2
/**
3
 * Jetpack Network Manager class file.
4
 *
5
 * @package jetpack
6
 */
7
8
use Automattic\Jetpack\Connection\Client;
9
use Automattic\Jetpack\Connection\Manager;
10
use Automattic\Jetpack\Connection\Utils as Connection_Utils;
11
use Automattic\Jetpack\Constants;
12
use Automattic\Jetpack\Status;
13
14
/**
15
 * Used to manage Jetpack installation on Multisite Network installs
16
 *
17
 * SINGLETON: To use call Jetpack_Network::init()
18
 *
19
 * DO NOT USE ANY STATIC METHODS IN THIS CLASS!!!!!!
20
 *
21
 * @since 2.9
22
 */
23
class Jetpack_Network {
24
25
	/**
26
	 * Holds a static copy of Jetpack_Network for the singleton
27
	 *
28
	 * @since 2.9
29
	 * @var Jetpack_Network
30
	 */
31
	private static $instance = null;
32
33
	/**
34
	 * An instance of the connection manager object.
35
	 *
36
	 * @since 7.7
37
	 * @var Automattic\Jetpack\Connection\Manager
38
	 */
39
	private $connection;
40
41
	/**
42
	 * Name of the network wide settings
43
	 *
44
	 * @since 2.9
45
	 * @var string
46
	 */
47
	private $settings_name = 'jetpack-network-settings';
48
49
	/**
50
	 * Defaults for settings found on the Jetpack > Settings page
51
	 *
52
	 * @since 2.9
53
	 * @var array
54
	 */
55
	private $setting_defaults = array(
56
		'auto-connect'                 => 0,
57
		'sub-site-connection-override' => 1,
58
	);
59
60
	/**
61
	 * Constructor
62
	 *
63
	 * @since 2.9
64
	 */
65
	private function __construct() {
66
		require_once ABSPATH . '/wp-admin/includes/plugin.php'; // For the is_plugin... check.
67
		require_once JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php'; // For managing the global whitelist.
68
69
		/**
70
		 * Sanity check to ensure the install is Multisite and we
71
		 * are in Network Admin
72
		 */
73
		if ( is_multisite() && is_network_admin() ) {
74
			add_action( 'network_admin_menu', array( $this, 'add_network_admin_menu' ) );
75
			add_action( 'network_admin_edit_jetpack-network-settings', array( $this, 'save_network_settings_page' ), 10, 0 );
76
			add_filter( 'admin_body_class', array( $this, 'body_class' ) );
77
78
			if ( isset( $_GET['page'] ) && 'jetpack' == $_GET['page'] ) {
79
				add_action( 'admin_init', array( $this, 'jetpack_sites_list' ) );
80
			}
81
		}
82
83
		/*
84
		 * Things that should only run on multisite
85
		 */
86
		if ( is_multisite() && is_plugin_active_for_network( 'jetpack/jetpack.php' ) ) {
87
			add_action( 'wp_before_admin_bar_render', array( $this, 'add_to_menubar' ) );
88
89
			/*
90
			 * If admin wants to automagically register new sites set the hook here
91
			 *
92
			 * This is a hacky way because xmlrpc is not available on wp_initialize_site
93
			 */
94
			if ( 1 === $this->get_option( 'auto-connect' ) ) {
95
				add_action( 'wp_initialize_site', array( $this, 'do_automatically_add_new_site' ) );
96
			}
97
		}
98
	}
99
100
	/**
101
	 * Sets a connection object.
102
	 *
103
	 * @param Automattic\Jetpack\Connection\Manager $connection the connection manager object.
104
	 */
105
	public function set_connection( Manager $connection ) {
106
		$this->connection = $connection;
107
	}
108
109
	/**
110
	 * Sets which modules get activated by default on subsite connection.
111
	 * Modules can be set in Network Admin > Jetpack > Settings
112
	 *
113
	 * @since 2.9
114
	 * @deprecated since 7.7.0
115
	 *
116
	 * @param array $modules List of modules.
117
	 */
118
	public function set_auto_activated_modules( $modules ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
119
		_deprecated_function( __METHOD__, 'jetpack-7.7' );
120
	}
121
122
	/**
123
	 * Registers new sites upon creation
124
	 *
125
	 * @since 2.9
126
	 * @since 7.4.0 Uses a WP_Site object.
127
	 * @uses  wp_initialize_site
128
	 *
129
	 * @param WP_Site $site the WordPress site object.
130
	 **/
131
	public function do_automatically_add_new_site( $site ) {
132
		if ( is_a( $site, 'WP_Site' ) ) {
133
			$this->do_subsiteregister( $site->id );
134
		}
135
	}
136
137
	/**
138
	 * Adds .network-admin class to the body tag
139
	 * Helps distinguish network admin JP styles from regular site JP styles
140
	 *
141
	 * @since 2.9
142
	 *
143
	 * @param String $classes current assigned body classes.
144
	 * @return String amended class string.
145
	 */
146
	public function body_class( $classes ) {
147
		return trim( $classes ) . ' network-admin ';
148
	}
149
150
	/**
151
	 * Provides access to an instance of Jetpack_Network
152
	 *
153
	 * This is how the Jetpack_Network object should *always* be accessed
154
	 *
155
	 * @since 2.9
156
	 * @return Jetpack_Network
157
	 */
158
	public static function init() {
159
		if ( ! self::$instance || ! is_a( self::$instance, 'Jetpack_Network' ) ) {
160
			self::$instance = new Jetpack_Network();
161
		}
162
163
		return self::$instance;
164
	}
165
166
	/**
167
	 * Registers the Multisite admin bar menu item shortcut.
168
	 * This shortcut helps users quickly and easily navigate to the Jetpack Network Admin
169
	 * menu from anywhere in their network.
170
	 *
171
	 * @since 2.9
172
	 */
173
	public function register_menubar() {
174
		add_action( 'wp_before_admin_bar_render', array( $this, 'add_to_menubar' ) );
175
	}
176
177
	/**
178
	 * Runs when Jetpack is deactivated from the network admin plugins menu.
179
	 * Each individual site will need to have Jetpack::disconnect called on it.
180
	 * Site that had Jetpack individually enabled will not be disconnected as
181
	 * on Multisite individually activated plugins are still activated when
182
	 * a plugin is deactivated network wide.
183
	 *
184
	 * @since 2.9
185
	 **/
186
	public function deactivate() {
187
		// Only fire if in network admin.
188
		if ( ! is_network_admin() ) {
189
			return;
190
		}
191
192
		$sites = get_sites();
193
194
		foreach ( $sites as $s ) {
195
			switch_to_blog( $s->blog_id );
196
			$active_plugins = get_option( 'active_plugins' );
197
198
			/*
199
			 * If this plugin was activated in the subsite individually
200
			 * we do not want to call disconnect. Plugins activated
201
			 * individually (before network activation) stay activated
202
			 * when the network deactivation occurs
203
			 */
204
			if ( ! in_array( 'jetpack/jetpack.php', $active_plugins, true ) ) {
205
				Jetpack::disconnect();
206
			}
207
		}
208
		restore_current_blog();
209
	}
210
211
	/**
212
	 * Adds a link to the Jetpack Network Admin page in the network admin menu bar.
213
	 *
214
	 * @since 2.9
215
	 **/
216
	public function add_to_menubar() {
217
		global $wp_admin_bar;
218
		// Don't show for logged out users or single site mode.
219
		if ( ! is_user_logged_in() || ! is_multisite() ) {
220
			return;
221
		}
222
223
		$wp_admin_bar->add_node(
224
			array(
225
				'parent' => 'network-admin',
226
				'id'     => 'network-admin-jetpack',
227
				'title'  => 'Jetpack',
228
				'href'   => $this->get_url( 'network_admin_page' ),
229
			)
230
		);
231
	}
232
233
	/**
234
	 * Returns various URL strings. Factory like
235
	 *
236
	 * $args can be a string or an array.
237
	 * If $args is an array there must be an element called name for the switch statement
238
	 *
239
	 * Currently supports:
240
	 * - subsiteregister: Pass array( 'name' => 'subsiteregister', 'site_id' => SITE_ID )
241
	 * - network_admin_page: Provides link to /wp-admin/network/JETPACK
242
	 * - subsitedisconnect: Pass array( 'name' => 'subsitedisconnect', 'site_id' => SITE_ID )
243
	 *
244
	 * @since 2.9
245
	 *
246
	 * @param Mixed $args URL parameters.
247
	 *
248
	 * @return String
249
	 **/
250
	public function get_url( $args ) {
251
		$url = null; // Default url value.
252
253
		if ( is_string( $args ) ) {
254
			$name = $args;
255
		} else if ( is_array( $args ) ) {
256
			$name = $args['name'];
257
		} else {
258
			return $url;
259
		}
260
261
		switch ( $name ) {
262
			case 'subsiteregister':
263
				if ( ! isset( $args['site_id'] ) ) {
264
					break; // If there is not a site id present we cannot go further.
265
				}
266
				$url = network_admin_url(
267
					'admin.php?page=jetpack&action=subsiteregister&site_id='
268
					. $args['site_id']
269
				);
270
				break;
271
272
			case 'network_admin_page':
273
				$url = network_admin_url( 'admin.php?page=jetpack' );
274
				break;
275
276
			case 'subsitedisconnect':
277
				if ( ! isset( $args['site_id'] ) ) {
278
					break; // If there is not a site id present we cannot go further.
279
				}
280
				$url = network_admin_url(
281
					'admin.php?page=jetpack&action=subsitedisconnect&site_id='
282
					. $args['site_id']
283
				);
284
				break;
285
		}
286
287
		return $url;
288
	}
289
290
	/**
291
	 * Adds the Jetpack  menu item to the Network Admin area
292
	 *
293
	 * @since 2.9
294
	 */
295
	public function add_network_admin_menu() {
296
		add_menu_page( 'Jetpack', 'Jetpack', 'jetpack_network_admin_page', 'jetpack', array( $this, 'wrap_network_admin_page' ), 'div', 3 );
297
		$jetpack_sites_page_hook    = add_submenu_page( 'jetpack', __( 'Jetpack Sites', 'jetpack' ), __( 'Sites', 'jetpack' ), 'jetpack_network_sites_page', 'jetpack', array( $this, 'wrap_network_admin_page' ) );
298
		$jetpack_settings_page_hook = add_submenu_page( 'jetpack', __( 'Settings', 'jetpack' ), __( 'Settings', 'jetpack' ), 'jetpack_network_settings_page', 'jetpack-settings', array( $this, 'wrap_render_network_admin_settings_page' ) );
299
		add_action( "admin_print_styles-$jetpack_sites_page_hook", array( 'Jetpack_Admin_Page', 'load_wrapper_styles' ) );
300
		add_action( "admin_print_styles-$jetpack_settings_page_hook", array( 'Jetpack_Admin_Page', 'load_wrapper_styles' ) );
301
		/**
302
		 * As jetpack_register_genericons is by default fired off a hook,
303
		 * the hook may have already fired by this point.
304
		 * So, let's just trigger it manually.
305
		 */
306
		require_once JETPACK__PLUGIN_DIR . '_inc/genericons.php';
307
		jetpack_register_genericons();
308
309 View Code Duplication
		if ( ! wp_style_is( 'jetpack-icons', 'registered' ) ) {
310
			wp_register_style( 'jetpack-icons', plugins_url( 'css/jetpack-icons.min.css', JETPACK__PLUGIN_FILE ), false, JETPACK__VERSION );
311
		}
312
313
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_menu_css' ) );
314
	}
315
316
	/**
317
	 * Adds JP menu icon
318
	 *
319
	 * @since 2.9
320
	 **/
321
	public function admin_menu_css() {
322
		wp_enqueue_style( 'jetpack-icons' );
323
	}
324
325
	/**
326
	 * Provides functionality for the Jetpack > Sites page.
327
	 * Does not do the display!
328
	 *
329
	 * @since 2.9
330
	 */
331
	public function jetpack_sites_list() {
332
		Jetpack::init();
333
334
		if ( isset( $_GET['action'] ) ) {
335
			switch ( $_GET['action'] ) {
336
				case 'subsiteregister':
337
					/**
338
					 * Add actual referrer checking.
339
					 *
340
					 * @todo check_admin_referer( 'jetpack-subsite-register' );
341
					 */
342
					Jetpack::log( 'subsiteregister' );
343
344
					// If !$_GET['site_id'] stop registration and error.
345 View Code Duplication
					if ( ! isset( $_GET['site_id'] ) || empty( $_GET['site_id'] ) ) {
346
						/**
347
						 * Log error to state cookie for display later.
348
						 *
349
						 * @todo Make state messages show on Jetpack NA pages
350
						 */
351
						Jetpack::state( 'missing_site_id', esc_html__( 'Site ID must be provided to register a sub-site.', 'jetpack' ) );
352
						break;
353
					}
354
355
					// Send data to register endpoint and retrieve shadow blog details.
356
					$result = $this->do_subsiteregister();
357
					$url    = $this->get_url( 'network_admin_page' );
358
359
					if ( is_wp_error( $result ) ) {
360
						$url = add_query_arg( 'action', 'connection_failed', $url );
361
					} else {
362
						$url = add_query_arg( 'action', 'connected', $url );
363
					}
364
365
					wp_safe_redirect( $url );
366
					exit;
367
368
				case 'subsitedisconnect':
369
					Jetpack::log( 'subsitedisconnect' );
370
371 View Code Duplication
					if ( ! isset( $_GET['site_id'] ) || empty( $_GET['site_id'] ) ) {
372
						Jetpack::state( 'missing_site_id', esc_html__( 'Site ID must be provided to disconnect a sub-site.', 'jetpack' ) );
373
						break;
374
					}
375
376
					$this->do_subsitedisconnect();
377
					break;
378
379
				case 'connected':
380
				case 'connection_failed':
381
					add_action( 'jetpack_notices', array( $this, 'show_jetpack_notice' ) );
382
					break;
383
			}
384
		}
385
	}
386
387
	/**
388
	 * Shows the Jetpack plugin notices.
389
	 */
390
	public function show_jetpack_notice() {
391
		if ( isset( $_GET['action'] ) && 'connected' == $_GET['action'] ) {
392
			$notice    = __( 'Site successfully connected.', 'jetpack' );
393
			$classname = 'updated';
394
		} elseif ( isset( $_GET['action'] ) && 'connection_failed' == $_GET['action'] ) {
395
			$notice    = __( 'Site connection failed!', 'jetpack' );
396
			$classname = 'error';
397
		}
398
		?>
399
		<div id="message" class="<?php echo esc_attr( $classname ); ?> jetpack-message jp-connect" style="display:block !important;">
400
			<p><?php echo esc_html( $notice ); ?></p>
401
		</div>
402
		<?php
403
	}
404
405
	/**
406
	 * Disconnect functionality for an individual site
407
	 *
408
	 * @since 2.9
409
	 * @see   Jetpack_Network::jetpack_sites_list()
410
	 *
411
	 * @param int $site_id the site identifier.
412
	 */
413
	public function do_subsitedisconnect( $site_id = null ) {
414
		if ( ! current_user_can( 'jetpack_disconnect' ) ) {
415
			return;
416
		}
417
		$site_id = ( is_null( $site_id ) ) ? $_GET['site_id'] : $site_id;
418
		switch_to_blog( $site_id );
419
		Jetpack::disconnect();
420
		restore_current_blog();
421
	}
422
423
	/**
424
	 * Registers a subsite with the Jetpack servers
425
	 *
426
	 * @since 2.9
427
	 * @todo  Break apart into easier to manage chunks that can be unit tested
428
	 * @see   Jetpack_Network::jetpack_sites_list();
429
	 *
430
	 * @param int $site_id the site identifier.
431
	 */
432
	public function do_subsiteregister( $site_id = null ) {
433
		if ( ! current_user_can( 'jetpack_disconnect' ) ) {
434
			return;
435
		}
436
437
		if ( ( new Status() )->is_development_mode() ) {
438
			return;
439
		}
440
441
		// Figure out what site we are working on.
442
		$site_id = ( is_null( $site_id ) ) ? $_GET['site_id'] : $site_id;
443
444
		/*
445
		 * Here we need to switch to the subsite
446
		 * For the registration process we really only hijack how it
447
		 * works for an individual site and pass in some extra data here
448
		 */
449
		switch_to_blog( $site_id );
450
451
		add_filter( 'jetpack_register_request_body', array( $this, 'filter_register_request_body' ) );
452
		add_action( 'jetpack_site_registered_user_token', array( $this, 'filter_register_user_token' ) );
453
454
		// Save the secrets in the subsite so when the wpcom server does a pingback it
455
		// will be able to validate the connection.
456
		$result = $this->connection->register( 'subsiteregister' );
457
458
		if ( is_wp_error( $result ) || ! $result ) {
459
			restore_current_blog();
460
			return $result;
461
		}
462
463
		Jetpack::activate_default_modules( false, false, array(), false );
464
465
		restore_current_blog();
466
	}
467
468
	/**
469
	 * Receives the registration response token.
470
	 *
471
	 * @param Object $token the received token.
472
	 */
473
	public function filter_register_user_token( $token ) {
474
		$is_master_user = ! Jetpack::is_active();
475
		Connection_Utils::update_user_token(
476
			get_current_user_id(),
477
			sprintf( '%s.%d', $token->secret, get_current_user_id() ),
478
			$is_master_user
479
		);
480
	}
481
482
	/**
483
	 * Filters the registration request body to include additional properties.
484
	 *
485
	 * @param Array $properties standard register request body properties.
486
	 * @return Array amended properties.
487
	 */
488
	public function filter_register_request_body( $properties ) {
489
		$blog_details = get_blog_details();
490
491
		$network = get_network();
492
493
		switch_to_blog( $network->blog_id );
494
		// The blog id on WordPress.com of the primary network site.
495
		$network_wpcom_blog_id = Jetpack_Options::get_option( 'id' );
496
		restore_current_blog();
497
498
		/**
499
		 * Both `state` and `user_id` need to be sent in the request, even though they are the same value.
500
		 * Connecting via the network admin combines `register()` and `authorize()` methods into one step,
501
		 * because we assume the main site is already authorized. `state` is used to verify the `register()`
502
		 * request, while `user_id()` is used to create the token in the `authorize()` request.
503
		 */
504
		return array_merge(
505
			$properties,
506
			array(
507
				'network_url'           => $this->get_url( 'network_admin_page' ),
508
				'network_wpcom_blog_id' => $network_wpcom_blog_id,
509
				'user_id'               => get_current_user_id(),
510
511
				/*
512
				 * Use the subsite's registration date as the site creation date.
513
				 *
514
				 * This is in contrast to regular standalone sites, where we use the helper
515
				 * `Jetpack::get_assumed_site_creation_date()` to assume the site's creation date.
516
				 */
517
				'site_created'          => $blog_details->registered,
518
			)
519
		);
520
	}
521
522
	/**
523
	 * A hook handler for adding admin pages and subpages.
524
	 */
525
	public function wrap_network_admin_page() {
526
		Jetpack_Admin_Page::wrap_ui( array( $this, 'network_admin_page' ) );
527
	}
528
529
	/**
530
	 * Handles the displaying of all sites on the network that are
531
	 * dis/connected to Jetpack
532
	 *
533
	 * @since 2.9
534
	 * @see   Jetpack_Network::jetpack_sites_list()
535
	 */
536
	public function network_admin_page() {
537
		global $current_site;
538
		$this->network_admin_page_header();
539
540
		$jp = Jetpack::init();
541
542
		// We should be, but ensure we are on the main blog.
543
		switch_to_blog( $current_site->blog_id );
544
		$main_active = $jp->is_active();
545
		restore_current_blog();
546
547
		// If we are in dev mode, just show the notice and bail.
548
		if ( ( new Status() )->is_development_mode() ) {
549
			Jetpack::show_development_mode_notice();
550
			return;
551
		}
552
553
		/*
554
		 * Ensure the main blog is connected as all other subsite blog
555
		 * connections will feed off this one
556
		 */
557
		if ( ! $main_active ) {
558
			$url  = $this->get_url(
559
				array(
560
					'name'    => 'subsiteregister',
561
					'site_id' => 1,
562
				)
563
			);
564
			$data = array( 'url' => $jp->build_connect_url() );
565
			Jetpack::init()->load_view( 'admin/must-connect-main-blog.php', $data );
566
567
			return;
568
		}
569
570
		require_once 'class.jetpack-network-sites-list-table.php';
571
572
		$network_sites_table = new Jetpack_Network_Sites_List_Table();
573
		echo '<div class="wrap"><h2>' . esc_html__( 'Sites', 'jetpack' ) . '</h2>';
574
		echo '<form method="post">';
575
		$network_sites_table->prepare_items();
576
		$network_sites_table->display();
577
		echo '</form></div>';
578
579
	}
580
581
	/**
582
	 * Stylized JP header formatting
583
	 *
584
	 * @since 2.9
585
	 */
586
	public function network_admin_page_header() {
587
		$is_connected = Jetpack::is_active();
588
589
		$data = array(
590
			'is_connected' => $is_connected,
591
		);
592
		Jetpack::init()->load_view( 'admin/network-admin-header.php', $data );
593
	}
594
595
	/**
596
	 * Fires when the Jetpack > Settings page is saved.
597
	 *
598
	 * @since 2.9
599
	 */
600
	public function save_network_settings_page() {
601
602
		if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'jetpack-network-settings' ) ) {
603
			// No nonce, push back to settings page.
604
			wp_safe_redirect(
605
				add_query_arg(
606
					array( 'page' => 'jetpack-settings' ),
607
					network_admin_url( 'admin.php' )
608
				)
609
			);
610
			exit();
611
		}
612
613
		// Try to save the Protect whitelist before anything else, since that action can result in errors.
614
		$whitelist = str_replace( ' ', '', $_POST['global-whitelist'] );
615
		$whitelist = explode( PHP_EOL, $whitelist );
616
		$result    = jetpack_protect_save_whitelist( $whitelist, true );
617
		if ( is_wp_error( $result ) ) {
618
			wp_safe_redirect(
619
				add_query_arg(
620
					array(
621
						'page'  => 'jetpack-settings',
622
						'error' => 'jetpack_protect_whitelist',
623
					),
624
					network_admin_url( 'admin.php' )
625
				)
626
			);
627
			exit();
628
		}
629
630
		/*
631
		 * Fields
632
		 *
633
		 * auto-connect - Checkbox for global Jetpack connection
634
		 * sub-site-connection-override - Allow sub-site admins to (dis)reconnect with their own Jetpack account
635
		 */
636
		$auto_connect = 0;
637
		if ( isset( $_POST['auto-connect'] ) ) {
638
			$auto_connect = 1;
639
		}
640
641
		$sub_site_connection_override = 0;
642
		if ( isset( $_POST['sub-site-connection-override'] ) ) {
643
			$sub_site_connection_override = 1;
644
		}
645
646
		$data = array(
647
			'auto-connect'                 => $auto_connect,
648
			'sub-site-connection-override' => $sub_site_connection_override,
649
		);
650
651
		update_site_option( $this->settings_name, $data );
652
		wp_safe_redirect(
653
			add_query_arg(
654
				array(
655
					'page'    => 'jetpack-settings',
656
					'updated' => 'true',
657
				),
658
				network_admin_url( 'admin.php' )
659
			)
660
		);
661
		exit();
662
	}
663
664
	/**
665
	 * A hook handler for adding admin pages and subpages.
666
	 */
667
	public function wrap_render_network_admin_settings_page() {
668
		Jetpack_Admin_Page::wrap_ui( array( $this, 'render_network_admin_settings_page' ) );
669
	}
670
671
	/**
672
	 * A hook rendering the admin settings page.
673
	 */
674
	public function render_network_admin_settings_page() {
675
		$this->network_admin_page_header();
676
		$options = wp_parse_args( get_site_option( $this->settings_name ), $this->setting_defaults );
0 ignored issues
show
$this->setting_defaults is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
677
678
		$modules      = array();
679
		$module_slugs = Jetpack::get_available_modules();
680
		foreach ( $module_slugs as $slug ) {
681
			$module           = Jetpack::get_module( $slug );
682
			$module['module'] = $slug;
683
			$modules[]        = $module;
684
		}
685
686
		usort( $modules, array( 'Jetpack', 'sort_modules' ) );
687
688
		if ( ! isset( $options['modules'] ) ) {
689
			$options['modules'] = $modules;
690
		}
691
692
		$data = array(
693
			'modules'                   => $modules,
694
			'options'                   => $options,
695
			'jetpack_protect_whitelist' => jetpack_protect_format_whitelist(),
696
		);
697
698
		Jetpack::init()->load_view( 'admin/network-settings.php', $data );
699
	}
700
701
	/**
702
	 * Updates a site wide option
703
	 *
704
	 * @since 2.9
705
	 *
706
	 * @param string $key option name.
707
	 * @param mixed  $value option value.
708
	 *
709
	 * @return boolean
710
	 **/
711
	public function update_option( $key, $value ) {
712
		$options         = get_site_option( $this->settings_name, $this->setting_defaults );
713
		$options[ $key ] = $value;
714
715
		return update_site_option( $this->settings_name, $options );
716
	}
717
718
	/**
719
	 * Retrieves a site wide option
720
	 *
721
	 * @since 2.9
722
	 *
723
	 * @param string $name - Name of the option in the database.
724
	 **/
725
	public function get_option( $name ) {
726
		$options = get_site_option( $this->settings_name, $this->setting_defaults );
727
		$options = wp_parse_args( $options, $this->setting_defaults );
0 ignored issues
show
$this->setting_defaults is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
728
729
		if ( ! isset( $options[ $name ] ) ) {
730
			$options[ $name ] = null;
731
		}
732
733
		return $options[ $name ];
734
	}
735
}
736