binder bind instance method

This commit is contained in:
Yuri Kuznetsov
2021-04-15 13:57:43 +03:00
parent 9b7313ce95
commit 9f7ed802ea
3 changed files with 136 additions and 26 deletions
+33 -10
View File
@@ -48,9 +48,7 @@ class Binder
*/
public function bindImplementation(string $key, string $implementationClassName): self
{
if (!$key || $key[0] === '$') {
throw new LogicException("Can't binding a parameter name globally.");
}
$this->validateBindingKey($key);
$this->data->addGlobal(
$key,
@@ -68,9 +66,7 @@ class Binder
*/
public function bindService(string $key, string $serviceName): self
{
if (!$key || $key[0] === '$') {
throw new LogicException("Can't binding a parameter name globally.");
}
$this->validateBindingKey($key);
$this->data->addGlobal(
$key,
@@ -81,16 +77,14 @@ class Binder
}
/**
* Bind an interface or parameter name to a callback.
* Bind an interface to a callback.
*
* @param $key An interface or interface with a parameter name (`Interface $name`).
* @param $callback A callback that will resolve a dependency.
*/
public function bindCallback(string $key, callable $callback): self
{
if (!$key || $key[0] === '$') {
throw new LogicException("Can't binding a parameter name globally.");
}
$this->validateBindingKey($key);
$this->data->addGlobal(
$key,
@@ -100,6 +94,24 @@ class Binder
return $this;
}
/**
* Bind an interface to a specific instance.
*
* @param $key An interface or interface with a parameter name (`Interface $name`).
* @param $instance An instance.
*/
public function bindInstance(string $key, object $instance): self
{
$this->validateBindingKey($key);
$this->data->addGlobal(
$key,
Binding::createFromValue($instance)
);
return $this;
}
/**
* Creates a contextual binder.
*
@@ -109,4 +121,15 @@ class Binder
{
return new ContextualBinder($this->data, $className);
}
private function validateBindingKey(string $key): void
{
if (!$key) {
throw new LogicException("Bad binding.");
}
if ($key[0] === '$') {
throw new LogicException("Can't binding a parameter name w/o an interface globally.");
}
}
}
@@ -51,9 +51,7 @@ class ContextualBinder
*/
public function bindImplementation(string $key, string $implementationClassName): self
{
if (!$key || $key[0] === '$') {
throw new LogicException("Bad binding.");
}
$this->validateBindingKeyNoParameterName($key);
$this->data->addContext(
$this->className,
@@ -67,14 +65,12 @@ class ContextualBinder
/**
* Bind an interface to a specific service.
*
* @param $key An interface, parameter name (`$name`) or interface with a parameter name (`Interface $name`).
* @param $key An interface or interface with a parameter name (`Interface $name`).
* @param $serviceName A service name.
*/
public function bindService(string $key, string $serviceName): self
{
if (!$key || $key[0] === '$') {
throw new LogicException("Bad binding.");
}
$this->validateBindingKeyNoParameterName($key);
$this->data->addContext(
$this->className,
@@ -88,11 +84,13 @@ class ContextualBinder
/**
* Bind an interface or parameter name to a specific value.
*
* @param $key An interface, parameter name (`$name`) or interface with a parameter name (`Interface $name`).
* @param $key Parameter name (`$name`) or interface with a parameter name (`Interface $name`).
* @param $value A value of any type.
*/
public function bindValue(string $key, $value): self
{
$this->validateBindingKeyParameterName($key);
$this->data->addContext(
$this->className,
$key,
@@ -102,14 +100,36 @@ class ContextualBinder
return $this;
}
/**
* Bind an interface to a specific instance.
*
* @param $key An interface or interface with a parameter name (`Interface $name`).
* @param $instance An instance.
*/
public function bindInstance(string $key, object $instance): self
{
$this->validateBindingKeyNoParameterName($key);
$this->data->addContext(
$this->className,
$key,
Binding::createFromValue($instance)
);
return $this;
}
/**
* Bind an interface or parameter name to a callback.
*
* @param $key An interface, parameter name (`$name`) or interface with a parameter name (`Interface $name`).
* @param $key An interface, parameter name (`$name`) or
* interface with a parameter name (`Interface $name`).
* @param $callback A callback that will resolve a dependency.
*/
public function bindCallback(string $key, callable $callback): self
{
$this->validateBinding($key);
$this->data->addContext(
$this->className,
$key,
@@ -118,4 +138,29 @@ class ContextualBinder
return $this;
}
private function validateBinding(string $key): void
{
if (!$key) {
throw new LogicException("Bad binding.");
}
}
private function validateBindingKeyNoParameterName(string $key): void
{
$this->validateBinding($key);
if ($key[0] === '$') {
throw new LogicException("Can't bind a parameter name w/o an interface.");
}
}
private function validateBindingKeyParameterName(string $key): void
{
$this->validateBinding($key);
if (strpos($key, '$') === false) {
throw new LogicException("Can't bind w/o a parameter name.");
}
}
}
@@ -43,9 +43,14 @@ use ReflectionNamedType;
class BindingContainerTest extends \PHPUnit\Framework\TestCase
{
/**
* @var Binder
*/
private $binder;
protected function setUp() : void
{
$this->loader = $this->getMockBuilder(BindingLoader::class)->disableOriginalConstructor()->getMock();
$this->loader = $this->createMock(BindingLoader::class);
$this->data = new BindingData();
@@ -59,7 +64,7 @@ class BindingContainerTest extends \PHPUnit\Framework\TestCase
protected function createClassMock(string $className) : ReflectionClass
{
$class = $this->getMockBuilder(ReflectionClass::class)->disableOriginalConstructor()->getMock();
$class = $this->createMock(ReflectionClass::class);
$class
->expects($this->any())
@@ -71,11 +76,11 @@ class BindingContainerTest extends \PHPUnit\Framework\TestCase
protected function createParamMock(string $name, ?string $className = null) : ReflectionParameter
{
$param = $this->getMockBuilder(ReflectionParameter::class)->disableOriginalConstructor()->getMock();
$param = $this->createMock(ReflectionParameter::class);
$class = null;
$type = $this->getMockBuilder(ReflectionNamedType::class)->disableOriginalConstructor()->getMock();
$type = $this->createMock(ReflectionNamedType::class);
if ($className) {
$class = $this->createClassMock($className);
@@ -114,7 +119,7 @@ class BindingContainerTest extends \PHPUnit\Framework\TestCase
return $param;
}
protected function createContainer()
protected function createContainer(): BindingContainer
{
return new BindingContainer($this->loader->load());
}
@@ -292,6 +297,44 @@ class BindingContainerTest extends \PHPUnit\Framework\TestCase
$this->assertIsCallable($binding->getValue());
}
public function testBindInstance()
{
$className = 'Espo\\Core\\Application';
$instance = $this->createMock($className);
$this->binder->bindInstance($className, $instance);
$param = $this->createParamMock('test', $className);
$binding = $this->createContainer()->get(null, $param);
$this->assertEquals(Binding::VALUE, $binding->getType());
$this->assertSame($instance, $binding->getValue());
}
public function testContextBindInstance()
{
$className = 'Espo\\Core\\Application';
$instance = $this->createMock($className);
$this->binder
->for('Espo\\Context')
->bindInstance($className, $instance);
$param = $this->createParamMock('test', $className);
$class = $this->createClassMock('Espo\\Context');
$binding = $this->createContainer()->get($class, $param);
$this->assertEquals(Binding::VALUE, $binding->getType());
$this->assertSame($instance, $binding->getValue());
}
public function testContextGetCallback()
{
$this->binder
@@ -373,7 +416,6 @@ class BindingContainerTest extends \PHPUnit\Framework\TestCase
$this->assertEquals('Espo\\ImplTest', $binding->getValue());
}
public function testNoContextClassName()
{
$this->binder
@@ -439,7 +481,7 @@ class BindingContainerTest extends \PHPUnit\Framework\TestCase
$this->binder
->for('Espo\\Context')
->bindValue('Espo\\SomeClass', $instance);
->bindValue('Espo\\SomeClass $test', $instance);
$class = $this->createClassMock('Espo\\Context');