Skip to content

Commit

Permalink
Merge pull request #1 from PHP-DI/wildcard-autowire
Browse files Browse the repository at this point in the history
Improve #616
  • Loading branch information
jasonrm committed Aug 25, 2018
2 parents db29477 + e1166cd commit 0017265
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 28 deletions.
20 changes: 20 additions & 0 deletions src/Definition/ObjectDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use DI\Definition\Dumper\ObjectDefinitionDumper;
use DI\Definition\ObjectDefinition\MethodInjection;
use DI\Definition\ObjectDefinition\PropertyInjection;
use DI\Definition\Source\DefinitionArray;
use ReflectionClass;

/**
Expand Down Expand Up @@ -223,6 +224,25 @@ public function replaceNestedDefinitions(callable $replacer)
});
}

/**
* Replaces all the wildcards in the string with the given replacements.
*
* @param string[] $replacements
*/
public function replaceWildcards(array $replacements)
{
$className = $this->getClassName();

foreach ($replacements as $replacement) {
$pos = strpos($className, DefinitionArray::WILDCARD);
if ($pos !== false) {
$className = substr_replace($className, $replacement, $pos, 1);
}
}

$this->setClassName($className);
}

public function __toString()
{
return (new ObjectDefinitionDumper)->dump($this);
Expand Down
29 changes: 2 additions & 27 deletions src/Definition/Source/DefinitionArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,8 @@ public function getDefinition(string $name)
$key = preg_quote($key);
$key = '#' . str_replace('\\' . self::WILDCARD, self::WILDCARD_PATTERN, $key) . '#';
if (preg_match($key, $name, $matches) === 1) {
$definition = $this->normalizer->normalizeRootDefinition($definition, $name);

// For a class definition, we replace * in the class name with the matches
// *Interface -> *Impl => FooInterface -> FooImpl
if ($definition instanceof ObjectDefinition) {
array_shift($matches);
$definition->setClassName(
$this->replaceWildcards($definition->getClassName(), $matches)
);
$definition = $this->normalizer->normalizeRootDefinition($definition, $name);
}
array_shift($matches);
$definition = $this->normalizer->normalizeRootDefinition($definition, $name, $matches);

return $definition;
}
Expand All @@ -137,20 +128,4 @@ public function getDefinitions() : array

return $definitions;
}

/**
* Replaces all the wildcards in the string with the given replacements.
* @param string[] $replacements
*/
private function replaceWildcards(string $string, array $replacements) : string
{
foreach ($replacements as $replacement) {
$pos = strpos($string, self::WILDCARD);
if ($pos !== false) {
$string = substr_replace($string, $replacement, $pos, 1);
}
}

return $string;
}
}
10 changes: 9 additions & 1 deletion src/Definition/Source/DefinitionNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use DI\Definition\Exception\InvalidDefinition;
use DI\Definition\FactoryDefinition;
use DI\Definition\Helper\DefinitionHelper;
use DI\Definition\ObjectDefinition;
use DI\Definition\ValueDefinition;

/**
Expand Down Expand Up @@ -38,10 +39,11 @@ public function __construct(Autowiring $autowiring)
*
* @param mixed $definition
* @param string $name The definition name.
* @param string[] $wildcardsReplacements Replacements for wildcard definitions.
*
* @throws InvalidDefinition
*/
public function normalizeRootDefinition($definition, string $name) : Definition
public function normalizeRootDefinition($definition, string $name, array $wildcardsReplacements = null) : Definition
{
if ($definition instanceof DefinitionHelper) {
$definition = $definition->getDefinition($name);
Expand All @@ -53,6 +55,12 @@ public function normalizeRootDefinition($definition, string $name) : Definition
$definition = new ValueDefinition($definition);
}

// For a class definition, we replace * in the class name with the matches
// *Interface -> *Impl => FooInterface -> FooImpl
if ($wildcardsReplacements && $definition instanceof ObjectDefinition) {
$definition->replaceWildcards($wildcardsReplacements);
}

if ($definition instanceof AutowireDefinition) {
$definition = $this->autowiring->autowire($name, $definition);
}
Expand Down
33 changes: 33 additions & 0 deletions tests/IntegrationTest/Definitions/WildcardDefinitionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ public function test_wildcards(ContainerBuilder $builder)
self::assertEntryIsNotCompiled($container, 'DI\Test\IntegrationTest\*\Interface*');
self::assertEntryIsNotCompiled($container, Interface1::class);
}
/**
* @dataProvider provideContainer
*/
public function test_wildcard_with_static_name(ContainerBuilder $builder)
{
$builder->addDefinitions([
'DI\Test\IntegrationTest\*\Interface*' => \DI\create(Implementation1::class),
]);
$container = $builder->build();

$object = $container->get(Interface1::class);
$this->assertInstanceOf(Implementation1::class, $object);

self::assertEntryIsNotCompiled($container, Interface1::class);
}

/**
* @dataProvider provideContainer
Expand All @@ -52,6 +67,24 @@ public function test_wildcards_autowire(ContainerBuilder $builder)
$object = $container->get(Interface1::class);
$this->assertInstanceOf(Implementation1::class, $object);

self::assertEntryIsNotCompiled($container, 'DI\Test\IntegrationTest\*\Interface*');
self::assertEntryIsNotCompiled($container, Interface1::class);
self::assertEntryIsNotCompiled($container, Interface2::class);
}

/**
* @dataProvider provideContainer
*/
public function test_wildcards_autowire_with_dependency(ContainerBuilder $builder)
{
$builder->addDefinitions([
'DI\Test\IntegrationTest\*\Interface*' => \DI\autowire('DI\Test\IntegrationTest\*\Implementation*'),
]);
$container = $builder->build();

$object = $container->get(Interface1::class);
$this->assertInstanceOf(Implementation1::class, $object);

$object2 = $container->get(Interface2::class);
$this->assertInstanceOf(Implementation2::class, $object2);
$this->assertInstanceOf(Implementation1::class, $object2->dependency);
Expand Down
35 changes: 35 additions & 0 deletions tests/UnitTest/Definition/ObjectDefinitionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,39 @@ public function test_method_injections()
new MethodInjection('method2'),
], $definition->getMethodInjections());
}

public function test_replace_wildcards()
{
$definition = new ObjectDefinition('class', 'Foo*\Bar*\Baz*');
$definition->replaceWildcards(['1', '2', '3']);
$this->assertEquals('Foo1\Bar2\Baz3', $definition->getClassName());
}

public function test_replace_wildcards_with_no_classname_defined()
{
$definition = new ObjectDefinition('Foo*\Bar*\Baz*');
$definition->replaceWildcards(['1', '2', '3']);
$this->assertEquals('Foo1\Bar2\Baz3', $definition->getClassName());
}

public function test_replace_wildcards_with_extra_replacements()
{
$definition = new ObjectDefinition('Foo*\Bar\Baz');
$definition->replaceWildcards(['1', '2', '3']);
$this->assertEquals('Foo1\Bar\Baz', $definition->getClassName());
}

public function test_replace_wildcards_with_missing_replacements()
{
$definition = new ObjectDefinition('Foo*\Bar*\Baz*');
$definition->replaceWildcards(['1']);
$this->assertEquals('Foo1\Bar*\Baz*', $definition->getClassName());
}

public function test_replace_wildcards_with_no_wildcards()
{
$definition = new ObjectDefinition('Foo\Bar\Baz');
$definition->replaceWildcards(['1', '2', '3']);
$this->assertEquals('Foo\Bar\Baz', $definition->getClassName());
}
}

0 comments on commit 0017265

Please sign in to comment.