Index: wp-includes/class-wp-factory.php
===================================================================
--- wp-includes/class-wp-factory.php	(revision 0)
+++ wp-includes/class-wp-factory.php	(revision 0)
@@ -0,0 +1,330 @@
+<?php
+/**
+ * WP Factory class.
+ *
+ * @package WordPress
+ * @since 3.X
+ */
+class WP_Factory {
+	
+	/**
+	 * Protected registered classes.
+	 *
+	 * List of registered classes.
+	 *
+	 * @since 3.X
+	 * @access protected
+	 * @var array
+	 */
+	protected $registeredClasses;
+	
+	/**
+	 * Protected registered objects.
+	 *
+	 * List of registered objects.
+	 *
+	 * @since 3.X
+	 * @access protected
+	 * @var array
+	 */
+	protected $registeredObjects;
+	
+	/**
+	 * Class constructor.
+	 *
+	 * Initializes the registered classes and objects lists.
+	 *
+	 * @since 3.X
+	 * @access public
+	 * @uses add_action() Adds private method to 'muplugins_loaded' action hook.
+	 * @uses add_action() Adds private method to 'plugins_loaded' action hook.
+	 */
+	public function __construct() {
+		$this->registeredClasses = array();
+		$this->registeredObjects = array();
+		add_action( 'muplugins_loaded', array( $this, '_muPluginsLoaded' ), PHP_INT_MAX  );
+		add_action( 'plugins_loaded', array( $this, '_pluginsLoaded' ), PHP_INT_MAX  );
+	}
+	
+	/**
+	 * Register class to the object factory.
+	 *
+	 * The class name and file path must be passed.
+	 * Additionally, the class may replace another registered class (already or not),
+	 * and the replaced class name is passed as third argument.
+	 * Finally, the class may require another registered class (already or not),
+	 * and the required class name is passed as forth argument.
+	 *
+	 * @since 3.X
+	 * @access public
+	 *
+	 * @param string $name The class name.
+	 * @param string $file The absolute path of the class file.
+	 * @param string $replaces Optional. The name of the class to be replaced.
+	 * @param string $requires Optional. The name of the required class (most often the parent class).
+	 * @param string $extends Optional. The name of the class that must be extended.
+	 * @return true|WP_Error True in case of success and WP_Error in case of failure.
+	 */
+	public function registerClass( $name, $file, $replaces = false, $requires = false, $extends = false ) {
+		$result = true;
+		if ( file_exists( $file ) ) {
+			$this->registeredClasses[ $name ] = ( object ) array( 'file' => $file, 'substitute' => isset( $this->registeredClasses[ $name ] ) ? $this->registeredClasses[ $name ]->substitute : false, 'requires' => $requires, 'extends' => $extends );
+			if ( $replaces ) {
+				if ( isset( $this->registeredClasses[ $replaces ] ) ) {
+					$this->registeredClasses[ $replaces ]->substitute = $name;
+				} else {
+					$this->registeredClasses[ $replaces ] = ( object ) array( 'file' => false, 'substitute' => $name, 'requires' => false, 'extends' => false );
+				}
+			}
+		} else {
+			$result = new WP_Error( 'wp_factory_error', printf( __( 'Class file %s does not exist.' ), $file ) );
+		}
+		return $result;
+	}
+	
+	/**
+	 * Register object to the object factory.
+	 *
+	 * The unique name and the class of the object must be passed.
+	 * The class of the object must be previously registered.
+	 * Additionally, a single argument may be passed for construction of the object.
+	 * In case of multiple arguments required, an array must be used in the constructor.
+	 * Finally, an optional flag orders to instantiate the object on 'plugins_loaded' action.
+	 *
+	 * @since 3.X
+	 * @access public
+	 *
+	 * @param string $name The object name.
+	 * @param string $class The registered object class.
+	 * @param mixed $args Optional. The construction arguments.
+	 * @param bool $init Optional. The flag to instantiate the object on 'plugins_loaded' action.
+	 * @return true|WP_Error True in case of success and a WP_Error in case of failure.
+	 */
+	public function registerObject( $name, $class, $args = null, $init = false ) {
+		$result = true;
+		if ( isset( $this->registeredClasses[ $class ] ) ) {
+			$this->registeredObjects[ $name ] = ( object ) array( 'class' => $class, 'args' => $args, 'object' => $init );
+		} else {
+			$result = new WP_Error( 'wp_factory_error', printf( __( 'Class %s is not registered.' ), $class ) );
+		}
+		return $result;
+	}
+	
+	/**
+	 * Return the registration settings of the class.
+	 *
+	 * If the class is previously registered, the returned object has the following attributes:
+	 * 'file': its class path
+	 * 'substitute': the actual class that is used on object construction
+	 * 'requires': the name of its required class 
+	 *
+	 * @since 3.X
+	 * @access public
+	 *
+	 * @param string $name The class name.
+	 * @return object|null The registration settings object or null if not registered.
+	 */
+	public function getRegisteredClass( $name ) {
+		return isset( $this->registeredClasses[ $name ] ) ? clone( $this->registeredClasses[ $name ] ) : null;
+	}
+	
+	/**
+	 * Return the registration settings of the named object.
+	 *
+	 * If the object is previously registered with the same name, the returned object has the following attributes:
+	 * 'class': the class name it has been registered with
+	 * 'args': the array of arguments to be passed on construction
+	 * 'object': the object itself if already instanciated or the $init argument value it has been registered with
+	 *
+	 * @since 3.X
+	 * @access public
+	 *
+	 * @param string $name The object name.
+	 * @return object|null The registration settings object or null if not registered.
+	 */
+	public function getRegisteredObject( $name ) {
+		return isset( $this->registeredObjects[ $name ] ) ? clone( $this->registeredObjects[ $name ] ) : null;
+	}
+	
+	/**
+	 * Return the named object.
+	 *
+	 * The object must be previously registered.
+	 * Implements the singleton design pattern.
+	 *
+	 * @since 1.0
+	 * @access public
+	 * @uses self::newObject() Instantiate the singleton object
+	 *
+	 * @param string $name The object name.
+	 * @return object|WP_Error The singleton in case of success and a WP_Error in case of failure.
+	 */
+	public function getObject( $name ) {
+		$result = null;
+		if ( isset( $this->registeredObjects[ $name ] ) ) {
+			$data = $this->registeredObjects[ $name ];
+			if ( !is_object( $data->object ) || is_wp_error( $data->object ) ) {
+				$data->object = $this->newObject( $data->class, $data->args );
+			}
+			$result = $data->object;
+		} else {
+			$result = new WP_Error( 'wp_factory_error', printf( __( 'Object %s is not registered.' ), $name ) );
+		}
+		return $result;
+	}
+	
+	/**
+	 * Instantiate a polymorphic object.
+	 *
+	 * The class must be previously registered.
+	 * If an additional class has been registered to replace the original class,
+	 * the replacing class is instantiated instead.
+	 * The replacing class must inherit from the original class.
+	 * The optional construction argument is single and must be the same way in the class's constructor.
+	 * In case of multiple arguments required, an array must be used in the constructor.
+	 * Includes all required class files.
+	 *
+	 * @since 3.X
+	 * @access public
+	 *
+	 * @param string $class The object class name.
+	 * @param mixed $args Optional. The construction arguments.
+	 * @return object|WP_Error The desired object in case of success and a WP_Error in case of failure.
+	 */
+	public function newObject( $class, $args = null ) {
+		$result = false;
+		if ( isset( $this->registeredClasses[ $class ] ) ) {
+			$includes = array();
+			$this->addInclude( &$includes, $class );
+			foreach ( $includes as $include ) {
+				try {
+					require_once( $include );
+				} catch ( Exception $e ) {
+					$result = new WP_Error( 'wp_factory_error', $e->getMessage() );
+					break;
+				}
+			}
+			if ( !is_wp_error( $result ) ) {
+				$base_class = $this->registeredClasses[ $class ]->extends ? $this->registeredClasses[ $class ]->extends : $class;
+				if ( ( $base_class != $class ) && !is_subclass_of( $class, $base_class ) ) {
+					$result = new WP_Error( 'wp_factory_error', printf( __( 'Class %s does not extend %s.' ), $class, $base_class ) );
+				}
+			}
+			if ( !is_wp_error( $result ) ) {
+				$new_class = $this->registeredClasses[ $class ]->substitute ? $this->registeredClasses[ $class ]->substitute : $class;
+				if ( is_subclass_of( $new_class, $class ) ) {
+					try {
+						$result = new $new_class( $args );
+					} catch ( Exception $e ) {
+						$result = new WP_Error( 'wp_factory_error', $e->getMessage() );
+					}
+				} else {
+					$result = new WP_Error( 'wp_factory_error', printf( __( 'Class %s does not extend %s.' ), $new_class, $class ) );
+				}
+			}
+		} else {
+			$result = new WP_Error( 'wp_factory_error', printf( __( 'Class %s is not registered.' ), $class ) );
+		}
+		return $result;
+	}
+	
+	/**
+	 * Dispose an object from filters and action hooks and other dependencies
+	 * so it's no longer referenced by any current process.
+	 *
+	 * The object may or may not be created by the factory.
+	 *
+	 * @since 3.X
+	 * @access public
+	 * @uses remove_filter() Remove all filters and action hooks
+	 *
+	 * @param object &$object The object to be disposed.
+	 */
+	public function disposeObject( &$object ) {
+		// Integrated from wp-includes/plugin.php::remove_filter()
+		$functions_to_remove = array();
+		$tags = $GLOBALS[ 'wp_filter' ];
+		foreach ( $tags as $tag => $priorities ) {
+			foreach ( $priorities as $priority => $functions ) {
+				foreach ( $functions as $function_idx => $function ) {
+					if ( is_array( $function[ 'function' ] ) && ( $object == $function[ 'function' ][ 0 ] ) ) {
+						$functions_to_remove[] = array( $tag, $function[ 'function' ][ 1 ], $priority, $function[ 'accepted_args' ] );
+					}
+				}
+			}
+		}
+		foreach ( $functions_to_remove as $function ) {
+			remove_filter( $function[ 0 ], array( &$object, $function[ 1 ] ), $function[ 2 ], $function[ 3 ] );
+		}
+	}
+	
+	/**
+	 * Add include file to includes list.
+	 *
+	 * Recursive function.
+	 *
+	 * @since 3.X
+	 * @access protected
+	 *
+	 * @param array &$includes The list of includes.
+	 * @param string $class The class name.
+	 */
+	protected function addInclude( &$includes, $class ) {
+		if ( isset( $this->registeredClasses[ $class ] ) ) {
+			// 1. Include required classes first
+			if ( $this->registeredClasses[ $class ]->extends ) {
+				$this->addInclude( &$includes, $this->registeredClasses[ $class ]->extends );
+			}
+			if ( $this->registeredClasses[ $class ]->requires ) {
+				$this->addInclude( &$includes, $this->registeredClasses[ $class ]->requires );
+			}
+			// 2. Include current class
+			if ( !in_array( $this->registeredClasses[ $class ]->file, $includes ) ) {
+				$includes[] = $this->registeredClasses[ $class ]->file;
+			}
+			// 3. Include subsitute class at last
+			if ( $this->registeredClasses[ $class ]->substitute ) {
+				$this->addInclude( &$includes, $this->registeredClasses[ $class ]->substitute );
+			}
+		}
+	}
+	
+	/**
+	 * Instantiate objects flagged as such.
+	 *
+	 * @since 3.X
+	 * @access protected
+	 *
+	 * @param bool|string $init The instantiation flag.
+	 */
+	protected function initObjects( $init ) {
+		foreach ( $this->registeredObjects as $name => $data ) {
+			if ( $data->object === $init ) {
+				$data->object = $this->newObject( $data->class, $data->args );
+			}
+		}
+	}
+	
+	/**
+	 * 'muplugins_loaded' action hook.
+	 *
+	 * @since 3.X
+	 * @access private
+	 * @uses self::initObjects() 'muplugins' instantiation flag
+	 */
+	function _muPluginsLoaded() {
+		$this->initObjects( 'muplugins' );
+	}
+	
+	/**
+	 * 'plugins_loaded' action hook.
+	 *
+	 * @since 3.X
+	 * @access private
+	 * @uses self::initObjects() True instantiation flag
+	 */
+	function _pluginsLoaded() {
+		$this->initObjects( true );
+	}
+	
+}
Index: wp-includes/factory.php
===================================================================
--- wp-includes/factory.php	(revision 0)
+++ wp-includes/factory.php	(revision 0)
@@ -0,0 +1,217 @@
+<?php
+/**
+ * WordPress Core API for object factory
+ *
+ * @package WordPress
+ * @since 3.X
+ */
+
+/**
+ * Register class to the object factory.
+ *
+ * This function is a proxy interface of the 'wp_factory' object's method.
+ * The class name and file path must be passed.
+ * Additionally, the class may replace another registered class (already or not),
+ * and the replaced class name is passed as third argument.
+ * Finally, the class may require another registered class (already or not),
+ * and the required class name is passed as forth argument.
+ *
+ * @since 3.X
+ * @uses WP_Factory::registerClass() Delegate to the 'wp_factory' object.
+ * @uses do_action() Calls 'wp_class_registered' once the class is registered.
+ * 	Same arguments are passed.
+ *
+ * @param string $name The class name.
+ * @param string $file The absolute path of the class file.
+ * @param string $replaces Optional. The name of the class to be replaced.
+ * @param string $requires Optional. The name of the required class (most often the parent class).
+ * @param string $extends Optional. The name of the class that must be extended.
+ * @return bool|WP_Error True in case of success and WP_Error in case of failure.
+ */
+function wp_register_class( $name, $file, $replaces = false, $requires = false, $extends = false ) {
+	$factory = wp_get_object( 'wp_factory' );
+	$result = true;
+	if ( is_a( $factory, 'WP_Factory' ) ) {
+		$result = $factory->registerClass( $name, $file, $replaces, $requires, $extends );
+	} else {
+		$result = new WP_Error( 'wp_factory_error', __( 'Factory is not a WP_Factory instance.' ) );
+	}
+	if ( $result && !is_wp_error( $result ) ) {
+		do_action( 'wp_class_registered', $name, $file, $replaces, $requires, $extends );
+	}
+	return $result;
+}
+
+/**
+ * Register object to the object factory.
+ *
+ * This function is a proxy interface of the 'wp_factory' object's method.
+ * The unique name and the class of the object must be passed.
+ * The class of the object must be previously registered.
+ * Additionally, a single argument may be passed for construction of the object.
+ * In case of multiple arguments required, an array must be used in the constructor.
+ * Finally, an optional flag orders to instantiate the object on 'plugins_loaded' action.
+ *
+ * @since 3.X
+ * @uses WP_Factory::registerObject() Delegate to the 'wp_factory' object.
+ * @uses do_action() Calls 'wp_object_registered' once the object is registered.
+ * 	Same arguments are passed.
+ *
+ * @param string $name The object name.
+ * @param string $class The registered object class.
+ * @param mixed $args Optional. The construction arguments.
+ * @param bool $init Optional. The flag to instantiate the object on 'plugins_loaded' action.
+ * @return bool|WP_Error True in case of success and a WP_Error in case of failure.
+ */
+function wp_register_object( $name, $class, $args = null, $init = false ) {
+	$factory = wp_get_object( 'wp_factory' );
+	$result = true;
+	if ( is_a( $factory, 'WP_Factory' ) ) {
+		$result = $factory->registerObject( $name, $class, $args, $init );
+	} else {
+		$result = new WP_Error( 'wp_factory_error', __( 'Factory is not a WP_Factory instance.' ) );
+	}
+	if ( $result && !is_wp_error( $result ) ) {
+		do_action( 'wp_object_registered', $name, $class, $args, $init );
+	}
+	return $result;
+}
+
+/**
+ * Return the registration settings of the class.
+ *
+ * If the class is previously registered, the returned object has the following attributes:
+ * 'file': its class path
+ * 'substitute': the actual class that is used on object construction
+ * 'requires': the name of its required class 
+ *
+ * @since 3.X
+ * @uses WP_Factory::getRegisteredClass() Delegate to the 'wp_factory' object.
+ * @uses apply_filters() Applies 'wp_registered_class' on the returned object.
+ *
+ * @param string $name The class name.
+ * @return object|null|WP_Error The registration settings object or null if not registered or WP_Error in case of error.
+ */
+function wp_get_registered_class( $name ) {
+	$factory = wp_get_object( 'wp_factory' );
+	$result = null;
+	if ( is_a( $factory, 'WP_Factory' ) ) {
+		$result = $factory->getRegisteredClass( $name );
+	} else {
+		$result = new WP_Error( 'wp_factory_error', __( 'Factory is not a WP_Factory instance.' ) );
+	}
+	if ( !is_wp_error( $result ) ) {
+		$result = apply_filters( 'wp_registered_class', $result, $name );
+	}
+	return $result;
+}
+
+/**
+ * Return the registration settings of the named object.
+ *
+ * If the object is previously registered with the same name, the returned object has the following attributes:
+ * 'class': the class name it has been registered with
+ * 'args': the array of arguments to be passed on construction
+ * 'object': the object itself if already instanciated or the $init argument value it has been registered with
+ *
+ * @since 3.X
+ * @uses WP_Factory::getRegisteredObject() Delegate to the 'wp_factory' object.
+ * @uses apply_filters() Applies 'wp_registered_object' on the returned object.
+ *
+ * @param string $name The object name.
+ * @return object|null|WP_Error The registration settings object or null if not registered or WP_Error in case of error.
+ */
+function wp_get_registered_object( $name ) {
+	$factory = wp_get_object( 'wp_factory' );
+	$result = null;
+	if ( is_a( $factory, 'WP_Factory' ) ) {
+		$result = $factory->getRegisteredObject( $name );
+	} else {
+		$result = new WP_Error( 'wp_factory_error', __( 'Factory is not a WP_Factory instance.' ) );
+	}
+	if ( !is_wp_error( $result ) ) {
+		$result = apply_filters( 'wp_registered_object', $result, $name );
+	}
+	return $result;
+}
+
+/**
+ * Return the named object.
+ *
+ * This function is a proxy interface of the 'wp_factory' object's method.
+ * The object must be previously registered.
+ * Implements the singleton design pattern.
+ *
+ * @since 3.X
+ * @uses WP_Factory::getObject() Delegate to the 'wp_factory' object.
+ *
+ * @param string $name The object name.
+ * @return object|WP_Error The singleton in case of success and a WP_Error in case of failure.
+ */
+function wp_get_object( $name ) {
+	global $wp_factory;
+	if ( is_null( $wp_factory ) ) {
+		require_once( path_join( ABSPATH . WPINC, 'class-wp-factory.php' ) );
+		$wp_factory = new WP_Factory();
+	}
+	$result = null;
+	if ( $name == 'wp_factory' ) {
+		$result = $wp_factory;
+	} else {
+		$result = $wp_factory->getObject( $name );
+	}
+	return $result;
+}
+
+/**
+ * Instantiate a polymorphic object.
+ *
+ * This function is a proxy interface of the 'wp_factory' object's method.
+ * The class must be previously registered.
+ * If an additional class has been registered to replace the original class,
+ * the replacing class is instantiated instead.
+ * The replacing class must inherit from the original class.
+ * The optional construction argument is single and must be the same way in the class's constructor.
+ * In case of multiple arguments required, an array must be used in the constructor.
+ * Includes all required class files.
+ *
+ * @since 3.X
+ * @uses WP_Factory::newObject() Delegate to the 'wp_factory' object.
+ *
+ * @param string $class The object class name.
+ * @param mixed $args Optional. The construction arguments.
+ * @return object|WP_Error The desired object in case of success and a WP_Error in case of failure.
+ */
+function wp_new_object( $class, $args = null ) {
+	$factory = wp_get_object( 'wp_factory' );
+	$result = true;
+	if ( is_a( $factory, 'WP_Factory' ) ) {
+		$result = $factory->newObject( $class, $args );
+	} else {
+		$result = new WP_Error( 'wp_factory_error', __( 'Factory is not a WP_Factory instance.' ) );
+	}
+	return $result;
+}
+
+/**
+ * Dispose an object from filters and action hooks and other dependencies
+ * so it's no longer referenced by any current process.
+ *
+ * The object may or may not be created by the factory.
+ *
+ * @since 3.X
+ * @uses WP_Factory::disposeObject() Delegate to the 'wp_factory' object.
+ *
+ * @param object &$object The object to be disposed.
+ * @return bool|WP_Error True in case of success and a WP_Error in case of failure.
+ */
+function wp_dispose_object( &$object ) {
+	$factory = wp_get_object( 'wp_factory' );
+	$result = true;
+	if ( is_a( $factory, 'WP_Factory' ) ) {
+		$factory->disposeObject( &$object );
+	} else {
+		$result = new WP_Error( 'wp_factory_error', __( 'Factory is not a WP_Factory instance.' ) );
+	}
+	return $result;
+}
Index: wp-settings.php
===================================================================
--- wp-settings.php	(revision 23179)
+++ wp-settings.php	(working copy)
@@ -63,6 +63,7 @@
 // Load early WordPress files.
 require( ABSPATH . WPINC . '/compat.php' );
 require( ABSPATH . WPINC . '/functions.php' );
+require( ABSPATH . WPINC . '/factory.php' );
 require( ABSPATH . WPINC . '/class-wp.php' );
 require( ABSPATH . WPINC . '/class-wp-error.php' );
 require( ABSPATH . WPINC . '/plugin.php' );
