diff --git a/Dice.php b/Dice.php index b75299b..be87773 100644 --- a/Dice.php +++ b/Dice.php @@ -55,8 +55,8 @@ 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); - } + $dice->rules[ltrim(strtolower($name), '\\')] = array_replace_recursive($dice->getRule($name), $rule); + } /** * Returns the rule that will be applied to the class $name when calling create() @@ -65,7 +65,7 @@ private function addRuleTo(Dice $dice, string $name, array $rule) { */ 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 @@ -78,6 +78,18 @@ 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; + + $subs = isset($rules['substitutions']) ? $rules['substitutions'] : []; + $rules['substitutions'] = array_merge($globalRules['substitutions'], $subs); + 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 @@ -191,8 +203,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..0aafd2c --- /dev/null +++ b/tests/GlobalRuleTest.php @@ -0,0 +1,164 @@ + | 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); + } + + 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); + } + + 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); + } +} 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; + } +}