From e04c98d96bcc932a917b2b7e7944887e4839056a Mon Sep 17 00:00:00 2001 From: Luke Arms Date: Tue, 29 Mar 2022 08:20:23 +1100 Subject: [PATCH] Fix issue where 'shareInstances' resolve but fail to propagate (#201) * #200 - Expand shareInstances test to replicate propagation issue * #200 - Fix issue where 'shareInstances' resolve but fail to propagate Because `$share` is passed by reference to `matchParam()`, and `matchParam()` removes matching objects from its `$search` array, instances may be removed from `$share` before it is passed to `expand()` or `create()`. Depending on the order of constructor parameters and the relative placement of `shareInstances` dependencies in the object tree, this may result in multiple instances of these dependencies being created. Fixed by passing a copy of the `$share` array to `matchParam()`. --- Dice.php | 2 +- tests/ShareInstancesTest.php | 10 ++++++++++ tests/TestData/ShareInstances.php | 4 +++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Dice.php b/Dice.php index 72fc66c..f80dca8 100644 --- a/Dice.php +++ b/Dice.php @@ -235,7 +235,7 @@ private function getParams(\ReflectionMethod $method, array $rule) { $parameters[] = $match; } // Do the same with $share - else if ($share && ($match = $this->matchParam($param, $class, $share)) !== false) { + else if (($copy = $share) && ($match = $this->matchParam($param, $class, $copy)) !== false) { $parameters[] = $match; } // When nothing from $args or $share matches but a class is type hinted, create an instance to use, using a substitution if set diff --git a/tests/ShareInstancesTest.php b/tests/ShareInstancesTest.php index 080e304..7387582 100644 --- a/tests/ShareInstancesTest.php +++ b/tests/ShareInstancesTest.php @@ -18,7 +18,9 @@ public function testShareInstances() { $this->assertInstanceOf('SharedInstanceTest1', $shareTest->share1); $this->assertInstanceOf('SharedInstanceTest2', $shareTest->share2); + $this->assertSame($shareTest->shared, $shareTest->share1->shared); $this->assertSame($shareTest->share1->shared, $shareTest->share2->shared); + $this->assertEquals($shareTest->shared->uniq, $shareTest->share1->shared->uniq); $this->assertEquals($shareTest->share1->shared->uniq, $shareTest->share2->shared->uniq); } @@ -41,7 +43,9 @@ public function testNamedShareInstances() { $this->assertInstanceOf('SharedInstanceTest1', $shareTest->share1); $this->assertInstanceOf('SharedInstanceTest2', $shareTest->share2); + $this->assertSame($shareTest->shared, $shareTest->share1->shared); $this->assertSame($shareTest->share1->shared, $shareTest->share2->shared); + $this->assertEquals($shareTest->shared->uniq, $shareTest->share1->shared->uniq); $this->assertEquals($shareTest->share1->shared->uniq, $shareTest->share2->shared->uniq); @@ -72,15 +76,21 @@ public function testShareInstancesMultiple() { $this->assertInstanceOf('SharedInstanceTest1', $shareTest->share1); $this->assertInstanceOf('SharedInstanceTest2', $shareTest->share2); + $this->assertSame($shareTest->shared, $shareTest->share1->shared); $this->assertSame($shareTest->share1->shared, $shareTest->share2->shared); + $this->assertEquals($shareTest->shared->uniq, $shareTest->share1->shared->uniq); $this->assertEquals($shareTest->share1->shared->uniq, $shareTest->share2->shared->uniq); $shareTest2 = $dice->create('TestSharedInstancesTop'); + $this->assertSame($shareTest2->shared, $shareTest2->share1->shared); $this->assertSame($shareTest2->share1->shared, $shareTest2->share2->shared); + $this->assertEquals($shareTest2->shared->uniq, $shareTest2->share1->shared->uniq); $this->assertEquals($shareTest2->share1->shared->uniq, $shareTest2->share2->shared->uniq); + $this->assertNotSame($shareTest->shared, $shareTest2->shared); $this->assertNotSame($shareTest->share1->shared, $shareTest2->share2->shared); + $this->assertNotEquals($shareTest->shared->uniq, $shareTest2->shared->uniq); $this->assertNotEquals($shareTest->share1->shared->uniq, $shareTest2->share2->shared->uniq); } diff --git a/tests/TestData/ShareInstances.php b/tests/TestData/ShareInstances.php index 855a8ad..d02ef61 100644 --- a/tests/TestData/ShareInstances.php +++ b/tests/TestData/ShareInstances.php @@ -5,10 +5,12 @@ * @license http:// www.opensource.org/licenses/bsd-license.php BSD License * * @version 3.0 */ class TestSharedInstancesTop { + public $shared; public $share1; public $share2; - public function __construct(SharedInstanceTest1 $share1, SharedInstanceTest2 $share2) { + public function __construct(Shared $shared, SharedInstanceTest1 $share1, SharedInstanceTest2 $share2) { + $this->shared = $shared; $this->share1 = $share1; $this->share2 = $share2; }