Index: bp-loader.php
--- bp-loader.php
+++ bp-loader.php
@@ -34,206 +34,155 @@
  */
 class BuddyPress {
 
-	/**
-	 * Note to Plugin and Theme authors:
-	 *
-	 * Do not directly reference the variables below in your code. Their names
-	 * and locations in the BuddyPress class are subject to change at any time.
-	 *
-	 * Most of them have reference functions located in bp-core-functions.php.
-	 * The ones that don't can be accessed via their respective WordPress API's.
-	 *
-	 * Components are encouraged to store their data in the $bp global rather
-	 * than new globals to keep all BuddyPress data in one place.
-	 */
+	/** Magic *****************************************************************/
 
-	/** Version ***************************************************************/
-
 	/**
-	 * @var string BuddyPress version
-	 */
-	public $version = '1.7';
-
-	/**
-	 * @var int Database version of current BuddyPress files
-	 */
-	public $db_version = 6066;
-
-	/**
-	 * @var int Database version raw from database connection
-	 */
-	public $db_version_raw = 0;
-
-	/**
-	 * @var string State of BuddyPress installation
-	 */
-	public $maintenance_mode = '';
-
-	/**
-	 * @var bool Include deprecated BuddyPress files or not
-	 */
-	public $load_deprecated = true;
-
-	/** Root ******************************************************************/
-
-	/**
-	 * @var int The root blog ID
-	 */
-	public $root_blog_id = 1;
-
-	/** Paths *****************************************************************/
-
-	/**
-	 * The absolute path and filename of this file.
+	 * BuddyPress uses many variables, most of which can be filtered to customize
+	 * the way that it works. To prevent unauthorized access, these variables
+	 * are stored in a private array that is magically updated using PHP 5.2+
+	 * methods. This is to prevent third party plugins from tampering with
+	 * essential information indirectly, which would cause issues later.
 	 *
-	 * @since BuddyPress (1.6)
-	 * @var string
+	 * @see BuddyPress::setup_globals()
+	 * @var array
 	 */
-	public $file;
+	private $data;
 
-	/**
-	 * @var string Basename of the BuddyPress plugin directory
-	 */
-	public $basename = '';
+	/** Not Magic *************************************************************/
 
 	/**
-	 * @var string Absolute path to the BuddyPress plugin directory
+	 * @var array Primary BuddyPress navigation
 	 */
-	public $plugin_dir = '';
+	public $bp_nav = array();
 
 	/**
-	 * @var string Absolute path to the BuddyPress themes directory
+	 * @var array Secondary BuddyPress navigation to $bp_nav
 	 */
-	public $themes_dir = '';
+	public $bp_options_nav = array();
 
 	/**
-	 * @var string Absolute path to the BuddyPress language directory
+	 * @var array The unfiltered URI broken down into chunks
+	 * @see bp_core_set_uri_globals()
 	 */
-	public $lang_dir = '';
+	public $unfiltered_uri = array();
 
-	/** URLs ******************************************************************/
-
 	/**
-	 * @var string URL to the BuddyPress plugin directory
+	 * @var array The canonical URI stack
+	 * @see bp_redirect_canonical()
+	 * @see bp_core_new_nav_item()
 	 */
-	public $plugin_url = '';
+	public $canonical_stack = array();
 
 	/**
-	 * @var string URL to the BuddyPress themes directory
+	 * @var array Additional navigation elements (supplemental)
 	 */
-	public $themes_url = '';
+	public $action_variables = array();
 
-	/** Users *****************************************************************/
-
 	/**
-	 * @var object Current user
+	 * @var array Required components (core, members)
 	 */
-	public $current_user = null;
+	public $required_components = array();
 
 	/**
-	 * @var object Displayed user
+	 * @var array Additional active components
 	 */
-	public $displayed_user = null;
+	public $loaded_components = array();
 
-	/** Navigation ************************************************************/
+	/** Option Overload *******************************************************/
 
 	/**
-	 * @var array Primary BuddyPress navigation
+	 * @var array Optional Overloads default options retrieved from get_option()
 	 */
-	public $bp_nav = array();
+	public $options = array();
 
-	/**
-	 * @var array Secondary BuddyPress navigation to $bp_nav
-	 */
-	public $bp_options_nav = array();
+	/** Singleton *************************************************************/
 
-	/** Toolbar ***************************************************************/
-
 	/**
-	 * @var string The primary toolbar ID
+	 * @var BuddyPress The one true BuddyPress
 	 */
-	public $my_account_menu_id = '';
+	private static $instance;
 
-	/** URI's *****************************************************************/
-
 	/**
-	 * @var array The unfiltered URI broken down into chunks
-	 * @see bp_core_set_uri_globals()
+	 * Main BuddyPress Instance
+	 *
+	 * BuddyPress is great
+	 * Please load it only one time
+	 * For this, we thank you
+	 *
+	 * Insures that only one instance of BuddyPress exists in memory at any one
+	 * time. Also prevents needing to define globals all over the place.
+	 *
+	 * @since BuddyPress (1.7)
+	 *
+	 * @staticvar array $instance
+	 * @uses BuddyPress::constants() Setup the constants (mostly deprecated)
+	 * @uses BuddyPress::setup_globals() Setup the globals needed
+	 * @uses BuddyPress::includes() Include the required files
+	 * @uses BuddyPress::setup_actions() Setup the hooks and actions
+	 * @see buddypress()
+	 *
+	 * @return The one true BuddyPress
 	 */
-	public $unfiltered_uri = array();
+	public static function instance() {
+		if ( ! isset( self::$instance ) ) {
+			self::$instance = new BuddyPress;
+			self::$instance->constants();
+			self::$instance->setup_globals();
+			self::$instance->includes();
+			self::$instance->setup_actions();
+		}
+		return self::$instance;
+	}
 
-	/**
-	 * @var int The current offset of the URI
-	 * @see bp_core_set_uri_globals()
-	 */
-	public $unfiltered_uri_offset = 0;
+	/** Magic Methods *********************************************************/
 
 	/**
-	 * @var bool Are status headers already sent?
+	 * A dummy constructor to prevent BuddyPress from being loaded more than once.
+	 *
+	 * @since BuddyPress (1.7)
+	 * @see BuddyPress::instance()
+	 * @see buddypress()
 	 */
-	public $no_status_set = false;
+	private function __construct() { /* Do nothing here */ }
 
 	/**
-	 * @var array The canonical URI stack
-	 * @see bp_redirect_canonical()
-	 * @see bp_core_new_nav_item()
+	 * A dummy magic method to prevent BuddyPress from being cloned
+	 *
+	 * @since BuddyPress (1.7)
 	 */
-	public $canonical_stack = array();
+	public function __clone() { wp_die( __( 'Cheatin&#8217; huh?', 'buddypress' ) ); }
 
-	/** Components ************************************************************/
-
 	/**
-	 * @var string Name of the current BuddyPress component (primary)
+	 * A dummy magic method to prevent BuddyPress from being unserialized
+	 *
+	 * @since BuddyPress (1.7)
 	 */
-	public $current_component = '';
+	public function __wakeup() { wp_die( __( 'Cheatin&#8217; huh?', 'buddypress' ) ); }
 
 	/**
-	 * @var string Name of the current BuddyPress item (secondary)
+	 * Magic method for checking the existence of a certain custom field
+	 *
+	 * @since BuddyPress (1.7)
 	 */
-	public $current_item = '';
+	public function __isset( $key ) { return isset( $this->data[$key] ); }
 
 	/**
-	 * @var string Name of the current BuddyPress action (tertiary)
+	 * Magic method for getting BuddyPress varibles
+	 *
+	 * @since BuddyPress (1.7)
 	 */
-	public $current_action = '';
+	public function __get( $key ) { return isset( $this->data[$key] ) ? $this->data[$key] : null; }
 
 	/**
-	 * @var array Additional navigation elements (supplemental)
+	 * Magic method for setting BuddyPress varibles
+	 *
+	 * @since BuddyPress (1.7)
 	 */
-	public $action_variables = array();
+	public function __set( $key, $value ) { $this->data[$key] = $value; }
 
-	/**
-	 * @var bool Displaying custom 2nd level navigation menu (I.E a group)
-	 */
-	public $is_single_item = false;
+	/** Private Methods *******************************************************/
 
-	/** Option Overload *******************************************************/
-
 	/**
-	 * @var array Optional Overloads default options retrieved from get_option()
-	 */
-	public $options = array();
-
-	/** Functions *************************************************************/
-
-	/**
-	 * The main BuddyPress loader
-	 *
-	 * @since BuddyPress (1.6)
-	 *
-	 * @uses BuddyPress::constants() Setup legacy constants
-	 * @uses BuddyPress::setup_globals() Setup globals needed
-	 * @uses BuddyPress::includes() Includ required files
-	 * @uses BuddyPress::setup_actions() Setup hooks and actions
-	 */
-	public function __construct() {
-		$this->constants();
-		$this->setup_globals();
-		$this->includes();
-		$this->setup_actions();
-	}
-
-	/**
 	 * Legacy BuddyPress constants
 	 *
 	 * Try to avoid using these. Their values have been moved into variables
@@ -315,6 +264,59 @@
 	 */
 	private function setup_globals() {
 
+		/** Versions **********************************************************/
+
+		$this->version        = '1.7';
+		$this->db_version     = 6066;
+		$this->db_version_raw = 0;
+
+		/** Loading ***********************************************************/
+
+		$this->maintenance_mode = '';
+		$this->load_deprecated  = true;
+
+		/** Toolbar ***********************************************************/
+
+		/**
+		 * @var string The primary toolbar ID
+		 */
+		$this->my_account_menu_id = '';
+
+		/** URI's *************************************************************/
+
+		/**
+		 * @var int The current offset of the URI
+		 * @see bp_core_set_uri_globals()
+		 */
+		$this->unfiltered_uri_offset = 0;
+
+		/**
+		 * @var bool Are status headers already sent?
+		 */
+		$this->no_status_set = false;
+
+		/** Components ********************************************************/
+
+		/**
+		 * @var string Name of the current BuddyPress component (primary)
+		 */
+		$this->current_component = '';
+
+		/**
+		 * @var string Name of the current BuddyPress item (secondary)
+		 */
+		$this->current_item = '';
+
+		/**
+		 * @var string Name of the current BuddyPress action (tertiary)
+		 */
+		$this->current_action = '';
+
+		/**
+		 * @var bool Displaying custom 2nd level navigation menu (I.E a group)
+		 */
+		$this->is_single_item = false;
+	
 		/** Root **************************************************************/
 
 		// BuddyPress Root blog ID
@@ -481,9 +483,34 @@
 	}
 }
 
-// "And now for something completely different"
-$GLOBALS['bp'] = new BuddyPress;
+/**
+ * The main function responsible for returning the one true BuddyPress Instance
+ * to functions everywhere.
+ *
+ * Use this function like you would a global variable, except without needing
+ * to declare the global.
+ *
+ * Example: <?php $bp = buddypress(); ?>
+ *
+ * @return The one true BuddyPress Instance
+ */
+function buddypress() {
+	return buddypress::instance();
+}
 
-endif;
+/**
+ * Hook BuddyPress early onto the 'plugins_loaded' action.
+ *
+ * This gives all other plugins the chance to load before BuddyPress, to get
+ * their actions, filters, and overrides setup without BuddyPress being in the
+ * way.
+ */
+if ( defined( 'BUDDYPRESS_LATE_LOAD' ) ) {
+	add_action( 'plugins_loaded', 'buddypress', (int) BUDDYPRESS_LATE_LOAD );
 
-?>
+// "And now here's something we hope you'll really like!"
+} else {
+	$GLOBALS['bp'] = &buddypress();
+}
+
+endif;
