PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 5.8.4
Jetpack – WP Security, Backup, Speed, & Growth v5.8.4
15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / class.jetpack-network.php
jetpack Last commit date
3rd-party 8 years ago _inc 1 year ago bin 8 years ago css 8 years ago images 1 year ago json-endpoints 3 years ago languages 8 years ago modules 1 year ago sal 8 years ago scss 8 years ago sync 8 years ago views 8 years ago .svnignore 12 years ago CODE-OF-CONDUCT.md 9 years ago changelog.txt 8 years ago class.frame-nonce-preview.php 9 years ago class.jetpack-admin.php 8 years ago class.jetpack-autoupdate.php 9 years ago class.jetpack-bbpress-json-api-compat.php 9 years ago class.jetpack-cli.php 8 years ago class.jetpack-client-server.php 8 years ago class.jetpack-client.php 8 years ago class.jetpack-connection-banner.php 8 years ago class.jetpack-constants.php 8 years ago class.jetpack-data.php 9 years ago class.jetpack-debugger.php 8 years ago class.jetpack-error.php 10 years ago class.jetpack-heartbeat.php 9 years ago class.jetpack-idc.php 8 years ago class.jetpack-ixr-client.php 10 years ago class.jetpack-jitm.php 8 years ago class.jetpack-modules-list-table.php 8 years ago class.jetpack-network-sites-list-table.php 9 years ago class.jetpack-network.php 8 years ago class.jetpack-options.php 8 years ago class.jetpack-post-images.php 8 years ago class.jetpack-signature.php 8 years ago class.jetpack-tracks.php 8 years ago class.jetpack-twitter-cards.php 8 years ago class.jetpack-user-agent.php 8 years ago class.jetpack-xmlrpc-server.php 8 years ago class.jetpack.php 8 years ago class.json-api-endpoints.php 3 years ago class.json-api.php 8 years ago class.photon.php 8 years ago composer.json 10 years ago functions.compat.php 9 years ago functions.gallery.php 8 years ago functions.global.php 8 years ago functions.opengraph.php 8 years ago functions.photon.php 9 years ago jetpack.php 1 year ago json-api-config.php 10 years ago json-endpoints.php 8 years ago locales.php 9 years ago readme.txt 1 year ago require-lib.php 8 years ago uninstall.php 8 years ago wpml-config.xml 10 years ago
class.jetpack-network.php
763 lines
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 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' );
312 */
313 Jetpack::log( 'subsiteregister' );
314
315 // If !$_GET['site_id'] stop registration and error
316 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
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 exit;
337
338 case 'subsitedisconnect':
339 Jetpack::log( 'subsitedisconnect' );
340
341 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 ) );
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
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 // better to try (and fail) to set a higher timeout than this system
405 // supports than to have register fail for more users than it should
406 $timeout = Jetpack::set_min_time_limit( 60 ) / 2;
407
408 // The blog id on WordPress.com of the primary network site
409 $network_wpcom_blog_id = Jetpack_Options::get_option( 'id' );
410
411 /*
412 * Here we need to switch to the subsite
413 * For the registration process we really only hijack how it
414 * works for an individual site and pass in some extra data here
415 */
416 switch_to_blog( $site_id );
417
418 // Save the secrets in the subsite so when the wpcom server does a pingback it
419 // will be able to validate the connection
420 $secrets = $jp->generate_secrets( 'register' );
421 if (
422 empty( $secrets['secret_1'] ) ||
423 empty( $secrets['secret_2'] ) ||
424 empty( $secrets['exp'] )
425 ) {
426 return new Jetpack_Error( 'missing_secrets' );
427 }
428
429 // Gra info for gmt offset
430 $gmt_offset = get_option( 'gmt_offset' );
431 if ( ! $gmt_offset ) {
432 $gmt_offset = 0;
433 }
434
435 /*
436 * Get the stats_option option from the db.
437 * It looks like the server strips this out so maybe it is not necessary?
438 * Does it match the Jetpack site with the old stats plugin id?
439 *
440 * @todo Find out if sending the stats_id is necessary
441 */
442 $stat_options = get_option( 'stats_options' );
443 $stat_id = $stat_options = isset( $stats_options['blog_id'] ) ? $stats_options['blog_id'] : null;
444 $user_id = get_current_user_id();
445
446 $tracks_identity = jetpack_tracks_get_identity( $user_id );
447
448 /**
449 * Both `state` and `user_id` need to be sent in the request, even though they are the same value.
450 * Connecting via the network admin combines `register()` and `authorize()` methods into one step,
451 * because we assume the main site is already authorized. `state` is used to verify the `register()`
452 * request, while `user_id()` is used to create the token in the `authorize()` request.
453 */
454 $args = array(
455 'method' => 'POST',
456 'body' => array(
457 'network_url' => $this->get_url( 'network_admin_page' ),
458 'network_wpcom_blog_id' => $network_wpcom_blog_id,
459 'siteurl' => site_url(),
460 'home' => home_url(),
461 'gmt_offset' => $gmt_offset,
462 'timezone_string' => (string) get_option( 'timezone_string' ),
463 'site_name' => (string) get_option( 'blogname' ),
464 'secret_1' => $secrets['secret_1'],
465 'secret_2' => $secrets['secret_2'],
466 'site_lang' => get_locale(),
467 'timeout' => $timeout,
468 'stats_id' => $stat_id, // Is this still required?
469 'user_id' => $user_id,
470 'state' => $user_id,
471 '_ui' => $tracks_identity['_ui'],
472 '_ut' => $tracks_identity['_ut'],
473 'jetpack_version' => JETPACK__VERSION
474 ),
475 'headers' => array(
476 'Accept' => 'application/json',
477 ),
478 'timeout' => $timeout,
479 );
480
481 Jetpack::apply_activation_source_to_args( $args['body'] );
482
483 // Attempt to retrieve shadow blog details
484 $response = Jetpack_Client::_wp_remote_request(
485 Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'subsiteregister' ) ), $args, true
486 );
487
488 /*
489 * $response should either be invalid or contain:
490 * - jetpack_id => id
491 * - jetpack_secret => blog_token
492 * - jetpack_public
493 *
494 * Store the wpcom site details
495 */
496 $valid_response = $jp->validate_remote_register_response( $response );
497
498 if ( is_wp_error( $valid_response ) || ! $valid_response ) {
499 restore_current_blog();
500 return $valid_response;
501 }
502
503 // Grab the response values to work with
504 $code = wp_remote_retrieve_response_code( $response );
505 $entity = wp_remote_retrieve_body( $response );
506 if ( $entity ) {
507 $json = json_decode( $entity );
508 } else {
509 $json = false;
510 }
511
512 if ( empty( $json->jetpack_secret ) || ! is_string( $json->jetpack_secret ) ) {
513 restore_current_blog();
514 return new Jetpack_Error( 'jetpack_secret', '', $code );
515 }
516
517 if ( isset( $json->jetpack_public ) ) {
518 $jetpack_public = (int) $json->jetpack_public;
519 } else {
520 $jetpack_public = false;
521 }
522
523 Jetpack_Options::update_options( array(
524 'id' => (int) $json->jetpack_id,
525 'blog_token' => (string) $json->jetpack_secret,
526 'public' => $jetpack_public,
527 ) );
528
529 /*
530 * Update the subsiteregister method on wpcom so that it also sends back the
531 * token in this same request
532 */
533 $is_master_user = ! Jetpack::is_active();
534 Jetpack::update_user_token(
535 get_current_user_id(),
536 sprintf( '%s.%d', $json->token->secret, get_current_user_id() ),
537 $is_master_user
538 );
539
540 Jetpack::activate_default_modules();
541
542 restore_current_blog();
543 }
544
545 /**
546 * Handles the displaying of all sites on the network that are
547 * dis/connected to Jetpack
548 *
549 * @since 2.9
550 * @see Jetpack_Network::jetpack_sites_list()
551 */
552 function network_admin_page() {
553 global $current_site;
554 $this->network_admin_page_header();
555
556 $jp = Jetpack::init();
557
558 // We should be, but ensure we are on the main blog
559 switch_to_blog( $current_site->blog_id );
560 $main_active = $jp->is_active();
561 restore_current_blog();
562
563 // If we are in dev mode, just show the notice and bail
564 if ( Jetpack::is_development_mode() ) {
565 Jetpack::show_development_mode_notice();
566 return;
567 }
568
569 /*
570 * Ensure the main blog is connected as all other subsite blog
571 * connections will feed off this one
572 */
573 if ( ! $main_active ) {
574 $url = $this->get_url( array(
575 'name' => 'subsiteregister',
576 'site_id' => 1,
577 ) );
578 $data = array( 'url' => $jp->build_connect_url() );
579 Jetpack::init()->load_view( 'admin/must-connect-main-blog.php', $data );
580
581 return;
582 }
583
584 require_once( 'class.jetpack-network-sites-list-table.php' );
585 $myListTable = new Jetpack_Network_Sites_List_Table();
586 echo '<div class="wrap"><h2>' . __( 'Sites', 'jetpack' ) . '</h2>';
587 echo '<form method="post">';
588 $myListTable->prepare_items();
589 $myListTable->display();
590 echo '</form></div>';
591
592 $this->network_admin_page_footer();
593 }
594
595 /**
596 * Stylized JP header formatting
597 *
598 * @since 2.9
599 */
600 function network_admin_page_header() {
601 global $current_user;
602
603 $is_connected = Jetpack::is_active();
604
605 $data = array(
606 'is_connected' => $is_connected
607 );
608 Jetpack::init()->load_view( 'admin/network-admin-header.php', $data );
609 }
610
611 /**
612 * Stylized JP footer formatting
613 *
614 * @since 2.9
615 */
616 function network_admin_page_footer() {
617 Jetpack::init()->load_view( 'admin/network-admin-footer.php' );
618 }
619
620 /**
621 * Fires when the Jetpack > Settings page is saved.
622 *
623 * @since 2.9
624 */
625 public function save_network_settings_page() {
626
627 if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'jetpack-network-settings' ) ) {
628 // no nonce, push back to settings page
629 wp_safe_redirect(
630 add_query_arg(
631 array( 'page' => 'jetpack-settings' ),
632 network_admin_url( 'admin.php' )
633 )
634 );
635 exit();
636 }
637
638 // try to save the Protect whitelist before anything else, since that action can result in errors
639 $whitelist = str_replace( ' ', '', $_POST['global-whitelist'] );
640 $whitelist = explode( PHP_EOL, $whitelist );
641 $result = jetpack_protect_save_whitelist( $whitelist, $global = true );
642 if ( is_wp_error( $result ) ) {
643 wp_safe_redirect(
644 add_query_arg(
645 array( 'page' => 'jetpack-settings', 'error' => 'jetpack_protect_whitelist' ),
646 network_admin_url( 'admin.php' )
647 )
648 );
649 exit();
650 }
651
652 /*
653 * Fields
654 *
655 * auto-connect - Checkbox for global Jetpack connection
656 * sub-site-connection-override - Allow sub-site admins to (dis)reconnect with their own Jetpack account
657 */
658 $auto_connect = 0;
659 if ( isset( $_POST['auto-connect'] ) ) {
660 $auto_connect = 1;
661 }
662
663 $sub_site_connection_override = 0;
664 if ( isset( $_POST['sub-site-connection-override'] ) ) {
665 $sub_site_connection_override = 1;
666 }
667
668 /* 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.
669 $manage_auto_activated_modules = 0;
670 if ( isset( $_POST['manage_auto_activated_modules'] ) ) {
671 $manage_auto_activated_modules = 1;
672 }
673
674 $modules = array();
675 if ( isset( $_POST['modules'] ) ) {
676 $modules = $_POST['modules'];
677 }
678 */
679
680 $data = array(
681 'auto-connect' => $auto_connect,
682 'sub-site-connection-override' => $sub_site_connection_override,
683 //'manage_auto_activated_modules' => $manage_auto_activated_modules,
684 //'modules' => $modules,
685 );
686
687 update_site_option( $this->settings_name, $data );
688 wp_safe_redirect(
689 add_query_arg(
690 array( 'page' => 'jetpack-settings', 'updated' => 'true' ),
691 network_admin_url( 'admin.php' )
692 )
693 );
694 exit();
695 }
696
697 public function render_network_admin_settings_page() {
698 $this->network_admin_page_header();
699 $options = wp_parse_args( get_site_option( $this->settings_name ), $this->setting_defaults );
700
701 $modules = array();
702 $module_slugs = Jetpack::get_available_modules();
703 foreach ( $module_slugs as $slug ) {
704 $module = Jetpack::get_module( $slug );
705 $module['module'] = $slug;
706 $modules[] = $module;
707 }
708
709 usort( $modules, array( 'Jetpack', 'sort_modules' ) );
710
711 if ( ! isset( $options['modules'] ) ) {
712 $options['modules'] = $modules;
713 }
714
715 $data = array(
716 'modules' => $modules,
717 'options' => $options,
718 'jetpack_protect_whitelist' => jetpack_protect_format_whitelist(),
719 );
720
721 Jetpack::init()->load_view( 'admin/network-settings.php', $data );
722 $this->network_admin_page_footer();
723 }
724
725 /**
726 * Updates a site wide option
727 *
728 * @since 2.9
729 *
730 * @param string $key
731 * @param mixed $value
732 *
733 * @return boolean
734 **/
735 public function update_option( $key, $value ) {
736 $options = get_site_option( $this->settings_name, $this->setting_defaults );
737 $options[ $key ] = $value;
738
739 return update_site_option( $this->settings_name, $options );
740 }
741
742 /**
743 * Retrieves a site wide option
744 *
745 * @since 2.9
746 *
747 * @param string $name - Name of the option in the database
748 **/
749 public function get_option( $name ) {
750 $options = get_site_option( $this->settings_name, $this->setting_defaults );
751 $options = wp_parse_args( $options, $this->setting_defaults );
752
753 if ( ! isset( $options[ $name ] ) ) {
754 $options[ $name ] = null;
755 }
756
757 return $options[ $name ];
758 }
759
760 }
761
762 // end class
763