feature #26768 [DI] Allow autoconfigured calls in PHP (Gary PEGEOT, GaryPEGEOT)
This PR was merged into the 4.1-dev branch. Discussion ---------- [DI] Allow autoconfigured calls in PHP | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? |no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | Allow to auto-configured method calls like: ```php $container->registerForAutoconfiguration(LoggerAwareInterface::class)->addMethodCall('setLogger', array(new Reference(LoggerInterface::class))); ``` Commits -------1d811cb3f7
Add test for both _intanceof and manual method setting.71bf3ced74
CS fix15c45ee40a
Add more test-cases2612f81052
Allow autoconfigured calls in PHP.
This commit is contained in:
commit
306c5992ec
@ -33,9 +33,6 @@ class ResolveInstanceofConditionalsPass implements CompilerPassInterface
|
||||
if ($definition->getArguments()) {
|
||||
throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface));
|
||||
}
|
||||
if ($definition->getMethodCalls()) {
|
||||
throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines method calls but these are not supported and should be removed.', $interface));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
@ -64,6 +61,7 @@ class ResolveInstanceofConditionalsPass implements CompilerPassInterface
|
||||
$definition->setInstanceofConditionals(array());
|
||||
$parent = $shared = null;
|
||||
$instanceofTags = array();
|
||||
$instanceofCalls = array();
|
||||
|
||||
foreach ($conditionals as $interface => $instanceofDefs) {
|
||||
if ($interface !== $class && (!$container->getReflectionClass($class, false))) {
|
||||
@ -81,7 +79,13 @@ class ResolveInstanceofConditionalsPass implements CompilerPassInterface
|
||||
$parent = 'instanceof.'.$interface.'.'.$key.'.'.$id;
|
||||
$container->setDefinition($parent, $instanceofDef);
|
||||
$instanceofTags[] = $instanceofDef->getTags();
|
||||
|
||||
foreach ($instanceofDef->getMethodCalls() as $methodCall) {
|
||||
$instanceofCalls[] = $methodCall;
|
||||
}
|
||||
|
||||
$instanceofDef->setTags(array());
|
||||
$instanceofDef->setMethodCalls(array());
|
||||
|
||||
if (isset($instanceofDef->getChanges()['shared'])) {
|
||||
$shared = $instanceofDef->isShared();
|
||||
@ -98,6 +102,7 @@ class ResolveInstanceofConditionalsPass implements CompilerPassInterface
|
||||
$definition = serialize($definition);
|
||||
$definition = substr_replace($definition, '53', 2, 2);
|
||||
$definition = substr_replace($definition, 'Child', 44, 0);
|
||||
/** @var ChildDefinition $definition */
|
||||
$definition = unserialize($definition);
|
||||
$definition->setParent($parent);
|
||||
|
||||
@ -117,6 +122,8 @@ class ResolveInstanceofConditionalsPass implements CompilerPassInterface
|
||||
}
|
||||
}
|
||||
|
||||
$definition->setMethodCalls(array_merge($instanceofCalls, $definition->getMethodCalls()));
|
||||
|
||||
// reset fields with "merge" behavior
|
||||
$abstract
|
||||
->setBindings($bindings)
|
||||
|
@ -207,6 +207,16 @@ class IntegrationTest extends TestCase
|
||||
'child_service',
|
||||
'child_service_expected',
|
||||
);
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->registerForAutoconfiguration(IntegrationTestStub::class)
|
||||
->addMethodCall('setSunshine', array('supernova'));
|
||||
yield array(
|
||||
'instanceof_and_calls',
|
||||
'main_service',
|
||||
'main_service_expected',
|
||||
$container,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,16 +200,34 @@ class ResolveInstanceofConditionalsPassTest extends TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
||||
* @expectedExceptionMessage Autoconfigured instanceof for type "PHPUnit\Framework\TestCase" defines method calls but these are not supported and should be removed.
|
||||
* Test that autoconfigured calls are handled gracefully.
|
||||
*/
|
||||
public function testProcessThrowsExceptionForAutoconfiguredCalls()
|
||||
public function testProcessForAutoconfiguredCalls()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->registerForAutoconfiguration(parent::class)
|
||||
->addMethodCall('setFoo');
|
||||
|
||||
$expected = array(
|
||||
array('setFoo', array(
|
||||
'plain_value',
|
||||
'%some_parameter%',
|
||||
)),
|
||||
array('callBar', array()),
|
||||
array('isBaz', array()),
|
||||
);
|
||||
|
||||
$container->registerForAutoconfiguration(parent::class)->addMethodCall('setFoo', $expected[0][1]);
|
||||
$container->registerForAutoconfiguration(self::class)->addMethodCall('callBar');
|
||||
|
||||
$def = $container->register('foo', self::class)->setAutoconfigured(true)->addMethodCall('isBaz');
|
||||
$this->assertEquals(
|
||||
array(array('isBaz', array())),
|
||||
$def->getMethodCalls(),
|
||||
'Definition shouldn\'t have only one method call.'
|
||||
);
|
||||
|
||||
(new ResolveInstanceofConditionalsPass())->process($container);
|
||||
|
||||
$this->assertEquals($expected, $container->findDefinition('foo')->getMethodCalls());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,10 @@
|
||||
services:
|
||||
# main_service should look like this in the end
|
||||
main_service_expected:
|
||||
class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub
|
||||
public: true
|
||||
autoconfigure: true
|
||||
calls:
|
||||
- [setSunshine, [supernova]]
|
||||
- [setSunshine, [warm]]
|
||||
|
@ -0,0 +1,9 @@
|
||||
services:
|
||||
_instanceof:
|
||||
Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStubParent:
|
||||
calls:
|
||||
- [setSunshine, [warm]]
|
||||
main_service:
|
||||
class: Symfony\Component\DependencyInjection\Tests\Compiler\IntegrationTestStub
|
||||
autoconfigure: true
|
||||
public: true
|
Reference in New Issue
Block a user