PageRenderTime 55ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/jetpack/class.jetpack-network.php

https://gitlab.com/Gashler/sg
PHP | 773 lines | 388 code | 110 blank | 275 comment | 62 complexity | dabeffe4c02650c7703111c4372365d8 MD5 | raw file
  1. <?php
  2. /**
  3. * Used to manage Jetpack installation on Multisite Network installs
  4. *
  5. * SINGLETON: To use call Jetpack_Network::init()
  6. *
  7. * DO NOT USE ANY STATIC METHODS IN THIS CLASS!!!!!!
  8. *
  9. * @since 2.9
  10. */
  11. class Jetpack_Network {
  12. /**
  13. * Holds a static copy of Jetpack_Network for the singleton
  14. *
  15. * @since 2.9
  16. * @var Jetpack_Network
  17. */
  18. private static $instance = null;
  19. /**
  20. * Name of the network wide settings
  21. *
  22. * @since 2.9
  23. * @var string
  24. */
  25. private $settings_name = 'jetpack-network-settings';
  26. /**
  27. * Defaults for settings found on the Jetpack > Settings page
  28. *
  29. * @since 2.9
  30. * @var array
  31. */
  32. private $setting_defaults = array(
  33. 'auto-connect' => 0,
  34. 'sub-site-connection-override' => 1,
  35. // 'manage_auto_activated_modules' => 0,
  36. );
  37. /**
  38. * Constructor
  39. *
  40. * @since 2.9
  41. */
  42. private function __construct() {
  43. require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); // For the is_plugin... check
  44. require_once( JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php' ); // For managing the global whitelist
  45. /*
  46. * Sanity check to ensure the install is Multisite and we
  47. * are in Network Admin
  48. */
  49. if (is_multisite() && is_network_admin()) {
  50. add_action('network_admin_menu', array($this, 'add_network_admin_menu'));
  51. add_action('network_admin_edit_jetpack-network-settings', array($this, 'save_network_settings_page'), 10, 0);
  52. add_filter( 'admin_body_class', array( $this, 'body_class' ) );
  53. if( isset( $_GET['page'] ) && 'jetpack' == $_GET['page'] ) {
  54. add_action( 'admin_init', array ( $this, 'jetpack_sites_list' ) );
  55. }
  56. }
  57. /*
  58. * Things that should only run on multisite
  59. */
  60. if( is_multisite() && is_plugin_active_for_network( 'jetpack/jetpack.php' ) ) {
  61. add_action( 'wp_before_admin_bar_render', array( $this, 'add_to_menubar' ) );
  62. /*
  63. * If admin wants to automagically register new sites set the hook here
  64. *
  65. * This is a hacky way because xmlrpc is not available on wpmu_new_blog
  66. */
  67. if( $this->get_option( 'auto-connect' ) == 1 ) {
  68. add_action( 'wpmu_new_blog', array( $this, 'do_automatically_add_new_site' ) );
  69. }
  70. }
  71. // 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.
  72. // add_filter( 'jetpack_get_default_modules', array( $this, 'set_auto_activated_modules' ) );
  73. }
  74. /**
  75. * Sets which modules get activated by default on subsite connection.
  76. * Modules can be set in Network Admin > Jetpack > Settings
  77. *
  78. * @since 2.9
  79. * @param array $modules
  80. * @return array
  81. **/
  82. public function set_auto_activated_modules( $modules ) {
  83. return $modules;
  84. /* 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.
  85. if( 1 == $this->get_option( 'manage_auto_activated_modules' ) ) {
  86. return (array) $this->get_option( 'modules' );
  87. } else {
  88. return $modules;
  89. }
  90. */
  91. }
  92. /**
  93. * Registers new sites upon creation
  94. *
  95. * @since 2.9
  96. * @uses wpmu_new_blog
  97. * @param int $blog_id
  98. **/
  99. public function do_automatically_add_new_site( $blog_id ) {
  100. $this->do_subsiteregister( $blog_id );
  101. }
  102. /**
  103. * Adds .network-admin class to the body tag
  104. * Helps distiguish network admin JP styles from regular site JP styles
  105. *
  106. * @since 2.9
  107. */
  108. public function body_class( $classes ) {
  109. return trim( $classes ) . ' network-admin ';
  110. }
  111. /**
  112. * Provides access to an instance of Jetpack_Network
  113. *
  114. * This is how the Jetpack_Network object should *always* be accessed
  115. *
  116. * @since 2.9
  117. * @return Jetpack_Network
  118. */
  119. public static function init() {
  120. if (!self::$instance || !is_a(self::$instance, 'Jetpack_Network')) {
  121. self::$instance = new Jetpack_Network;
  122. }
  123. return self::$instance;
  124. }
  125. /**
  126. * Registers the Multisite admin bar menu item shortcut.
  127. * This shortcut helps users quickly and easily navigate to the Jetpack Network Admin
  128. * menu from anywhere in their network.
  129. *
  130. * @since 2.9
  131. */
  132. public function register_menubar() {
  133. add_action( 'wp_before_admin_bar_render', array( $this, 'add_to_menubar' ) );
  134. }
  135. /**
  136. * Runs when Jetpack is deactivated from the network admin plugins menu.
  137. * Each individual site will need to have Jetpack::disconnect called on it.
  138. * Site that had Jetpack individually enabled will not be disconnected as
  139. * on Multisite individually activated plugins are still activated when
  140. * a plugin is deactivated network wide.
  141. *
  142. * @since 2.9
  143. **/
  144. public function deactivate() {
  145. if( !is_network_admin() ) return; // Only fire if in network admin
  146. $sites = $this->wp_get_sites();
  147. foreach( $sites as $s ) {
  148. switch_to_blog( $s->blog_id );
  149. $active_plugins = get_option( 'active_plugins' );
  150. /*
  151. * If this plugin was activated in the subsite individually
  152. * we do not want to call disconnect. Plugins activated
  153. * individually (before network activation) stay activated
  154. * when the network deactivation occurs
  155. */
  156. if( !in_array( 'jetpack/jetpack.php', $active_plugins ) ) {
  157. Jetpack::disconnect();
  158. }
  159. }
  160. restore_current_blog();
  161. }
  162. /**
  163. * Adds a link to the Jetpack Network Admin page in the netowrk admin menu bar.
  164. *
  165. * @since 2.9
  166. **/
  167. public function add_to_menubar () {
  168. global $wp_admin_bar;
  169. // Don't show for logged out users or single site mode.
  170. if ( ! is_user_logged_in() || ! is_multisite() )
  171. return;
  172. $wp_admin_bar->add_node( array(
  173. 'parent' => 'network-admin',
  174. 'id' => 'network-admin-jetpack',
  175. 'title' => __( 'Jetpack' , 'jetpack' ),
  176. 'href' => $this->get_url( 'network_admin_page' ),
  177. ) );
  178. }
  179. /**
  180. * Returns various URL strings. Factory like
  181. *
  182. * $args can be a string or an array.
  183. * If $args is an array there must be an element called name for the switch statement
  184. *
  185. * Currently supports:
  186. * - subsiteregister: Pass array( 'name' => 'subsiteregister', 'site_id' => SITE_ID )
  187. * - network_admin_page: Provides link to /wp-admin/network/JETPACK
  188. * - subsitedisconnect: Pass array( 'name' => 'subsitedisconnect', 'site_id' => SITE_ID )
  189. *
  190. * @since 2.9
  191. * @param Mixed $args
  192. * @return String
  193. **/
  194. public function get_url( $args ) {
  195. $url = null; // Default url value
  196. if( is_string( $args ) )
  197. $name = $args;
  198. else
  199. $name = $args['name'];
  200. switch( $name ) {
  201. case 'subsiteregister':
  202. if( !isset( $args['site_id'] ) ) {
  203. break; // If there is not a site id present we cannot go further
  204. }
  205. $url = network_admin_url(
  206. 'admin.php?page=jetpack&action=subsiteregister&site_id='
  207. . $args['site_id'] );
  208. break;
  209. case 'network_admin_page':
  210. $url = network_admin_url( 'admin.php?page=jetpack' );
  211. break;
  212. case 'subsitedisconnect':
  213. if( !isset( $args['site_id'] ) ) {
  214. break; // If there is not a site id present we cannot go further
  215. }
  216. $url = network_admin_url(
  217. 'admin.php?page=jetpack&action=subsitedisconnect&site_id='
  218. . $args['site_id'] );
  219. break;
  220. }
  221. return $url;
  222. }
  223. /**
  224. * Adds the Jetpack menu item to the Network Admin area
  225. *
  226. * @since 2.9
  227. */
  228. public function add_network_admin_menu() {
  229. add_menu_page( __( 'Jetpack', 'jetpack' ), __( 'Jetpack', 'jetpack' ), 'manage_network_plugins', 'jetpack', array( $this, 'network_admin_page' ), 'div', 3 );
  230. add_submenu_page( 'jetpack', __( 'Jetpack Sites', 'jetpack' ), __( 'Sites', 'jetpack' ), 'manage_sites', 'jetpack', array( $this, 'network_admin_page' ) );
  231. add_submenu_page( 'jetpack', __( 'Settings', 'jetpack' ), __( 'Settings', 'jetpack' ), 'manage_network_plugins', 'jetpack-settings', array( $this, 'render_network_admin_settings_page' ) );
  232. /**
  233. * As jetpack_register_genericons is by default fired off a hook,
  234. * the hook may have already fired by this point.
  235. * So, let's just trigger it manually.
  236. */
  237. require_once( JETPACK__PLUGIN_DIR . '_inc/genericons.php' );
  238. jetpack_register_genericons();
  239. if ( ! wp_style_is( 'jetpack-icons', 'registered' ) )
  240. wp_register_style( 'jetpack-icons', plugins_url( 'css/jetpack-icons.min.css', JETPACK__PLUGIN_FILE ), false, JETPACK__VERSION );
  241. add_action( 'admin_enqueue_scripts', array( $this, 'admin_menu_css' ) );
  242. }
  243. /**
  244. * Adds JP menu icon
  245. *
  246. * @since 2.9
  247. **/
  248. function admin_menu_css() {
  249. wp_enqueue_style( 'jetpack-icons' );
  250. }
  251. /**
  252. * Provides functionality for the Jetpack > Sites page.
  253. * Does not do the display!
  254. *
  255. * @since 2.9
  256. */
  257. public function jetpack_sites_list() {
  258. Jetpack::init();
  259. if( isset( $_GET['action'] ) ) {
  260. switch( $_GET['action'] ) {
  261. case 'subsiteregister':
  262. /*
  263. * @todo check_admin_referer( 'jetpack-subsite-register' );
  264. */
  265. Jetpack::log( 'subsiteregister' );
  266. // If !$_GET['site_id'] stop registration and error
  267. if( !isset( $_GET['site_id'] ) || empty( $_GET['site_id'] ) ) {
  268. // Log error to state cookie for display later
  269. /**
  270. * @todo Make state messages show on Jetpack NA pages
  271. **/
  272. Jetpack::state( 'missing_site_id', 'Site ID must be provided to register a sub-site' );
  273. break;
  274. }
  275. // Send data to register endpoint and retrieve shadow blog details
  276. $result = $this->do_subsiteregister();
  277. $url = $this->get_url( 'network_admin_page' );
  278. if( is_wp_error( $result ) ) {
  279. $url = add_query_arg( 'action', 'connection_failed', $url );
  280. } else {
  281. $url = add_query_arg( 'action', 'connected', $url );
  282. }
  283. wp_safe_redirect( $url );
  284. break;
  285. case 'subsitedisconnect':
  286. Jetpack::log( 'subsitedisconnect' );
  287. if( !isset( $_GET['site_id'] ) || empty( $_GET['site_id'] ) ) {
  288. Jetpack::state( 'missing_site_id', 'Site ID must be provided to disconnect a sub-site' );
  289. break;
  290. }
  291. $this->do_subsitedisconnect();
  292. break;
  293. case 'connected':
  294. case 'connection_failed':
  295. add_action( 'jetpack_notices', array( $this, 'show_jetpack_notice' ) );
  296. break;
  297. }
  298. }
  299. }
  300. public function show_jetpack_notice() {
  301. if( isset( $_GET['action'] ) && 'connected' == $_GET['action'] ) {
  302. $notice = 'Blog successfully connected';
  303. } else if( isset( $_GET['action'] ) && 'connection_failed' == $_GET['action'] ) {
  304. $notice = 'Blog connection <strong>failed</strong>';
  305. }
  306. Jetpack::init()->load_view( 'admin/network-admin-alert.php', array( 'notice' => $notice ) );
  307. }
  308. /**
  309. * Disconnect functionality for an individual site
  310. *
  311. * @since 2.9
  312. * @see Jetpack_Network::jetpack_sites_list()
  313. */
  314. public function do_subsitedisconnect( $site_id = null ) {
  315. if ( ! current_user_can( 'jetpack_disconnect' ) ) {
  316. return;
  317. }
  318. $site_id = ( is_null( $site_id ) ) ? $_GET['site_id']: $site_id;
  319. switch_to_blog( $site_id );
  320. Jetpack::disconnect();
  321. restore_current_blog();
  322. }
  323. /**
  324. * Registers a subsite with the Jetpack servers
  325. *
  326. * @since 2.9
  327. * @todo Break apart into easier to manage chunks that can be unit tested
  328. * @see Jetpack_Network::jetpack_sites_list();
  329. */
  330. public function do_subsiteregister( $site_id = null ) {
  331. if ( ! current_user_can( 'jetpack_disconnect' ) ) {
  332. return;
  333. }
  334. $jp = Jetpack::init();
  335. // Figure out what site we are working on
  336. $site_id = ( is_null( $site_id ) ) ? $_GET['site_id']: $site_id;
  337. // Build secrets to sent to wpcom for verification
  338. $secrets = $jp->generate_secrets();
  339. // Remote query timeout limit
  340. $timeout = $jp->get_remote_query_timeout_limit();
  341. // The blog id on WordPress.com of the primary network site
  342. $network_wpcom_blog_id = Jetpack_Options::get_option( 'id' );
  343. /*
  344. * Here we need to switch to the subsite
  345. * For the registration process we really only hijack how it
  346. * works for an idividual site and pass in some extra data here
  347. */
  348. switch_to_blog( $site_id );
  349. // Save the secrets in the subsite so when the wpcom server does a pingback it
  350. // will be able to validate the connection
  351. Jetpack_Options::update_option( 'register',
  352. $secrets[0] . ':' .$secrets[1]. ':' . $secrets[2]
  353. );
  354. // Gra info for gmt offset
  355. $gmt_offset = get_option( 'gmt_offset' );
  356. if ( ! $gmt_offset ) {
  357. $gmt_offset = 0;
  358. }
  359. /*
  360. * Get the stats_option option from the db.
  361. * It looks like the server strips this out so maybe it is not necessary?
  362. * Does it match the Jetpack site with the old stats plugin id?
  363. *
  364. * @todo Find out if sending the stats_id is necessary
  365. */
  366. $stat_options = get_option( 'stats_options' );
  367. $stat_id = $stat_options = isset($stats_options['blog_id']) ? $stats_options['blog_id'] : null;
  368. $args = array(
  369. 'method' => 'POST',
  370. 'body' => array(
  371. 'network_url' => $this->get_url( 'network_admin_page' ),
  372. 'network_wpcom_blog_id' => $network_wpcom_blog_id,
  373. 'siteurl' => site_url(),
  374. 'home' => home_url(),
  375. 'gmt_offset' => $gmt_offset,
  376. 'timezone_string' => (string) get_option( 'timezone_string' ),
  377. 'site_name' => (string) get_option( 'blogname' ),
  378. 'secret_1' => $secrets[0],
  379. 'secret_2' => $secrets[1],
  380. 'site_lang' => get_locale(),
  381. 'timeout' => $timeout,
  382. 'stats_id' => $stat_id, // Is this still required?
  383. 'user_id' => get_current_user_id(),
  384. ),
  385. 'headers' => array(
  386. 'Accept' => 'application/json',
  387. ),
  388. 'timeout' => $timeout,
  389. );
  390. // Attempt to retrieve shadow blog details
  391. $response = Jetpack_Client::_wp_remote_request(
  392. Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'subsiteregister' ) ), $args, true
  393. );
  394. /*
  395. * $response should either be invalid or contain:
  396. * - jetpack_id => id
  397. * - jetpack_secret => blog_token
  398. * - jetpack_public
  399. *
  400. * Store the wpcom site details
  401. */
  402. $valid_response = $jp->validate_remote_register_response( $response );
  403. if( is_wp_error( $valid_response ) || !$valid_response ) {
  404. return $valid_response;
  405. }
  406. // Grab the response values to work with
  407. $code = wp_remote_retrieve_response_code( $response );
  408. $entity = wp_remote_retrieve_body( $response );
  409. if ( $entity )
  410. $json = json_decode( $entity );
  411. else
  412. $json = false;
  413. if ( empty( $json->jetpack_secret ) || ! is_string( $json->jetpack_secret ) )
  414. return new Jetpack_Error( 'jetpack_secret', '', $code );
  415. if ( isset( $json->jetpack_public ) ) {
  416. $jetpack_public = (int) $json->jetpack_public;
  417. } else {
  418. $jetpack_public = false;
  419. }
  420. Jetpack_Options::update_options(
  421. array(
  422. 'id' => (int) $json->jetpack_id,
  423. 'blog_token' => (string) $json->jetpack_secret,
  424. 'public' => $jetpack_public,
  425. )
  426. );
  427. /*
  428. * Update the subsiteregister method on wpcom so that it also sends back the
  429. * token in this same request
  430. */
  431. $is_master_user = ! Jetpack::is_active();
  432. Jetpack::update_user_token(
  433. get_current_user_id(),
  434. sprintf(
  435. '%s.%d',
  436. $json->token->secret,
  437. get_current_user_id()
  438. ),
  439. $is_master_user
  440. );
  441. Jetpack::activate_default_modules();
  442. restore_current_blog();
  443. }
  444. /**
  445. * Handles the displaying of all sites on the network that are
  446. * dis/connected to Jetpack
  447. *
  448. * @since 2.9
  449. * @see Jetpack_Network::jetpack_sites_list()
  450. */
  451. function network_admin_page() {
  452. global $current_site;
  453. $this->network_admin_page_header();
  454. $jp = Jetpack::init();
  455. // We should be, but ensure we are on the main blog
  456. switch_to_blog( $current_site->blog_id );
  457. $main_active = $jp->is_active();
  458. restore_current_blog();
  459. // If we are in dev mode, just show the notice and bail
  460. if ( Jetpack::is_development_mode() ) {
  461. Jetpack::show_development_mode_notice();
  462. return;
  463. }
  464. /*
  465. * Ensure the main blog is connected as all other subsite blog
  466. * connections will feed off this one
  467. */
  468. if( !$main_active ) {
  469. $url = $this->get_url( array(
  470. 'name' => 'subsiteregister',
  471. 'site_id' => 1,
  472. ) );
  473. $data = array( 'url' => $jp->build_connect_url() );
  474. Jetpack::init()->load_view( 'admin/must-connect-main-blog.php', $data );
  475. return;
  476. }
  477. require_once( 'class.jetpack-network-sites-list-table.php' );
  478. $myListTable = new Jetpack_Network_Sites_List_Table();
  479. echo '<div class="wrap"><h2>' . __('Sites', 'jetpack') . '</h2>';
  480. echo '<form method="post">';
  481. $myListTable->prepare_items();
  482. $myListTable->display();
  483. echo '</form></div>';
  484. $this->network_admin_page_footer();
  485. }
  486. /**
  487. * Stylized JP header formatting
  488. *
  489. * @since 2.9
  490. */
  491. function network_admin_page_header() {
  492. global $current_user;
  493. $is_connected = Jetpack::is_active();
  494. $data = array(
  495. 'is_connected' => $is_connected
  496. );
  497. Jetpack::init()->load_view( 'admin/network-admin-header.php', $data );
  498. }
  499. /**
  500. * Stylized JP footer formatting
  501. *
  502. * @since 2.9
  503. */
  504. function network_admin_page_footer() {
  505. Jetpack::init()->load_view( 'admin/network-admin-footer.php' );
  506. }
  507. /**
  508. * Fires when the Jetpack > Settings page is saved.
  509. *
  510. * @since 2.9
  511. */
  512. public function save_network_settings_page() {
  513. if ( ! wp_verify_nonce( $_POST['_wpnonce'], 'jetpack-network-settings' ) ) {
  514. // no nonce, push back to settings page
  515. wp_safe_redirect(
  516. add_query_arg(
  517. array( 'page' => 'jetpack-settings' ),
  518. network_admin_url( 'admin.php' )
  519. )
  520. );
  521. exit();
  522. }
  523. // try to save the Protect whitelist before anything else, since that action can result in errors
  524. $whitelist = str_replace( ' ', '', $_POST['global-whitelist'] );
  525. $whitelist = explode( PHP_EOL, $whitelist );
  526. $result = jetpack_protect_save_whitelist( $whitelist, $global = true );
  527. if ( is_wp_error( $result ) ) {
  528. wp_safe_redirect(
  529. add_query_arg(
  530. array( 'page' => 'jetpack-settings', 'error' => 'jetpack_protect_whitelist' ),
  531. network_admin_url( 'admin.php' )
  532. )
  533. );
  534. exit();
  535. }
  536. /*
  537. * Fields
  538. *
  539. * auto-connect - Checkbox for global Jetpack connection
  540. * sub-site-connection-override - Allow sub-site admins to (dis)reconnect with their own Jetpack account
  541. */
  542. $auto_connect = 0;
  543. if( isset( $_POST['auto-connect'] ) )
  544. $auto_connect = 1;
  545. $sub_site_connection_override = 0;
  546. if( isset( $_POST['sub-site-connection-override'] ) )
  547. $sub_site_connection_override = 1;
  548. /* 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.
  549. $manage_auto_activated_modules = 0;
  550. if( isset( $_POST['manage_auto_activated_modules'] ) )
  551. $manage_auto_activated_modules = 1;
  552. $modules = array();
  553. if( isset( $_POST['modules'] ) )
  554. $modules = $_POST['modules'];
  555. */
  556. $data = array(
  557. 'auto-connect' => $auto_connect,
  558. 'sub-site-connection-override' => $sub_site_connection_override,
  559. // 'manage_auto_activated_modules' => $manage_auto_activated_modules,
  560. // 'modules' => $modules,
  561. );
  562. update_site_option( $this->settings_name, $data );
  563. wp_safe_redirect(
  564. add_query_arg(
  565. array( 'page' => 'jetpack-settings', 'updated' => 'true' ),
  566. network_admin_url( 'admin.php' )
  567. )
  568. );
  569. exit();
  570. }
  571. public function render_network_admin_settings_page() {
  572. $this->network_admin_page_header();
  573. $options = wp_parse_args( get_site_option( $this->settings_name ), $this->setting_defaults );
  574. $modules = array();
  575. $module_slugs = Jetpack::get_available_modules();
  576. foreach ( $module_slugs as $slug ) {
  577. $module = Jetpack::get_module( $slug );
  578. $module['module'] = $slug;
  579. $modules[] = $module;
  580. }
  581. usort( $modules, array( 'Jetpack', 'sort_modules' ) );
  582. if( !isset( $options['modules'] ) ) {
  583. $options['modules'] = $modules;
  584. }
  585. $data = array(
  586. 'modules' => $modules,
  587. 'options' => $options,
  588. 'jetpack_protect_whitelist' => jetpack_protect_format_whitelist(),
  589. );
  590. Jetpack::init()->load_view( 'admin/network-settings.php', $data );
  591. $this->network_admin_page_footer();
  592. }
  593. /**
  594. * Updates a site wide option
  595. *
  596. * @since 2.9
  597. * @param string $key
  598. * @param mixed $value
  599. * @return boolean
  600. **/
  601. public function update_option( $key, $value ) {
  602. $options = get_site_option( $this->settings_name, $this->setting_defaults );
  603. $options[$key] = $value;
  604. return update_site_option( $this->settings_name, $options );
  605. }
  606. /**
  607. * Retrieves a site wide option
  608. *
  609. * @since 2.9
  610. * @param string $name - Name of the option in the database
  611. **/
  612. public function get_option( $name ) {
  613. $options = get_site_option( $this->settings_name, $this->setting_defaults );
  614. $options = wp_parse_args( $options, $this->setting_defaults );
  615. if( !isset( $options[$name] ) )
  616. $options[$name] = null;
  617. return $options[$name];
  618. }
  619. /**
  620. * Return an array of sites on the specified network. If no network is specified,
  621. * return all sites, regardless of network.
  622. *
  623. *
  624. * @todo REMOVE THIS FUNCTION! This function is moving to core. Use that one in favor of this. WordPress::wp_get_sites(). http://codex.wordpress.org/Function_Reference/wp_get_sites NOTE, This returns an array instead of stdClass. Be sure to update class.network-sites-list-table.php
  625. * @since 2.9
  626. * @deprecated 2.4.5
  627. * @param array|string $args Optional. Specify the status of the sites to return.
  628. * @return array An array of site data
  629. */
  630. public function wp_get_sites($args = array()) {
  631. global $wpdb;
  632. if (wp_is_large_network())
  633. return;
  634. $defaults = array('network_id' => $wpdb->siteid);
  635. $args = wp_parse_args($args, $defaults);
  636. $query = "SELECT * FROM $wpdb->blogs WHERE 1=1 ";
  637. if (isset($args['network_id']) && ( is_array($args['network_id']) || is_numeric($args['network_id']) )) {
  638. $network_ids = array_map('intval', (array) $args['network_id']);
  639. $network_ids = implode(',', $network_ids);
  640. $query .= "AND site_id IN ($network_ids) ";
  641. }
  642. if (isset($args['public']))
  643. $query .= $wpdb->prepare("AND public = %s ", $args['public']);
  644. if (isset($args['archived']))
  645. $query .= $wpdb->prepare("AND archived = %s ", $args['archived']);
  646. if (isset($args['mature']))
  647. $query .= $wpdb->prepare("AND mature = %s ", $args['mature']);
  648. if (isset($args['spam']))
  649. $query .= $wpdb->prepare("AND spam = %s ", $args['spam']);
  650. if (isset($args['deleted']))
  651. $query .= $wpdb->prepare("AND deleted = %s ", $args['deleted']);
  652. if( isset( $args['exclude_blogs'] ) )
  653. $query .= "AND blog_id NOT IN (" . implode( ',', $args['exclude_blogs'] ) . ")";
  654. $key = 'wp_get_sites:' . md5($query);
  655. if (!$site_results = wp_cache_get($key, 'site-id-cache')) {
  656. $site_results = (array) $wpdb->get_results($query);
  657. wp_cache_set($key, $site_results, 'site-id-cache');
  658. }
  659. return $site_results;
  660. }
  661. }
  662. // end class