class Horde_Injector implements Horde_Injector_Scope
{
/**
+ * Parent scope.
+ *
* @var Horde_Injector_Scope
*/
private $_parentInjector;
/**
+ * Binders for objects/instances.
+ *
* @var array
*/
private $_bindings = array();
/**
+ * Binders for objects/instances that are created on demand.
+ *
+ * @var array
+ */
+ private $_ondemand = array();
+
+ /**
+ * Created objects/instances.
+ *
* @var array
*/
private $_instances;
}
/**
- * Add a Horde_Injector_Binder to an interface
+ * Add a Horde_Injector_Binder to an interface.
*
* This is the method by which we bind an interface to a concrete
* implentation or factory. For convenience, binders may be added by
}
/**
+ * Add a Horde_Injector_Binder to an interface. Unlike addBinder(), the
+ * binder interface will not be created until it is first accessed.
+ *
+ * @see self::addBinder()
+ *
+ * @param string $interface The interface to bind to.
+ * @param string $name The name of the binder class to create.
+ *
+ * @return Horde_Injector A reference to itself for method chaining.
+ */
+ public function addOndemandBinder($interface, $name)
+ {
+ $this->_ondemand[$interface] = $name;
+ return $this;
+ }
+
+ /**
+ * Creates a binder object on demand from the current binder
+ * configuration.
+ *
+ * @param string $interface The interface to bind to.
+ */
+ private function _addOndemandBinder($interface)
+ {
+ if (!isset($this->_bindings[$interface]) &&
+ isset($this->_ondemand[$interface])) {
+ $binder = new $this->_ondemand[$interface]();
+ $this->_addBinder($interface, $binder);
+ unset($this->_ondemand[$interface]);
+ }
+ }
+
+ /**
* Get the Binder associated with the specified instance.
*
* Binders are objects responsible for binding a particular interface
*/
public function getBinder($interface)
{
+ $this->_addOndemandBinder($interface);
+
return isset($this->_bindings[$interface])
? $this->_bindings[$interface]
: $this->_parentInjector->getBinder($interface);
if (!isset($this->_instances[$interface])) {
// Do we have a binding for this interface? If so then we don't
// ask our parent
- if (!isset($this->_bindings[$interface])) {
+ if (!isset($this->_bindings[$interface]) &&
+ !isset($this->_ondemand[$interface])) {
// Does our parent have an instance?
if ($instance = $this->_parentInjector->getInstance($interface)) {
return $instance;
}
}
- // We have to make our own instance
+ // We have to make our own instance.
$this->setInstance($interface, $this->createInstance($interface));
}
$this->assertSame($binder, $injector->getBinder('BOUND_INTERFACE'));
}
+ public function testOndemandBoundBinder()
+ {
+ $injector = new Horde_Injector(new Horde_Injector_TopLevel());
+ $binder = new Horde_Injector_Binder_Mock();
+ $injector->addOndemandBinder('BOUND_INTERFACE', 'Horde_Injector_Binder_Mock');
+ $this->assertNotSame($binder, $injector->getBinder('BOUND_INTERFACE'));
+ }
+
public function testShouldProvideMagicFactoryMethodForBinderAddition()
{
$injector = new Horde_Injector(new Horde_Injector_TopLevel());