Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit afc023e

Browse files
committed
[DI] Add support for getter autowiring
1 parent 9e6d6ba commit afc023e

File tree

3 files changed

+146
-5
lines changed

3 files changed

+146
-5
lines changed

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ private function completeDefinition($id, Definition $definition, array $autowire
108108
$methodsCalled[$methodCall[0]] = true;
109109
}
110110

111+
foreach ($definition->getOverriddenGetters() as $overriddenGetter => $returnValue) {
112+
$methodsCalled[$overriddenGetter] = true;
113+
}
114+
111115
foreach ($this->getMethodsToAutowire($id, $reflectionClass, $autowiredMethods) as $reflectionMethod) {
112116
if (!isset($methodsCalled[$reflectionMethod->name])) {
113117
$this->autowireMethod($id, $definition, $reflectionMethod);
@@ -132,7 +136,7 @@ private function getMethodsToAutowire($id, \ReflectionClass $reflectionClass, ar
132136
$regexList[] = '/^'.str_replace('\*', '.*', preg_quote($pattern, '/')).'$/i';
133137
}
134138

135-
foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
139+
foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $reflectionMethod) {
136140
if ($reflectionMethod->isStatic()) {
137141
continue;
138142
}
@@ -164,6 +168,19 @@ private function getMethodsToAutowire($id, \ReflectionClass $reflectionClass, ar
164168
*/
165169
private function autowireMethod($id, Definition $definition, \ReflectionMethod $reflectionMethod)
166170
{
171+
if (null === $this->types) {
172+
$this->populateAvailableTypes();
173+
}
174+
175+
if ($this->overrideGetter($id, $definition, $reflectionMethod)) {
176+
return;
177+
}
178+
179+
if ($reflectionMethod->isProtected()) {
180+
// Only getter overriding is supported for protected methods
181+
return;
182+
}
183+
167184
if ($isConstructor = $reflectionMethod->isConstructor()) {
168185
$arguments = $definition->getArguments();
169186
} else {
@@ -193,10 +210,6 @@ private function autowireMethod($id, Definition $definition, \ReflectionMethod $
193210
continue;
194211
}
195212

196-
if (null === $this->types) {
197-
$this->populateAvailableTypes();
198-
}
199-
200213
if (isset($this->types[$typeHint->name])) {
201214
$value = new Reference($this->types[$typeHint->name]);
202215
$addMethodCall = true;
@@ -247,6 +260,43 @@ private function autowireMethod($id, Definition $definition, \ReflectionMethod $
247260
}
248261
}
249262

263+
/**
264+
* Getter injection.
265+
*
266+
* @param string $id
267+
* @param Definition $definition
268+
* @param \ReflectionMethod $reflectionMethod
269+
*
270+
* @return bool
271+
*/
272+
private function overrideGetter($id, Definition $definition, \ReflectionMethod $reflectionMethod)
273+
{
274+
if (!method_exists($reflectionMethod, 'getReturnType')) {
275+
return false;
276+
}
277+
278+
if (0 !== $reflectionMethod->getNumberOfParameters() || $reflectionMethod->isFinal() || $reflectionMethod->returnsReference() || !($returnType = $reflectionMethod->getReturnType())) {
279+
return false;
280+
}
281+
282+
$class = (string) $returnType;
283+
if (isset($this->types[$class])) {
284+
$value = new Reference($this->types[$class]);
285+
} else {
286+
try {
287+
$value = $this->createAutowiredDefinition(new \ReflectionClass($class), $id);
288+
} catch (\ReflectionException $e) {
289+
return false;
290+
} catch (RuntimeException $e) {
291+
return false;
292+
}
293+
}
294+
295+
$definition->setOverriddenGetter($reflectionMethod->name, $value);
296+
297+
return true;
298+
}
299+
250300
/**
251301
* Populates the list of available types.
252302
*/

src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
1515
use Symfony\Component\DependencyInjection\ContainerBuilder;
1616
use Symfony\Component\DependencyInjection\Reference;
17+
use Symfony\Component\DependencyInjection\Tests\Fixtures\GetterOverriding;
1718

1819
/**
1920
* @author Kévin Dunglas <[email protected]>
@@ -497,6 +498,31 @@ public function testExplicitMethodInjection()
497498
);
498499
}
499500

501+
/**
502+
* @requires PHP 7.1
503+
*/
504+
public function testGetterOverriding()
505+
{
506+
$container = new ContainerBuilder();
507+
$container->register('b', B::class);
508+
509+
$container
510+
->register('getter_overriding', GetterOverriding::class)
511+
->setOverriddenGetter('getExplicitlyDefined', new Reference('b'))
512+
->setAutowiredMethods(array('get*'))
513+
;
514+
515+
$pass = new AutowirePass();
516+
$pass->process($container);
517+
518+
$overridenGetters = $container->getDefinition('getter_overriding')->getOverriddenGetters();
519+
$this->assertEquals($overridenGetters, array(
520+
'getExplicitlyDefined' => new Reference('b'),
521+
'getFoo' => new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\foo'),
522+
'getBar' => new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\bar'),
523+
));
524+
}
525+
500526
/**
501527
* @dataProvider getCreateResourceTests
502528
*/
@@ -807,6 +833,11 @@ public function notASetter(A $a)
807833
{
808834
// should be called only when explicitly specified
809835
}
836+
837+
protected function setProtectedMethod(A $a)
838+
{
839+
// should not be called
840+
}
810841
}
811842

812843
class SetterInjectionCollision
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
13+
14+
/**
15+
* To test getter autowiring with PHP >= 7.1.
16+
*
17+
* @author Kévin Dunglas <[email protected]>
18+
*/
19+
class GetterOverriding
20+
{
21+
public function getFoo(): ?Foo
22+
{
23+
// should be called
24+
}
25+
26+
protected function getBar(): Bar
27+
{
28+
// should be called
29+
}
30+
31+
public function getNoTypeHint()
32+
{
33+
// should not be called
34+
}
35+
36+
public function getUnknown(): NotExist
37+
{
38+
// should not be called
39+
}
40+
41+
public function getExplicitlyDefined(): B
42+
{
43+
// should be called but not autowired
44+
}
45+
46+
public function getScalar(): string
47+
{
48+
// should not be called
49+
}
50+
51+
final public function getFinal(): A
52+
{
53+
// should not be called
54+
}
55+
56+
public function &getReference(): A
57+
{
58+
// should not be called
59+
}
60+
}

0 commit comments

Comments
 (0)