Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbee5364

Browse files
committed
[DependencyInjection] Automatically detect the definitions class when possible
1 parent56c7206 commitbee5364

File tree

4 files changed

+237
-0
lines changed

4 files changed

+237
-0
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\DependencyInjection\Compiler;
13+
14+
useSymfony\Component\DependencyInjection\ContainerBuilder;
15+
useSymfony\Component\DependencyInjection\Definition;
16+
useSymfony\Component\DependencyInjection\Reference;
17+
18+
/**
19+
* @author Guilhem N. <egetick@gmail.com>
20+
*/
21+
class FactoryReturnTypePassimplements CompilerPassInterface
22+
{
23+
/**
24+
* {@inheritdoc}
25+
*/
26+
publicfunctionprocess(ContainerBuilder$container)
27+
{
28+
// works only since php 7.0 and hhvm 3.11
29+
if (!method_exists(\ReflectionMethod::class,'getReturnType')) {
30+
return;
31+
}
32+
33+
foreach ($container->getDefinitions()as$id =>$definition) {
34+
$this->updateDefinition($container,$id,$definition);
35+
}
36+
}
37+
38+
privatefunctionupdateDefinition(ContainerBuilder$container,$id,Definition$definition,array$previous =array())
39+
{
40+
// circular reference
41+
if (isset($previous[$id])) {
42+
return;
43+
}
44+
45+
$factory =$definition->getFactory();
46+
if (null ===$factory ||null !==$definition->getClass()) {
47+
return;
48+
}
49+
50+
$class =null;
51+
if (is_string($factory)) {
52+
try {
53+
$m =new \ReflectionFunction($factory);
54+
}catch (\ReflectionException$e) {
55+
return;
56+
}
57+
}else {
58+
if ($factory[0]instanceof Reference) {
59+
$previous[$id] =true;
60+
$factoryDefinition =$container->findDefinition((string)$factory[0]);
61+
$this->updateDefinition($container, (string)$factory[0],$factoryDefinition,$previous);
62+
$class =$factoryDefinition->getClass();
63+
}else {
64+
$class =$factory[0];
65+
}
66+
67+
try {
68+
$m =new \ReflectionMethod($class,$factory[1]);
69+
}catch (\ReflectionException$e) {
70+
return;
71+
}
72+
}
73+
74+
$returnType =$m->getReturnType();
75+
if (null !==$returnType && !$returnType->isBuiltin()) {
76+
$returnType = (string)$returnType;
77+
if (null !==$class) {
78+
$declaringClass =$m->getDeclaringClass()->getName();
79+
if ('self' ===$returnType) {
80+
$returnType =$declaringClass;
81+
}elseif ('parent' ===$returnType) {
82+
$returnType =get_parent_class($declaringClass) ?:null;
83+
}
84+
}
85+
86+
$definition->setClass($returnType);
87+
}
88+
}
89+
}

‎src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public function __construct()
4747
newCheckDefinitionValidityPass(),
4848
newResolveReferencesToAliasesPass(),
4949
newResolveInvalidReferencesPass(),
50+
newFactoryReturnTypePass(),
5051
newAutowirePass(),
5152
newAnalyzeServiceReferencesPass(true),
5253
newCheckCircularReferencesPass(),
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\DependencyInjection\Tests\Compiler;
13+
14+
useSymfony\Component\DependencyInjection\Compiler\FactoryReturnTypePass;
15+
useSymfony\Component\DependencyInjection\ContainerBuilder;
16+
useSymfony\Component\DependencyInjection\Reference;
17+
useSymfony\Component\DependencyInjection\Tests\Fixtures\factoryFunction;
18+
useSymfony\Component\DependencyInjection\Tests\Fixtures\FactoryDummy;
19+
useSymfony\Component\DependencyInjection\Tests\Fixtures\FactoryParent;
20+
21+
/**
22+
* @author Guilhem N. <egetick@gmail.com>
23+
*/
24+
class FactoryReturnTypePassTestextends \PHPUnit_Framework_TestCase
25+
{
26+
publicfunctiontestProcess()
27+
{
28+
$container =newContainerBuilder();
29+
30+
$factory =$container->register('factory');
31+
$factory->setFactory(array(FactoryDummy::class,'createFactory'));
32+
33+
$foo =$container->register('foo');
34+
$foo->setFactory(array(newReference('factory'),'create'));
35+
36+
$bar =$container->register('bar',__CLASS__);
37+
$bar->setFactory(array(newReference('factory'),'create'));
38+
39+
$pass =newFactoryReturnTypePass();
40+
$pass->process($container);
41+
42+
if (method_exists(\ReflectionMethod::class,'getReturnType')) {
43+
$this->assertEquals(FactoryDummy::class,$factory->getClass());
44+
$this->assertEquals(\stdClass::class,$foo->getClass());
45+
}else {
46+
$this->assertNull($factory->getClass());
47+
$this->assertNull($foo->getClass());
48+
}
49+
$this->assertEquals(__CLASS__,$bar->getClass());
50+
}
51+
52+
/**
53+
* @dataProvider returnTypesProvider
54+
*/
55+
publicfunctiontestReturnTypes($factory,$returnType,$hhvmSupport =true)
56+
{
57+
if (!$hhvmSupport &&defined('HHVM_VERSION')) {
58+
$this->markTestSkipped('Scalar typehints not supported by hhvm.');
59+
}
60+
61+
$container =newContainerBuilder();
62+
63+
$service =$container->register('service');
64+
$service->setFactory($factory);
65+
66+
$pass =newFactoryReturnTypePass();
67+
$pass->process($container);
68+
69+
if (method_exists(\ReflectionMethod::class,'getReturnType')) {
70+
$this->assertEquals($returnType,$service->getClass());
71+
}else {
72+
$this->assertNull($service->getClass());
73+
}
74+
}
75+
76+
publicfunctionreturnTypesProvider()
77+
{
78+
returnarray(
79+
// must be loaded before the function as they are in the same file
80+
array(array(FactoryDummy::class,'createBuiltin'),null,false),
81+
array(array(FactoryDummy::class,'createParent'), FactoryParent::class),
82+
array(array(FactoryDummy::class,'createSelf'), FactoryDummy::class),
83+
array(factoryFunction::class, FactoryDummy::class),
84+
);
85+
}
86+
87+
publicfunctiontestCircularReference()
88+
{
89+
$container =newContainerBuilder();
90+
91+
$factory =$container->register('factory');
92+
$factory->setFactory(array(newReference('factory2'),'createSelf'));
93+
94+
$factory2 =$container->register('factory2');
95+
$factory2->setFactory(array(newReference('factory'),'create'));
96+
97+
$pass =newFactoryReturnTypePass();
98+
$pass->process($container);
99+
100+
$this->assertNull($factory->getClass());
101+
$this->assertNull($factory2->getClass());
102+
}
103+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\DependencyInjection\Tests\Fixtures;
13+
14+
class FactoryDummyextends FactoryParent
15+
{
16+
publicstaticfunctioncreateFactory():FactoryDummy
17+
{
18+
}
19+
20+
publicfunctioncreate():\stdClass
21+
{
22+
}
23+
24+
// Not supported by hhvm
25+
publicfunctioncreateBuiltin():int
26+
{
27+
}
28+
29+
publicstaticfunctioncreateSelf():self
30+
{
31+
}
32+
33+
publicstaticfunctioncreateParent():parent
34+
{
35+
}
36+
}
37+
38+
class FactoryParent
39+
{
40+
}
41+
42+
functionfactoryFunction():FactoryDummy
43+
{
44+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp