/class-buddypress.php

  1. <?php 
  2.  
  3. // Exit if accessed directly. 
  4. defined( 'ABSPATH' ) || exit; 
  5.  
  6. /** 
  7. * Main BuddyPress Class. 
  8. * 
  9. * Tap tap tap... Is this thing on? 
  10. * 
  11. * @since 1.6.0 
  12. */ 
  13. class BuddyPress { 
  14.  
  15. /** Magic *****************************************************************/ 
  16.  
  17. /** 
  18. * BuddyPress uses many variables, most of which can be filtered to 
  19. * customize the way that it works. To prevent unauthorized access,  
  20. * these variables are stored in a private array that is magically 
  21. * updated using PHP 5.2+ methods. This is to prevent third party 
  22. * plugins from tampering with essential information indirectly, which 
  23. * would cause issues later. 
  24. * 
  25. * @see BuddyPress::setup_globals() 
  26. * @var array 
  27. */ 
  28. private $data; 
  29.  
  30. /** Not Magic *************************************************************/ 
  31.  
  32. /** 
  33. * @var array Primary BuddyPress navigation. 
  34. */ 
  35. public $bp_nav = array(); 
  36.  
  37. /** 
  38. * @var array Secondary BuddyPress navigation to $bp_nav. 
  39. */ 
  40. public $bp_options_nav = array(); 
  41.  
  42. /** 
  43. * @var array The unfiltered URI broken down into chunks. 
  44. * @see bp_core_set_uri_globals() 
  45. */ 
  46. public $unfiltered_uri = array(); 
  47.  
  48. /** 
  49. * @var array The canonical URI stack. 
  50. * @see bp_redirect_canonical() 
  51. * @see bp_core_new_nav_item() 
  52. */ 
  53. public $canonical_stack = array(); 
  54.  
  55. /** 
  56. * @var array Additional navigation elements (supplemental). 
  57. */ 
  58. public $action_variables = array(); 
  59.  
  60. /** 
  61. * @var string Current member directory type. 
  62. */ 
  63. public $current_member_type = ''; 
  64.  
  65. /** 
  66. * @var array Required components (core, members). 
  67. */ 
  68. public $required_components = array(); 
  69.  
  70. /** 
  71. * @var array Additional active components. 
  72. */ 
  73. public $loaded_components = array(); 
  74.  
  75. /** 
  76. * @var array Active components. 
  77. */ 
  78. public $active_components = array(); 
  79.  
  80. /** 
  81. * Whether autoload is in use. 
  82. * 
  83. * @since 2.5.0 
  84. * @var bool 
  85. */ 
  86. public $do_autoload = true; 
  87.  
  88. /** Option Overload *******************************************************/ 
  89.  
  90. /** 
  91. * @var array Optional Overloads default options retrieved from get_option(). 
  92. */ 
  93. public $options = array(); 
  94.  
  95. /** Singleton *************************************************************/ 
  96.  
  97. /** 
  98. * Main BuddyPress Instance. 
  99. * 
  100. * BuddyPress is great. 
  101. * Please load it only one time. 
  102. * For this, we thank you. 
  103. * 
  104. * Insures that only one instance of BuddyPress exists in memory at any 
  105. * one time. Also prevents needing to define globals all over the place. 
  106. * 
  107. * @since 1.7.0 
  108. * 
  109. * @static object $instance 
  110. * @see buddypress() 
  111. * 
  112. * @return BuddyPress The one true BuddyPress. 
  113. */ 
  114. public static function instance() { 
  115.  
  116. // Store the instance locally to avoid private static replication 
  117. static $instance = null; 
  118.  
  119. // Only run these methods if they haven't been run previously 
  120. if ( null === $instance ) { 
  121. $instance = new BuddyPress; 
  122. $instance->constants(); 
  123. $instance->setup_globals(); 
  124. $instance->legacy_constants(); 
  125. $instance->includes(); 
  126. $instance->setup_actions(); 
  127.  
  128. // Always return the instance 
  129. return $instance; 
  130.  
  131. // The last metroid is in captivity. The galaxy is at peace. 
  132.  
  133. /** Magic Methods *********************************************************/ 
  134.  
  135. /** 
  136. * A dummy constructor to prevent BuddyPress from being loaded more than once. 
  137. * 
  138. * @since 1.7.0 
  139. * @see BuddyPress::instance() 
  140. * @see buddypress() 
  141. */ 
  142. private function __construct() { /** Do nothing here */
  143.  
  144. /** 
  145. * A dummy magic method to prevent BuddyPress from being cloned. 
  146. * 
  147. * @since 1.7.0 
  148. */ 
  149. public function __clone() { _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'buddypress' ), '1.7' ); } 
  150.  
  151. /** 
  152. * A dummy magic method to prevent BuddyPress from being unserialized. 
  153. * 
  154. * @since 1.7.0 
  155. */ 
  156. public function __wakeup() { _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'buddypress' ), '1.7' ); } 
  157.  
  158. /** 
  159. * Magic method for checking the existence of a certain custom field. 
  160. * 
  161. * @since 1.7.0 
  162. * 
  163. * @param string $key Key to check the set status for. 
  164. * 
  165. * @return bool 
  166. */ 
  167. public function __isset( $key ) { return isset( $this->data[$key] ); } 
  168.  
  169. /** 
  170. * Magic method for getting BuddyPress variables. 
  171. * 
  172. * @since 1.7.0 
  173. * 
  174. * @param string $key Key to return the value for. 
  175. * 
  176. * @return mixed 
  177. */ 
  178. public function __get( $key ) { return isset( $this->data[$key] ) ? $this->data[$key] : null; } 
  179.  
  180. /** 
  181. * Magic method for setting BuddyPress variables. 
  182. * 
  183. * @since 1.7.0 
  184. * 
  185. * @param string $key Key to set a value for. 
  186. * @param mixed $value Value to set. 
  187. */ 
  188. public function __set( $key, $value ) { $this->data[$key] = $value; } 
  189.  
  190. /** 
  191. * Magic method for unsetting BuddyPress variables. 
  192. * 
  193. * @since 1.7.0 
  194. * 
  195. * @param string $key Key to unset a value for. 
  196. */ 
  197. public function __unset( $key ) { if ( isset( $this->data[$key] ) ) unset( $this->data[$key] ); } 
  198.  
  199. /** 
  200. * Magic method to prevent notices and errors from invalid method calls. 
  201. * 
  202. * @since 1.7.0 
  203. * 
  204. * @param string $name 
  205. * @param array $args 
  206. * 
  207. * @return null 
  208. */ 
  209. public function __call( $name = '', $args = array() ) { unset( $name, $args ); return null; } 
  210.  
  211. /** Private Methods *******************************************************/ 
  212.  
  213. /** 
  214. * Bootstrap constants. 
  215. * 
  216. * @since 1.6.0 
  217. * 
  218. */ 
  219. private function constants() { 
  220.  
  221. // Place your custom code (actions/filters) in a file called 
  222. // '/plugins/bp-custom.php' and it will be loaded before anything else. 
  223. if ( file_exists( WP_PLUGIN_DIR . '/bp-custom.php' ) ) { 
  224. require( WP_PLUGIN_DIR . '/bp-custom.php' ); 
  225.  
  226. // Path and URL 
  227. if ( ! defined( 'BP_PLUGIN_DIR' ) ) { 
  228. define( 'BP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 
  229.  
  230. if ( ! defined( 'BP_PLUGIN_URL' ) ) { 
  231. define( 'BP_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); 
  232.  
  233. // Only applicable to those running trunk 
  234. if ( ! defined( 'BP_SOURCE_SUBDIRECTORY' ) ) { 
  235. define( 'BP_SOURCE_SUBDIRECTORY', '' ); 
  236.  
  237. // Define on which blog ID BuddyPress should run 
  238. if ( ! defined( 'BP_ROOT_BLOG' ) ) { 
  239.  
  240. // Default to use current blog ID 
  241. // Fulfills non-network installs and BP_ENABLE_MULTIBLOG installs 
  242. $root_blog_id = get_current_blog_id(); 
  243.  
  244. // Multisite check 
  245. if ( is_multisite() ) { 
  246.  
  247. // Multiblog isn't enabled 
  248. if ( ! defined( 'BP_ENABLE_MULTIBLOG' ) || ( defined( 'BP_ENABLE_MULTIBLOG' ) && (int) constant( 'BP_ENABLE_MULTIBLOG' ) === 0 ) ) { 
  249. // Check to see if BP is network-activated 
  250. // We're not using is_plugin_active_for_network() b/c you need to include the 
  251. // /wp-admin/includes/plugin.php file in order to use that function. 
  252.  
  253. // get network-activated plugins 
  254. $plugins = get_site_option( 'active_sitewide_plugins'); 
  255.  
  256. // basename 
  257. $basename = basename( constant( 'BP_PLUGIN_DIR' ) ) . '/bp-loader.php'; 
  258.  
  259. // plugin is network-activated; use main site ID instead 
  260. if ( isset( $plugins[ $basename ] ) ) { 
  261. $current_site = get_current_site(); 
  262. $root_blog_id = $current_site->blog_id; 
  263.  
  264.  
  265. define( 'BP_ROOT_BLOG', $root_blog_id ); 
  266.  
  267. // The search slug has to be defined nice and early because of the way 
  268. // search requests are loaded 
  269. // 
  270. // @todo Make this better 
  271. if ( ! defined( 'BP_SEARCH_SLUG' ) ) { 
  272. define( 'BP_SEARCH_SLUG', 'search' ); 
  273.  
  274. /** 
  275. * Component global variables. 
  276. * 
  277. * @since 1.6.0 
  278. * 
  279. */ 
  280. private function setup_globals() { 
  281.  
  282. /** Versions **********************************************************/ 
  283.  
  284. $this->version = '2.8.2'; 
  285. $this->db_version = 11105; 
  286.  
  287. /** Loading ***********************************************************/ 
  288.  
  289. /** 
  290. * Should deprecated code be loaded? 
  291. * 
  292. * @since 2.0.0 Defaults to false always 
  293. * @since 2.8.0 Defaults to true on upgrades, false for new installs. 
  294. */ 
  295. $this->load_deprecated = false; 
  296.  
  297. /** Toolbar ***********************************************************/ 
  298.  
  299. /** 
  300. * @var string The primary toolbar ID. 
  301. */ 
  302. $this->my_account_menu_id = ''; 
  303.  
  304. /** URIs **************************************************************/ 
  305.  
  306. /** 
  307. * @var int The current offset of the URI. 
  308. * @see bp_core_set_uri_globals() 
  309. */ 
  310. $this->unfiltered_uri_offset = 0; 
  311.  
  312. /** 
  313. * @var bool Are status headers already sent? 
  314. */ 
  315. $this->no_status_set = false; 
  316.  
  317. /** Components ********************************************************/ 
  318.  
  319. /** 
  320. * @var string Name of the current BuddyPress component (primary). 
  321. */ 
  322. $this->current_component = ''; 
  323.  
  324. /** 
  325. * @var string Name of the current BuddyPress item (secondary). 
  326. */ 
  327. $this->current_item = ''; 
  328.  
  329. /** 
  330. * @var string Name of the current BuddyPress action (tertiary). 
  331. */ 
  332. $this->current_action = ''; 
  333.  
  334. /** 
  335. * @var bool Displaying custom 2nd level navigation menu (I.E a group). 
  336. */ 
  337. $this->is_single_item = false; 
  338.  
  339. /** Root **************************************************************/ 
  340.  
  341. /** 
  342. * Filters the BuddyPress Root blog ID. 
  343. * 
  344. * @since 1.5.0 
  345. * 
  346. * @const constant BP_ROOT_BLOG BuddyPress Root blog ID. 
  347. */ 
  348. $this->root_blog_id = (int) apply_filters( 'bp_get_root_blog_id', BP_ROOT_BLOG ); 
  349.  
  350. /** Paths**************************************************************/ 
  351.  
  352. // BuddyPress root directory 
  353. $this->file = constant( 'BP_PLUGIN_DIR' ) . 'bp-loader.php'; 
  354. $this->basename = basename( constant( 'BP_PLUGIN_DIR' ) ) . '/bp-loader.php'; 
  355. $this->plugin_dir = trailingslashit( constant( 'BP_PLUGIN_DIR' ) . constant( 'BP_SOURCE_SUBDIRECTORY' ) ); 
  356. $this->plugin_url = trailingslashit( constant( 'BP_PLUGIN_URL' ) . constant( 'BP_SOURCE_SUBDIRECTORY' ) ); 
  357.  
  358. // Languages 
  359. $this->lang_dir = $this->plugin_dir . 'bp-languages'; 
  360.  
  361. // Templates (theme compatibility) 
  362. $this->themes_dir = $this->plugin_dir . 'bp-templates'; 
  363. $this->themes_url = $this->plugin_url . 'bp-templates'; 
  364.  
  365. // Themes (for bp-default) 
  366. $this->old_themes_dir = $this->plugin_dir . 'bp-themes'; 
  367. $this->old_themes_url = $this->plugin_url . 'bp-themes'; 
  368.  
  369. /** Theme Compat ******************************************************/ 
  370.  
  371. $this->theme_compat = new stdClass(); // Base theme compatibility class 
  372. $this->filters = new stdClass(); // Used when adding/removing filters 
  373.  
  374. /** Users *************************************************************/ 
  375.  
  376. $this->current_user = new stdClass(); 
  377. $this->displayed_user = new stdClass(); 
  378.  
  379. /** Post types and taxonomies *****************************************/ 
  380. $this->email_post_type = apply_filters( 'bp_email_post_type', 'bp-email' ); 
  381. $this->email_taxonomy_type = apply_filters( 'bp_email_tax_type', 'bp-email-type' ); 
  382.  
  383. /** 
  384. * Legacy BuddyPress constants. 
  385. * 
  386. * Try to avoid using these. Their values have been moved into variables 
  387. * in the instance, and have matching functions to get/set their values. 
  388. * 
  389. * @since 1.7.0 
  390. */ 
  391. private function legacy_constants() { 
  392.  
  393. // Define the BuddyPress version 
  394. if ( ! defined( 'BP_VERSION' ) ) { 
  395. define( 'BP_VERSION', $this->version ); 
  396.  
  397. // Define the database version 
  398. if ( ! defined( 'BP_DB_VERSION' ) ) { 
  399. define( 'BP_DB_VERSION', $this->db_version ); 
  400.  
  401. // Define if deprecated functions should be ignored 
  402. if ( ! defined( 'BP_IGNORE_DEPRECATED' ) ) { 
  403. define( 'BP_IGNORE_DEPRECATED', true ); 
  404.  
  405. /** 
  406. * Include required files. 
  407. * 
  408. * @since 1.6.0 
  409. * 
  410. */ 
  411. private function includes() { 
  412. spl_autoload_register( array( $this, 'autoload' ) ); 
  413.  
  414. // Load the WP abstraction file so BuddyPress can run on all WordPress setups. 
  415. require( $this->plugin_dir . 'bp-core/bp-core-wpabstraction.php' ); 
  416.  
  417. // Setup the versions (after we include multisite abstraction above) 
  418. $this->versions(); 
  419.  
  420. /** Update/Install ****************************************************/ 
  421.  
  422. // Theme compatibility 
  423. require( $this->plugin_dir . 'bp-core/bp-core-template-loader.php' ); 
  424. require( $this->plugin_dir . 'bp-core/bp-core-theme-compatibility.php' ); 
  425.  
  426. // Require all of the BuddyPress core libraries 
  427. require( $this->plugin_dir . 'bp-core/bp-core-dependency.php' ); 
  428. require( $this->plugin_dir . 'bp-core/bp-core-actions.php' ); 
  429. require( $this->plugin_dir . 'bp-core/bp-core-caps.php' ); 
  430. require( $this->plugin_dir . 'bp-core/bp-core-cache.php' ); 
  431. require( $this->plugin_dir . 'bp-core/bp-core-cssjs.php' ); 
  432. require( $this->plugin_dir . 'bp-core/bp-core-update.php' ); 
  433. require( $this->plugin_dir . 'bp-core/bp-core-options.php' ); 
  434. require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php' ); 
  435. require( $this->plugin_dir . 'bp-core/bp-core-filters.php' ); 
  436. require( $this->plugin_dir . 'bp-core/bp-core-attachments.php' ); 
  437. require( $this->plugin_dir . 'bp-core/bp-core-avatars.php' ); 
  438. require( $this->plugin_dir . 'bp-core/bp-core-widgets.php' ); 
  439. require( $this->plugin_dir . 'bp-core/bp-core-template.php' ); 
  440. require( $this->plugin_dir . 'bp-core/bp-core-adminbar.php' ); 
  441. require( $this->plugin_dir . 'bp-core/bp-core-buddybar.php' ); 
  442. require( $this->plugin_dir . 'bp-core/bp-core-catchuri.php' ); 
  443. require( $this->plugin_dir . 'bp-core/bp-core-functions.php' ); 
  444. require( $this->plugin_dir . 'bp-core/bp-core-moderation.php' ); 
  445. require( $this->plugin_dir . 'bp-core/bp-core-loader.php' ); 
  446. require( $this->plugin_dir . 'bp-core/bp-core-customizer-email.php' ); 
  447.  
  448. // Maybe load deprecated functionality (this double negative is proof positive!) 
  449. if ( ! bp_get_option( '_bp_ignore_deprecated_code', ! $this->load_deprecated ) ) { 
  450. require( $this->plugin_dir . 'bp-core/deprecated/1.2.php' ); 
  451. require( $this->plugin_dir . 'bp-core/deprecated/1.5.php' ); 
  452. require( $this->plugin_dir . 'bp-core/deprecated/1.6.php' ); 
  453. require( $this->plugin_dir . 'bp-core/deprecated/1.7.php' ); 
  454. require( $this->plugin_dir . 'bp-core/deprecated/1.9.php' ); 
  455. require( $this->plugin_dir . 'bp-core/deprecated/2.0.php' ); 
  456. require( $this->plugin_dir . 'bp-core/deprecated/2.1.php' ); 
  457. require( $this->plugin_dir . 'bp-core/deprecated/2.2.php' ); 
  458. require( $this->plugin_dir . 'bp-core/deprecated/2.3.php' ); 
  459. require( $this->plugin_dir . 'bp-core/deprecated/2.4.php' ); 
  460. require( $this->plugin_dir . 'bp-core/deprecated/2.5.php' ); 
  461. require( $this->plugin_dir . 'bp-core/deprecated/2.6.php' ); 
  462. require( $this->plugin_dir . 'bp-core/deprecated/2.7.php' ); 
  463.  
  464. /** 
  465. * Autoload classes. 
  466. * 
  467. * @since 2.5.0 
  468. * 
  469. * @param string $class 
  470. */ 
  471. public function autoload( $class ) { 
  472. $class_parts = explode( '_', strtolower( $class ) ); 
  473.  
  474. if ( 'bp' !== $class_parts[0] ) { 
  475. return; 
  476.  
  477. $components = array( 
  478. 'activity',  
  479. 'blogs',  
  480. 'core',  
  481. 'friends',  
  482. 'groups',  
  483. 'members',  
  484. 'messages',  
  485. 'notifications',  
  486. 'settings',  
  487. 'xprofile',  
  488. ); 
  489.  
  490. // These classes don't have a name that matches their component. 
  491. $irregular_map = array( 
  492. 'BP_Akismet' => 'activity',  
  493.  
  494. 'BP_Admin' => 'core',  
  495. 'BP_Attachment_Avatar' => 'core',  
  496. 'BP_Attachment_Cover_Image' => 'core',  
  497. 'BP_Attachment' => 'core',  
  498. 'BP_Button' => 'core',  
  499. 'BP_Component' => 'core',  
  500. 'BP_Customizer_Control_Range' => 'core',  
  501. 'BP_Date_Query' => 'core',  
  502. 'BP_Email_Delivery' => 'core',  
  503. 'BP_Email_Recipient' => 'core',  
  504. 'BP_Email' => 'core',  
  505. 'BP_Embed' => 'core',  
  506. 'BP_Media_Extractor' => 'core',  
  507. 'BP_Members_Suggestions' => 'core',  
  508. 'BP_PHPMailer' => 'core',  
  509. 'BP_Recursive_Query' => 'core',  
  510. 'BP_Suggestions' => 'core',  
  511. 'BP_Theme_Compat' => 'core',  
  512. 'BP_User_Query' => 'core',  
  513. 'BP_Walker_Category_Checklist' => 'core',  
  514. 'BP_Walker_Nav_Menu_Checklist' => 'core',  
  515. 'BP_Walker_Nav_Menu' => 'core',  
  516.  
  517. 'BP_Core_Friends_Widget' => 'friends',  
  518.  
  519. 'BP_Group_Extension' => 'groups',  
  520. 'BP_Group_Member_Query' => 'groups',  
  521.  
  522. 'BP_Core_Members_Template' => 'members',  
  523. 'BP_Core_Members_Widget' => 'members',  
  524. 'BP_Core_Recently_Active_Widget' => 'members',  
  525. 'BP_Core_Whos_Online_Widget' => 'members',  
  526. 'BP_Registration_Theme_Compat' => 'members',  
  527. 'BP_Signup' => 'members',  
  528. ); 
  529.  
  530. $component = null; 
  531.  
  532. // First check to see if the class is one without a properly namespaced name. 
  533. if ( isset( $irregular_map[ $class ] ) ) { 
  534. $component = $irregular_map[ $class ]; 
  535.  
  536. // Next chunk is usually the component name. 
  537. } elseif ( in_array( $class_parts[1], $components, true ) ) { 
  538. $component = $class_parts[1]; 
  539.  
  540. if ( ! $component ) { 
  541. return; 
  542.  
  543. // Sanitize class name. 
  544. $class = strtolower( str_replace( '_', '-', $class ) ); 
  545.  
  546. $path = dirname( __FILE__ ) . "/bp-{$component}/classes/class-{$class}.php"; 
  547.  
  548. // Sanity check. 
  549. if ( ! file_exists( $path ) ) { 
  550. return; 
  551.  
  552. /** 
  553. * Sanity check 2 - Check if component is active before loading class. 
  554. * Skip if PHPUnit is running, or BuddyPress is installing for the first time. 
  555. */ 
  556. if ( 
  557. ! in_array( $component, array( 'core', 'members' ), true ) && 
  558. ! bp_is_active( $component ) && 
  559. ! function_exists( 'tests_add_filter' ) 
  560. ) { 
  561. return; 
  562.  
  563. require $path; 
  564.  
  565. /** 
  566. * Set up the default hooks and actions. 
  567. * 
  568. * @since 1.6.0 
  569. * 
  570. */ 
  571. private function setup_actions() { 
  572.  
  573. // Add actions to plugin activation and deactivation hooks 
  574. add_action( 'activate_' . $this->basename, 'bp_activation' ); 
  575. add_action( 'deactivate_' . $this->basename, 'bp_deactivation' ); 
  576.  
  577. // If BuddyPress is being deactivated, do not add any actions 
  578. if ( bp_is_deactivation( $this->basename ) ) { 
  579. return; 
  580.  
  581. // Array of BuddyPress core actions 
  582. $actions = array( 
  583. 'setup_theme', // Setup the default theme compat 
  584. 'setup_current_user', // Setup currently logged in user 
  585. 'register_post_types', // Register post types 
  586. 'register_post_statuses', // Register post statuses 
  587. 'register_taxonomies', // Register taxonomies 
  588. 'register_views', // Register the views 
  589. 'register_theme_directory', // Register the theme directory 
  590. 'register_theme_packages', // Register bundled theme packages (bp-themes) 
  591. 'load_textdomain', // Load textdomain 
  592. 'add_rewrite_tags', // Add rewrite tags 
  593. 'generate_rewrite_rules' // Generate rewrite rules 
  594. ); 
  595.  
  596. // Add the actions 
  597. foreach( $actions as $class_action ) { 
  598. if ( method_exists( $this, $class_action ) ) { 
  599. add_action( 'bp_' . $class_action, array( $this, $class_action ), 5 ); 
  600.  
  601. /** 
  602. * Fires after the setup of all BuddyPress actions. 
  603. * 
  604. * Includes bbp-core-hooks.php. 
  605. * 
  606. * @since 1.7.0 
  607. * 
  608. * @param BuddyPress $this. Current BuddyPress instance. Passed by reference. 
  609. */ 
  610. do_action_ref_array( 'bp_after_setup_actions', array( &$this ) ); 
  611.  
  612. /** 
  613. * Private method to align the active and database versions. 
  614. * 
  615. * @since 1.7.0 
  616. */ 
  617. private function versions() { 
  618.  
  619. // Get the possible DB versions (boy is this gross) 
  620. $versions = array(); 
  621. $versions['1.6-single'] = get_blog_option( $this->root_blog_id, '_bp_db_version' ); 
  622.  
  623. // 1.6-single exists, so trust it 
  624. if ( !empty( $versions['1.6-single'] ) ) { 
  625. $this->db_version_raw = (int) $versions['1.6-single']; 
  626.  
  627. // If no 1.6-single exists, use the max of the others 
  628. } else { 
  629. $versions['1.2'] = get_site_option( 'bp-core-db-version' ); 
  630. $versions['1.5-multi'] = get_site_option( 'bp-db-version' ); 
  631. $versions['1.6-multi'] = get_site_option( '_bp_db_version' ); 
  632. $versions['1.5-single'] = get_blog_option( $this->root_blog_id, 'bp-db-version' ); 
  633.  
  634. // Remove empty array items 
  635. $versions = array_filter( $versions ); 
  636. $this->db_version_raw = (int) ( !empty( $versions ) ) ? (int) max( $versions ) : 0; 
  637.  
  638. /** Public Methods ********************************************************/ 
  639.  
  640. /** 
  641. * Set up BuddyPress's legacy theme directory. 
  642. * 
  643. * Starting with version 1.2, and ending with version 1.8, BuddyPress 
  644. * registered a custom theme directory - bp-themes - which contained 
  645. * the bp-default theme. Since BuddyPress 1.9, bp-themes is no longer 
  646. * registered (and bp-default no longer offered) on new installations. 
  647. * Sites using bp-default (or a child theme of bp-default) will 
  648. * continue to have bp-themes registered as before. 
  649. * 
  650. * @since 1.5.0 
  651. * 
  652. * @todo Move bp-default to wordpress.org/extend/themes and remove this. 
  653. */ 
  654. public function register_theme_directory() { 
  655. if ( ! bp_do_register_theme_directory() ) { 
  656. return; 
  657.  
  658. register_theme_directory( $this->old_themes_dir ); 
  659.  
  660. /** 
  661. * Register bundled theme packages. 
  662. * 
  663. * Note that since we currently have complete control over bp-themes and 
  664. * the bp-legacy folders, it's fine to hardcode these here. If at a 
  665. * later date we need to automate this, an API will need to be built. 
  666. * 
  667. * @since 1.7.0 
  668. */ 
  669. public function register_theme_packages() { 
  670.  
  671. // Register the default theme compatibility package 
  672. bp_register_theme_package( array( 
  673. 'id' => 'legacy',  
  674. 'name' => __( 'BuddyPress Default', 'buddypress' ),  
  675. 'version' => bp_get_version(),  
  676. 'dir' => trailingslashit( $this->themes_dir . '/bp-legacy' ),  
  677. 'url' => trailingslashit( $this->themes_url . '/bp-legacy' ) 
  678. ) ); 
  679.  
  680. // Register the basic theme stack. This is really dope. 
  681. bp_register_template_stack( 'get_stylesheet_directory', 10 ); 
  682. bp_register_template_stack( 'get_template_directory', 12 ); 
  683. bp_register_template_stack( 'bp_get_theme_compat_dir', 14 ); 
  684.  
  685. /** 
  686. * Set up the default BuddyPress theme compatibility location. 
  687. * 
  688. * @since 1.7.0 
  689. */ 
  690. public function setup_theme() { 
  691.  
  692. // Bail if something already has this under control 
  693. if ( ! empty( $this->theme_compat->theme ) ) { 
  694. return; 
  695.  
  696. // Setup the theme package to use for compatibility 
  697. bp_setup_theme_compat( bp_get_theme_package_id() ); 
.