From 4f335c1af251af94ffc5711010bb7b719da36f55 Mon Sep 17 00:00:00 2001 From: Asis Pattisahusiwa Date: Sat, 11 Jul 2020 22:39:52 +0900 Subject: [PATCH 1/3] Fix #186, inherit global rules --- Dice.php | 22 +++++-- tests/GlobalRuleTest.php | 114 ++++++++++++++++++++++++++++++++++ tests/TestData/GlobalRule.php | 68 ++++++++++++++++++++ 3 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 tests/GlobalRuleTest.php create mode 100644 tests/TestData/GlobalRule.php diff --git a/Dice.php b/Dice.php index b75299b..9b3bfb4 100644 --- a/Dice.php +++ b/Dice.php @@ -55,8 +55,23 @@ private function addRuleTo(Dice $dice, string $name, array $rule) { if (isset($rule['substitutions'])) foreach($rule['substitutions'] as $key => $value) $rule['substitutions'][ltrim($key, '\\')] = $value; //Clear any existing instance or cache for this class unset($dice->instances[$name], $dice->cache[$name]); - $dice->rules[ltrim(strtolower($name), '\\')] = array_replace_recursive($dice->getRule($name), $rule); - } + $rules = array_replace_recursive($dice->getRule($name), $rule); + + if ($name !== '*') { + $rules = $this->appendGlobalRule($rules); + } + + $dice->rules[ltrim(strtolower($name), '\\')] = $rules; + } + + private function appendGlobalRule(array $rules) : array + { + $globalRules = isset($this->rules['*']) ? $this->rules['*'] : []; + if (!isset($globalRules['substitutions'])) return $rules; + + $rules['substitutions'] = array_merge($globalRules['substitutions'], $rules['substitutions']); + return $rules; + } /** * Returns the rule that will be applied to the class $name when calling create() @@ -191,8 +206,7 @@ private function expand($param, array $share = [], bool $createFromString = fals } /** * Looks through the array $search for any object which can be used to fulfil $param - The original array $search is modifed so must be passed by reference. - + * The original array $search is modifed so must be passed by reference. */ private function matchParam(\ReflectionParameter $param, $class, array &$search) { foreach ($search as $i => $arg) { diff --git a/tests/GlobalRuleTest.php b/tests/GlobalRuleTest.php new file mode 100644 index 0000000..7894359 --- /dev/null +++ b/tests/GlobalRuleTest.php @@ -0,0 +1,114 @@ + | https:// r.je/dice.html * + * @license http:// www.opensource.org/licenses/bsd-license.php BSD License * + * @version 3.0 */ +class GlobalRuleTest extends DiceTest +{ + public function testGlobal1() + { + $rule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $dice = $this->dice->addRule('*', $rule); + + $obj = $dice->create('Global1'); + + $this->assertInstanceOf('GlobalImplementation', $obj->obj); + } + + public function testGlobal2() + { + $rule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $dice = $this->dice->addRule('*', $rule); + + $obj = $dice->create('Global2'); + + $this->assertInstanceOf('GlobalImplementation', $obj->obj); + } + + public function testGlobal3() + { + $rule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $dice = $this->dice->addRule('*', $rule); + + $obj = $dice->create('Global3'); + + $this->assertInstanceOf('GlobalImplementation', $obj->obj); + } + + public function testGlobal4() + { + $rule = [ + 'substitutions' => [ + 'GlobalRuleInterface' => 'GlobalRuleImplementation', + 'GlobalInterface' => 'GlobalImplementation' + ] + ]; + $dice = $this->dice->addRule('*', $rule); + + $obj = $dice->create('Global4'); + + $this->assertInstanceOf('GlobalImplementation', $obj->glb); + $this->assertInstanceOf('GlobalRuleImplementation', $obj->glbr); + } + + public function testGlobal4_1() + { + $glbRule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $glb4Rule = [ + 'substitutions' => ['GlobalRuleInterface' => 'GlobalRuleImplementation'] + ]; + $dice = $this->dice->addRule('*', $glbRule); + $dice = $dice->addRule('Global4', $glb4Rule); + + $obj = $dice->create('Global4'); + + $this->assertInstanceOf('GlobalImplementation', $obj->glb); + $this->assertInstanceOf('GlobalRuleImplementation', $obj->glbr); + } + + public function testGlobal4_2() + { + $glbRule = [ + 'substitutions' => ['GlobalRuleInterface' => 'GlobalRuleImplementation'] + ]; + $glb4Rule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $dice = $this->dice->addRule('*', $glbRule); + $dice = $dice->addRule('Global4', $glb4Rule); + + $obj = $dice->create('Global4'); + + $this->assertInstanceOf('GlobalImplementation', $obj->glb); + $this->assertInstanceOf('GlobalRuleImplementation', $obj->glbr); + } + + public function testGlobal4_3() + { + $glbRule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $glb4Rule = [ + 'substitutions' => [ + 'GlobalInterface' => 'AnotherGlobalImplementation', + 'GlobalRuleInterface' => 'GlobalRuleImplementation' + ] + ]; + $dice = $this->dice->addRule('*', $glbRule); + $dice = $dice->addRule('Global4', $glb4Rule); + + $obj = $dice->create('Global4'); + + $this->assertInstanceOf('AnotherGlobalImplementation', $obj->glb); + $this->assertInstanceOf('GlobalRuleImplementation', $obj->glbr); + } +} diff --git a/tests/TestData/GlobalRule.php b/tests/TestData/GlobalRule.php new file mode 100644 index 0000000..9c6565a --- /dev/null +++ b/tests/TestData/GlobalRule.php @@ -0,0 +1,68 @@ +obj = $obj; + } +} + +class Global2 +{ + public $std; + public $obj; + public function __construct(stdClass $std, GlobalInterface $obj) + { + $this->std = $std; + $this->obj = $obj; + } +} + +class Global3 +{ + public $obj; + public $std; + public function __construct(GlobalInterface $obj, stdClass $std) + { + $this->obj = $obj; + $this->std = $std; + } +} + +class Global4 +{ + public $glb; + public $glbr; + public function __construct(GlobalInterface $glb, GlobalRuleInterface $glbr) + { + $this->glb = $glb; + $this->glbr = $glbr; + } +} From 8d7f10fb9946c80ce96388739484a35611449f27 Mon Sep 17 00:00:00 2001 From: Asis Pattisahusiwa Date: Sun, 12 Jul 2020 00:34:28 +0900 Subject: [PATCH 2/3] Append global rule should be added in getRule function --- Dice.php | 30 +++++++++++++----------------- tests/GlobalRuleTest.php | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/Dice.php b/Dice.php index 9b3bfb4..ffe62a0 100644 --- a/Dice.php +++ b/Dice.php @@ -55,22 +55,7 @@ private function addRuleTo(Dice $dice, string $name, array $rule) { if (isset($rule['substitutions'])) foreach($rule['substitutions'] as $key => $value) $rule['substitutions'][ltrim($key, '\\')] = $value; //Clear any existing instance or cache for this class unset($dice->instances[$name], $dice->cache[$name]); - $rules = array_replace_recursive($dice->getRule($name), $rule); - - if ($name !== '*') { - $rules = $this->appendGlobalRule($rules); - } - - $dice->rules[ltrim(strtolower($name), '\\')] = $rules; - } - - private function appendGlobalRule(array $rules) : array - { - $globalRules = isset($this->rules['*']) ? $this->rules['*'] : []; - if (!isset($globalRules['substitutions'])) return $rules; - - $rules['substitutions'] = array_merge($globalRules['substitutions'], $rules['substitutions']); - return $rules; + $dice->rules[ltrim(strtolower($name), '\\')] = array_replace_recursive($dice->getRule($name), $rule); } /** @@ -80,7 +65,7 @@ private function appendGlobalRule(array $rules) : array */ public function getRule(string $name): array { $lcName = strtolower(ltrim($name, '\\')); - if (isset($this->rules[$lcName])) return $this->rules[$lcName]; + if (isset($this->rules[$lcName])) return $this->appendGlobalRule($lcName, $this->rules[$lcName]); foreach ($this->rules as $key => $rule) { // Find a rule which matches the class described in $name where: if (empty($rule['instanceOf']) // It's not a named instance, the rule is applied to a class name @@ -93,6 +78,17 @@ public function getRule(string $name): array { return isset($this->rules['*']) ? $this->rules['*'] : []; } + private function appendGlobalRule(string $name, array $rules) : array + { + if ($name === '*') return $rules; + + $globalRules = isset($this->rules['*']) ? $this->rules['*'] : []; + if (!isset($globalRules['substitutions'])) return $rules; + + $rules['substitutions'] = array_merge($globalRules['substitutions'], $rules['substitutions']); + return $rules; + } + /** * Returns a fully constructed object based on $name using $args and $share as constructor arguments if supplied * @param string name The name of the class to instantiate diff --git a/tests/GlobalRuleTest.php b/tests/GlobalRuleTest.php index 7894359..928fed4 100644 --- a/tests/GlobalRuleTest.php +++ b/tests/GlobalRuleTest.php @@ -111,4 +111,41 @@ public function testGlobal4_3() $this->assertInstanceOf('AnotherGlobalImplementation', $obj->glb); $this->assertInstanceOf('GlobalRuleImplementation', $obj->glbr); } + + public function testGlobal4_4() + { + $glbRule = [ + 'substitutions' => ['GlobalRuleInterface' => 'GlobalRuleImplementation'] + ]; + $glb4Rule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $dice = $this->dice->addRule('Global4', $glb4Rule); + $dice = $dice->addRule('*', $glbRule); + + $obj = $dice->create('Global4'); + + $this->assertInstanceOf('GlobalImplementation', $obj->glb); + $this->assertInstanceOf('GlobalRuleImplementation', $obj->glbr); + } + + public function testGlobal4_5() + { + $glbRule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $glb4Rule = [ + 'substitutions' => [ + 'GlobalInterface' => 'AnotherGlobalImplementation', + 'GlobalRuleInterface' => 'GlobalRuleImplementation' + ] + ]; + $dice = $this->dice->addRule('Global4', $glb4Rule); + $dice = $dice->addRule('*', $glbRule); + + $obj = $dice->create('Global4'); + + $this->assertInstanceOf('AnotherGlobalImplementation', $obj->glb); + $this->assertInstanceOf('GlobalRuleImplementation', $obj->glbr); + } } From 8082bf19f679659b866b54cd1208ddbb1a312ba4 Mon Sep 17 00:00:00 2001 From: Asis Pattisahusiwa Date: Sun, 12 Jul 2020 00:47:35 +0900 Subject: [PATCH 3/3] Fix undefined substitutions index --- Dice.php | 3 ++- tests/GlobalRuleTest.php | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Dice.php b/Dice.php index ffe62a0..be87773 100644 --- a/Dice.php +++ b/Dice.php @@ -85,7 +85,8 @@ private function appendGlobalRule(string $name, array $rules) : array $globalRules = isset($this->rules['*']) ? $this->rules['*'] : []; if (!isset($globalRules['substitutions'])) return $rules; - $rules['substitutions'] = array_merge($globalRules['substitutions'], $rules['substitutions']); + $subs = isset($rules['substitutions']) ? $rules['substitutions'] : []; + $rules['substitutions'] = array_merge($globalRules['substitutions'], $subs); return $rules; } diff --git a/tests/GlobalRuleTest.php b/tests/GlobalRuleTest.php index 928fed4..0aafd2c 100644 --- a/tests/GlobalRuleTest.php +++ b/tests/GlobalRuleTest.php @@ -148,4 +148,17 @@ public function testGlobal4_5() $this->assertInstanceOf('AnotherGlobalImplementation', $obj->glb); $this->assertInstanceOf('GlobalRuleImplementation', $obj->glbr); } + + public function testNoSubstitutionKey() + { + $rule = [ + 'substitutions' => ['GlobalInterface' => 'GlobalImplementation'] + ]; + $dice = $this->dice->addRule('Global3', ['shared'=> true]); + $dice = $dice->addRule('*', $rule); + + $obj = $dice->create('Global3'); + + $this->assertInstanceOf('GlobalImplementation', $obj->obj); + } }