Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #186, inherit global rules #187

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions Dice.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
164 changes: 164 additions & 0 deletions tests/GlobalRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php
/* @description Dice - A minimal Dependency Injection Container for PHP *
* @author Tom Butler [email protected] *
* @copyright 2012-2018 Tom Butler <[email protected]> | 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);
}
}
68 changes: 68 additions & 0 deletions tests/TestData/GlobalRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

interface GlobalInterface
{

}

class GlobalImplementation implements GlobalInterface
{

}

class AnotherGlobalImplementation implements GlobalInterface
{

}

interface GlobalRuleInterface
{

}

class GlobalRuleImplementation implements GlobalRuleInterface
{

}

class Global1
{
public $obj;
public function __construct(GlobalInterface $obj)
{
$this->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;
}
}