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 3dae76d

Browse filesBrowse files
[DI] Add getter injection
1 parent d614193 commit 3dae76d
Copy full SHA for 3dae76d

28 files changed

+274
-16
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ public function process(ContainerBuilder $container)
7575

7676
if (!$this->onlyConstructorArguments) {
7777
$this->processArguments($definition->getMethodCalls());
78+
$this->processArguments($definition->getOverriddenGetters());
7879
$this->processArguments($definition->getProperties());
7980
if ($definition->getConfigurator()) {
8081
$this->processArguments(array($definition->getConfigurator()));
@@ -108,6 +109,7 @@ private function processArguments(array $arguments)
108109
} elseif ($argument instanceof Definition) {
109110
$this->processArguments($argument->getArguments());
110111
$this->processArguments($argument->getMethodCalls());
112+
$this->processArguments($argument->getOverriddenGetters());
111113
$this->processArguments($argument->getProperties());
112114

113115
if (is_array($argument->getFactory())) {

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ private function processDefinition(Definition $definition)
4141
{
4242
$this->processReferences($definition->getArguments());
4343
$this->processReferences($definition->getMethodCalls());
44+
$this->processReferences($definition->getOverriddenGetters());
4445
$this->processReferences($definition->getProperties());
4546
}
4647

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public function process(ContainerBuilder $container)
4747

4848
$this->validateReferences($definition->getArguments());
4949
$this->validateReferences($definition->getMethodCalls());
50+
$this->validateReferences($definition->getOverriddenGetters());
5051
$this->validateReferences($definition->getProperties());
5152
}
5253
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ private function inlineArguments(ContainerBuilder $container, array $arguments,
8484
} elseif ($argument instanceof Definition) {
8585
$argument->setArguments($this->inlineArguments($container, $argument->getArguments()));
8686
$argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls()));
87+
$argument->setOverriddenGetters($this->inlineArguments($container, $argument->getOverriddenGetters()));
8788
$argument->setProperties($this->inlineArguments($container, $argument->getProperties()));
8889

8990
$configurator = $this->inlineArguments($container, array($argument->getConfigurator()));

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public function process(ContainerBuilder $container)
7676
foreach ($container->getDefinitions() as $definitionId => $definition) {
7777
$definition->setArguments($this->updateArgumentReferences($replacements, $definitionId, $definition->getArguments()));
7878
$definition->setMethodCalls($this->updateArgumentReferences($replacements, $definitionId, $definition->getMethodCalls()));
79+
$definition->setOverriddenGetters($this->updateArgumentReferences($replacements, $definitionId, $definition->getOverriddenGetters()));
7980
$definition->setProperties($this->updateArgumentReferences($replacements, $definitionId, $definition->getProperties()));
8081
$definition->setFactory($this->updateFactoryReference($replacements, $definition->getFactory()));
8182
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ private function resolveArguments(ContainerBuilder $container, array $arguments,
7272
}
7373
$argument->setArguments($this->resolveArguments($container, $argument->getArguments()));
7474
$argument->setMethodCalls($this->resolveArguments($container, $argument->getMethodCalls()));
75+
$argument->setOverriddenGetters($this->resolveArguments($container, $argument->getOverriddenGetters()));
7576
$argument->setProperties($this->resolveArguments($container, $argument->getProperties()));
7677

7778
$configurator = $this->resolveArguments($container, array($argument->getConfigurator()));
@@ -131,6 +132,7 @@ private function doResolveDefinition(ContainerBuilder $container, ChildDefinitio
131132
$def->setClass($parentDef->getClass());
132133
$def->setArguments($parentDef->getArguments());
133134
$def->setMethodCalls($parentDef->getMethodCalls());
135+
$def->setOverriddenGetters($parentDef->getOverriddenGetters());
134136
$def->setProperties($parentDef->getProperties());
135137
$def->setAutowiringTypes($parentDef->getAutowiringTypes());
136138
if ($parentDef->isDeprecated()) {
@@ -203,6 +205,11 @@ private function doResolveDefinition(ContainerBuilder $container, ChildDefinitio
203205
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
204206
}
205207

208+
// merge overridden getters
209+
foreach ($definition->getOverriddenGetters() as $k => $v) {
210+
$def->setOverriddenGetter($k, $v);
211+
}
212+
206213
// merge autowiring types
207214
foreach ($definition->getAutowiringTypes() as $autowiringType) {
208215
$def->addAutowiringType($autowiringType);

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ public function process(ContainerBuilder $container)
5353
}
5454
$definition->setMethodCalls($calls);
5555

56+
$getters = array();
57+
foreach ($definition->getOverriddenGetters() as $name => $value) {
58+
try {
59+
$value = $this->processArguments(array($value), true);
60+
$getters[$name] = reset($value);
61+
} catch (RuntimeException $e) {
62+
// this call is simply removed
63+
}
64+
}
65+
$definition->setOverriddenGetters($getters);
66+
5667
$properties = array();
5768
foreach ($definition->getProperties() as $name => $value) {
5869
try {

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public function process(ContainerBuilder $container)
5151
}
5252
$definition->setMethodCalls($calls);
5353

54+
$definition->setOverriddenGetters($parameterBag->resolveValue($definition->getOverriddenGetters()));
5455
$definition->setProperties($parameterBag->resolveValue($definition->getProperties()));
5556
} catch (ParameterNotFoundException $e) {
5657
$e->setSourceId($id);

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function process(ContainerBuilder $container)
4141

4242
$definition->setArguments($this->processArguments($definition->getArguments()));
4343
$definition->setMethodCalls($this->processArguments($definition->getMethodCalls()));
44+
$definition->setOverriddenGetters($this->processArguments($definition->getOverriddenGetters()));
4445
$definition->setProperties($this->processArguments($definition->getProperties()));
4546
$definition->setFactory($this->processFactory($definition->getFactory()));
4647
}

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+63-2Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,9 @@ private function createService(Definition $definition, $id, $tryProxy = true)
887887
$arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));
888888

889889
if (null !== $factory = $definition->getFactory()) {
890+
if ($definition->getOverriddenGetters()) {
891+
throw new RuntimeException(sprintf('Cannot dump definition: The "%s" service has both a factory and overridden getters but these are incompatible.', $id));
892+
}
890893
if (is_array($factory)) {
891894
$factory = array($this->resolveServices($parameterBag->resolveValue($factory[0])), $factory[1]);
892895
} elseif (!is_string($factory)) {
@@ -905,11 +908,15 @@ private function createService(Definition $definition, $id, $tryProxy = true)
905908
} else {
906909
$r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));
907910

908-
$service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
909-
910911
if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
911912
@trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED);
912913
}
914+
if ($definition->getOverriddenGetters()) {
915+
$service = eval(sprintf('return new class(...$arguments) extends %s { private $c0nt41n3r; private $g3ttErV4lu35; %s };', $r->name, $this->addOverriddenGetters($id, $definition, $r)));
916+
call_user_func(\Closure::bind(function ($c, $v) { $this->c0nt41n3r = $c; $this->g3ttErV4lu35 = $v; }, $service, $service), $this, $definition->getOverriddenGetters());
917+
} else {
918+
$service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments);
919+
}
913920
}
914921

915922
if ($tryProxy || !$definition->isLazy()) {
@@ -1114,6 +1121,60 @@ public function getEnvCounters()
11141121
return $this->envCounters;
11151122
}
11161123

1124+
private function addOverriddenGetters($id, Definition $definition, \ReflectionClass $class)
1125+
{
1126+
if (PHP_VERSION_ID < 70000) {
1127+
throw new RuntimeException(sprintf('Getter-based injection requires PHP 7 or more as used for service "%s".', $id));
1128+
}
1129+
if ($class->isFinal()) {
1130+
throw new RuntimeException(sprintf('Invalid getter for service "%s": class "%s" is final.', $id, $class->name));
1131+
}
1132+
$getters = '';
1133+
foreach ($definition->getOverriddenGetters() as $name => $returnValue) {
1134+
if (!$class->hasMethod($name)) {
1135+
throw new RuntimeException(sprintf('Invalid getter for service "%s": method "%s::%s" does not exist.', $id, $class->name, $name));
1136+
}
1137+
if (($r = $class->getMethod($name))->isPrivate()) {
1138+
throw new RuntimeException(sprintf('Invalid getter for service "%s": method "%s::%s" is private.', $id, $class->name, $name));
1139+
}
1140+
if ($r->isFinal()) {
1141+
throw new RuntimeException(sprintf('Invalid getter for service "%s": method "%s::%s" is final.', $id, $class->name, $name));
1142+
}
1143+
if ($r->isInternal()) {
1144+
throw new RuntimeException(sprintf('Invalid getter for service "%s": method "%s::%s" is internal.', $id, $class->name, $name));
1145+
}
1146+
if ($r->returnsReference()) {
1147+
throw new RuntimeException(sprintf('Invalid getter for service "%s": method "%s::%s" returns by reference.', $id, $class->name, $name));
1148+
}
1149+
if (0 < $r->getNumberOfParameters()) {
1150+
throw new RuntimeException(sprintf('Invalid getter for service "%s": method "%s::%s" has parameters.', $id, $class->name, $name));
1151+
}
1152+
if ($type = $r->getReturnType()) {
1153+
$type = ': '.($type->allowsNull() ? '?' : '').$this->generateTypeHint($type, $r);
1154+
}
1155+
$visibility = $r->isProtected() ? 'protected' : 'public';
1156+
$nameExport = var_export($name, true);
1157+
$getters .= <<<EOF
1158+
1159+
$visibility function $name()$type {
1160+
\$c = \$this->cOnt4In3r;
1161+
\$b = \$c->getParameterBag();
1162+
\$v = \$this->g3ttErV4lu35[$nameExport];
1163+
1164+
foreach (\$c->getServiceConditionals(\$v) as \$s) {
1165+
if (!\$c->has(\$s)) {
1166+
return parent::$name();
1167+
}
1168+
}
1169+
1170+
return \$c->resolveServices(\$b->unescapeValue(\$b->resolveValue(\$v)));
1171+
}
1172+
EOF;
1173+
}
1174+
1175+
return $getters;
1176+
}
1177+
11171178
/**
11181179
* Returns the Service Conditionals.
11191180
*

‎src/Symfony/Component/DependencyInjection/Definition.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Definition.php
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class Definition
2929
private $deprecationTemplate = 'The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed.';
3030
private $properties = array();
3131
private $calls = array();
32+
private $getters = array();
3233
private $configurator;
3334
private $tags = array();
3435
private $public = true;
@@ -319,6 +320,28 @@ public function getMethodCalls()
319320
return $this->calls;
320321
}
321322

323+
public function setOverriddenGetter($name, $returnValue)
324+
{
325+
if (!$name) {
326+
throw new InvalidArgumentException(sprintf('Getter name cannot be empty.'));
327+
}
328+
$this->getters[$name] = $returnValue;
329+
330+
return $this;
331+
}
332+
333+
public function setOverriddenGetters(array $getters)
334+
{
335+
$this->getters = $getters;
336+
337+
return $this;
338+
}
339+
340+
public function getOverriddenGetters()
341+
{
342+
return $this->getters;
343+
}
344+
322345
/**
323346
* Sets tags for this definition.
324347
*

‎src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ public function dump(array $options = array())
7979
$this->findEdges($id, $call[1], false, $call[0].'()')
8080
);
8181
}
82+
83+
foreach ($definition->getOverriddenGetters() as $name => $value) {
84+
$this->edges[$id] = array_merge(
85+
$this->edges[$id],
86+
$this->findEdges($id, $value, false, $name.'()')
87+
);
88+
}
8289
}
8390

8491
return $this->container->resolveEnvPlaceholders($this->startDot().$this->addNodes().$this->addEdges().$this->endDot(), '__ENV_%s__');

0 commit comments

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