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

Appearance settings

Commit 9ed1810

Browse filesBrowse files
committed
[DI] Add support for getter autowiring
1 parent 9e6d6ba commit 9ed1810
Copy full SHA for 9ed1810

File tree

2 files changed

+133
-5
lines changed
Filter options

2 files changed

+133
-5
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+55-5Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
+78Lines changed: 78 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\HttpFoundation\RequestStack;
1718

1819
/**
1920
* @author Kévin Dunglas <dunglas@gmail.com>
@@ -497,6 +498,32 @@ public function testExplicitMethodInjection()
497498
);
498499
}
499500

501+
public function testGetterOverriding()
502+
{
503+
if (PHP_VERSION_ID < 70100) {
504+
$this->markTestSkipped('This test requires PHP 7.1 or superior');
505+
}
506+
507+
$container = new ContainerBuilder();
508+
$container->register('b', B::class);
509+
510+
$container
511+
->register('getter_overriding', GetterOverriding::class)
512+
->setOverriddenGetter('getExplicitlyDefined', new Reference('b'))
513+
->setAutowiredMethods(array('get*'))
514+
;
515+
516+
$pass = new AutowirePass();
517+
$pass->process($container);
518+
519+
$overridenGetters = $container->getDefinition('getter_overriding')->getOverriddenGetters();
520+
$this->assertEquals($overridenGetters, array(
521+
'getExplicitlyDefined' => new Reference('b'),
522+
'getFoo' => new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\foo'),
523+
'getBar' => new Reference('autowired.symfony\component\dependencyinjection\tests\compiler\bar'),
524+
));
525+
}
526+
500527
/**
501528
* @dataProvider getCreateResourceTests
502529
*/
@@ -807,6 +834,11 @@ public function notASetter(A $a)
807834
{
808835
// should be called only when explicitly specified
809836
}
837+
838+
protected function setProtectedMethod(A $a)
839+
{
840+
// should not be called
841+
}
810842
}
811843

812844
class SetterInjectionCollision
@@ -818,3 +850,49 @@ public function setMultipleInstancesForOneArg(CollisionInterface $collision)
818850
// should throw an exception
819851
}
820852
}
853+
854+
if (PHP_VERSION_ID >= 70100) {
855+
class GetterOverriding
856+
{
857+
public function getFoo(): ?Foo
858+
{
859+
// should be called
860+
}
861+
862+
protected function getBar(): Bar
863+
{
864+
// should be called
865+
}
866+
867+
public function getNoTypeHint()
868+
{
869+
// should not be called
870+
}
871+
872+
public function getUnknown(): NotExist
873+
{
874+
// should not be called
875+
}
876+
877+
public function getExplicitlyDefined(): B
878+
{
879+
// should be called but not autowired
880+
}
881+
882+
public function getScalar(): string
883+
{
884+
// should not be called
885+
}
886+
887+
final public function getFinal(): A
888+
{
889+
// should not be called
890+
}
891+
892+
public function &getReference(): A
893+
{
894+
// should not be called
895+
}
896+
897+
}
898+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.