Skip to content

Commit

Permalink
Allow extend to accept any callable (Fix #21)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbabker committed Jun 19, 2017
1 parent 723747e commit 9f29c94
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 17 deletions.
76 changes: 64 additions & 12 deletions Tests/ResourceDecorationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,16 @@
class ResourceDecoration extends TestCase
{
/**
* @testdox An extended resource replaces the original resource
* Value used within resource methods
*
* @var integer
*/
public function testExtend()
private $value = 42;

/**
* @testdox An extended resource replaces the original resource with a Closure
*/
public function testExtendClosure()
{
$container = new Container();
$container->share(
Expand All @@ -30,23 +37,46 @@ function ()
}
);

$value = 42;

$container->extend(
'foo',
function ($shared) use ($value)
function ($shared)
{
$shared->value = $value;
$shared->value = $this->value;

return $shared;
}
);

$one = $container->get('foo');
$this->assertEquals($value, $one->value);
$this->assertEquals($this->value, $one->value);

$two = $container->get('foo');
$this->assertEquals($value, $two->value);
$this->assertEquals($this->value, $two->value);

$this->assertSame($one, $two);
}

/**
* @testdox An extended resource replaces the original resource with a callback function
*/
public function testExtendCallback()
{
$container = new Container();
$container->share(
'foo',
[$this, 'baseCallable']
);

$container->extend(
'foo',
[$this, 'decoratingCallable']
);

$one = $container->get('foo');
$this->assertEquals($this->value, $one->value);

$two = $container->get('foo');
$this->assertEquals($this->value, $two->value);

$this->assertSame($one, $two);
}
Expand Down Expand Up @@ -98,16 +128,38 @@ function ()
}
);

$value = 42;

$container->extend(
'foo',
function ($shared) use ($value)
function ($shared)
{
$shared->value = $value;
$shared->value = $this->value;

return $shared;
}
);
}

/**
* A base method defining a resource in a container
*
* @return \stdClass
*/
public function baseCallable()
{
return new \stdClass;
}

/**
* Method defining the decorating instruction for a container's resource
*
* @param \stdClass $shared The return from the resource that was decorated
*
* @return \stdClass
*/
public function decoratingCallable($shared)
{
$shared->value = $this->value;

return $shared;
}
}
11 changes: 6 additions & 5 deletions src/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -341,26 +341,27 @@ public function createChild()
}

/**
* Extend a defined service Closure by wrapping the existing one with a new Closure. This
* works very similar to a decorator pattern. Note that this only works on service Closures
* Extend a defined service Closure by wrapping the existing one with a new callable function.
*
* This works very similar to a decorator pattern. Note that this only works on service Closures
* that have been defined in the current Provider, not parent providers.
*
* @param string $resourceName The unique identifier for the Closure or property.
* @param \Closure $callable A Closure to wrap the original service Closure.
* @param callable $callable A callable to wrap the original service Closure.
*
* @return void
*
* @since 1.0
* @throws \InvalidArgumentException
*/
public function extend($resourceName, \Closure $callable)
public function extend($resourceName, callable $callable)
{
$key = $this->resolveAlias($resourceName);
$resource = $this->getResource($key, true);

$closure = function ($c) use ($callable, $resource)
{
return $callable($resource->getInstance(), $c);
return call_user_func($callable, $resource->getInstance(), $c);
};

$this->set($key, $closure, $resource->isShared());
Expand Down

0 comments on commit 9f29c94

Please sign in to comment.