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

Commit77fb641

Browse files
[DI] Add getter injection
1 parent84a5483 commit77fb641

File tree

28 files changed

+807
-47
lines changed

28 files changed

+807
-47
lines changed

‎src/Symfony/Component/DependencyInjection/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
3.3.0
55
-----
66

7+
*[EXPERIMENTAL] added support for getter-injection
78
* added support for omitting the factory class name in a service definition if the definition class is set
89
* deprecated case insensitivity of service identifiers
910
* added "iterator" argument type for lazy iteration over a set of values and services

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ protected function processValue($value, $isRoot = false)
6161
}elseif ($valueinstanceof Definition) {
6262
$value->setArguments($this->processValue($value->getArguments()));
6363
$value->setProperties($this->processValue($value->getProperties()));
64+
$value->setOverriddenGetters($this->processValue($value->getOverriddenGetters()));
6465
$value->setMethodCalls($this->processValue($value->getMethodCalls()));
6566

6667
if ($v =$value->getFactory()) {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ private function doResolveDefinition(ChildDefinition $definition)
8989
$def->setClass($parentDef->getClass());
9090
$def->setArguments($parentDef->getArguments());
9191
$def->setMethodCalls($parentDef->getMethodCalls());
92+
$def->setOverriddenGetters($parentDef->getOverriddenGetters());
9293
$def->setProperties($parentDef->getProperties());
9394
$def->setAutowiringTypes($parentDef->getAutowiringTypes());
9495
if ($parentDef->isDeprecated()) {
@@ -161,6 +162,11 @@ private function doResolveDefinition(ChildDefinition $definition)
161162
$def->setMethodCalls(array_merge($def->getMethodCalls(),$calls));
162163
}
163164

165+
// merge overridden getters
166+
foreach ($definition->getOverriddenGetters()as$k =>$v) {
167+
$def->setOverriddenGetter($k,$v);
168+
}
169+
164170
// merge autowiring types
165171
foreach ($definition->getAutowiringTypes()as$autowiringType) {
166172
$def->addAutowiringType($autowiringType);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ private function processValue($value, $rootLevel = 0, $level = 0)
5959
}
6060
$value->setArguments($this->processValue($value->getArguments(),0));
6161
$value->setProperties($this->processValue($value->getProperties(),1));
62+
$value->setOverriddenGetters($this->processValue($value->getOverriddenGetters(),1));
6263
$value->setMethodCalls($this->processValue($value->getMethodCalls(),2));
6364
}elseif (is_array($value)) {
6465
$i =0;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public function process(ContainerBuilder $container)
4242

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

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

Lines changed: 122 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
useSymfony\Component\Config\Resource\ResourceInterface;
3030
useSymfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
3131
useSymfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
32+
useSymfony\Component\DependencyInjection\LazyProxy\GetterProxyInterface;
3233
useSymfony\Component\ExpressionLanguage\Expression;
3334
useSymfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
3435

@@ -890,6 +891,9 @@ private function createService(Definition $definition, $id, $tryProxy = true)
890891
$arguments =$this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));
891892

892893
if (null !==$factory =$definition->getFactory()) {
894+
if ($definition->getOverriddenGetters()) {
895+
thrownewRuntimeException(sprintf('Cannot create service "%s": factories and overridden getters are incompatible with each other.',$id));
896+
}
893897
if (is_array($factory)) {
894898
$factory =array($this->resolveServices($parameterBag->resolveValue($factory[0])),$factory[1]);
895899
}elseif (!is_string($factory)) {
@@ -908,11 +912,31 @@ private function createService(Definition $definition, $id, $tryProxy = true)
908912
}else {
909913
$r =new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));
910914

911-
$service =null ===$r->getConstructor() ?$r->newInstance() :$r->newInstanceArgs($arguments);
912-
913915
if (!$definition->isDeprecated() &&0 <strpos($r->getDocComment(),"\n * @deprecated")) {
914916
@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);
915917
}
918+
if ($definition->getOverriddenGetters()) {
919+
static$salt;
920+
if (null ===$salt) {
921+
$salt =str_replace('.','',uniqid('',true));
922+
}
923+
$service =sprintf('%s implements\\%s { private $container%4$s; private $values%4$s; %s }',$r->name, GetterProxyInterface::class,$this->generateOverriddenGetters($id,$definition,$r,$salt),$salt);
924+
if (!class_exists($proxyClass ='SymfonyProxy_'.md5($service),false)) {
925+
eval(sprintf('class %s extends %s',$proxyClass,$service));
926+
}
927+
$r =new \ReflectionClass($proxyClass);
928+
$constructor =$r->getConstructor();
929+
if ($constructor && !defined('HHVM_VERSION') &&$constructor->getDeclaringClass()->isInternal()) {
930+
$constructor =null;
931+
}
932+
$service =$constructor ?$r->newInstanceWithoutConstructor() :$r->newInstanceArgs($arguments);
933+
call_user_func(\Closure::bind(function ($c,$v,$s) {$this->{'container'.$s} =$c;$this->{'values'.$s} =$v; },$service,$service),$this,$definition->getOverriddenGetters(),$salt);
934+
if ($constructor) {
935+
$constructor->invokeArgs($service,$arguments);
936+
}
937+
}else {
938+
$service =null ===$r->getConstructor() ?$r->newInstance() :$r->newInstanceArgs($arguments);
939+
}
916940
}
917941

918942
if ($tryProxy || !$definition->isLazy()) {
@@ -1155,6 +1179,102 @@ public function getEnvCounters()
11551179
return$this->envCounters;
11561180
}
11571181

1182+
privatefunctiongenerateOverriddenGetters($id,Definition$definition,\ReflectionClass$class,$salt)
1183+
{
1184+
if ($class->isFinal()) {
1185+
thrownewRuntimeException(sprintf('Unable to configure getter injection for service "%s": class "%s" cannot be marked as final.',$id,$class->name));
1186+
}
1187+
$getters ='';
1188+
foreach ($definition->getOverriddenGetters()as$name =>$returnValue) {
1189+
$r =self::getGetterReflector($class,$name,$id,$type);
1190+
$visibility =$r->isProtected() ?'protected' :'public';
1191+
$name =var_export($name,true);
1192+
$getters .=<<<EOF
1193+
1194+
{$visibility} function{$r->name}(){$type} {
1195+
\$c =\$this->container{$salt};
1196+
\$b =\$c->getParameterBag();
1197+
\$v =\$this->values{$salt}[{$name}];
1198+
1199+
foreach (\$c->getServiceConditionals(\$v) as\$s) {
1200+
if (!\$c->has(\$s)) {
1201+
return parent::{$r->name}();
1202+
}
1203+
}
1204+
1205+
return\$c->resolveServices(\$b->unescapeValue(\$b->resolveValue(\$v)));
1206+
}
1207+
EOF;
1208+
}
1209+
1210+
return$getters;
1211+
}
1212+
1213+
/**
1214+
* @internal
1215+
*/
1216+
publicstaticfunctiongetGetterReflector(\ReflectionClass$class,$name,$id, &$type)
1217+
{
1218+
if (!$class->hasMethod($name)) {
1219+
thrownewRuntimeException(sprintf('Unable to configure getter injection for service "%s": method "%s::%s" does not exist.',$id,$class->name,$name));
1220+
}
1221+
$r =$class->getMethod($name);
1222+
if ($r->isPrivate()) {
1223+
thrownewRuntimeException(sprintf('Unable to configure getter injection for service "%s": method "%s::%s" must be public or protected.',$id,$class->name,$r->name));
1224+
}
1225+
if ($r->isStatic()) {
1226+
thrownewRuntimeException(sprintf('Unable to configure getter injection for service "%s": method "%s::%s" cannot be static.',$id,$class->name,$r->name));
1227+
}
1228+
if ($r->isFinal()) {
1229+
thrownewRuntimeException(sprintf('Unable to configure getter injection for service "%s": method "%s::%s" cannot be marked as final.',$id,$class->name,$r->name));
1230+
}
1231+
if ($r->returnsReference()) {
1232+
thrownewRuntimeException(sprintf('Unable to configure getter injection for service "%s": method "%s::%s" cannot return by reference.',$id,$class->name,$r->name));
1233+
}
1234+
if (0 <$r->getNumberOfParameters()) {
1235+
thrownewRuntimeException(sprintf('Unable to configure getter injection for service "%s": method "%s::%s" cannot have any arguments.',$id,$class->name,$r->name));
1236+
}
1237+
if ($type =method_exists($r,'getReturnType') ?$r->getReturnType() :null) {
1238+
$type =':'.($type->allowsNull() ?'?' :'').self::generateTypeHint($type,$r);
1239+
}
1240+
1241+
return$r;
1242+
}
1243+
1244+
/**
1245+
* @internal
1246+
*/
1247+
publicstaticfunctiongenerateTypeHint($type,\ReflectionFunctionAbstract$r)
1248+
{
1249+
if (is_string($type)) {
1250+
$name =$type;
1251+
1252+
if ('callable' ===$name ||'array' ===$name) {
1253+
return$name;
1254+
}
1255+
}else {
1256+
$name =$typeinstanceof \ReflectionNamedType ?$type->getName() :$type->__toString();
1257+
1258+
if ($type->isBuiltin()) {
1259+
return$name;
1260+
}
1261+
}
1262+
$lcName =strtolower($name);
1263+
1264+
if ('self' !==$lcName &&'parent' !==$lcName) {
1265+
return'\\'.$name;
1266+
}
1267+
if (!$rinstanceof \ReflectionMethod) {
1268+
return;
1269+
}
1270+
if ('self' ===$lcName) {
1271+
return'\\'.$r->getDeclaringClass()->name;
1272+
}
1273+
if ($parent =$r->getDeclaringClass()->getParentClass()) {
1274+
return'\\'.$parent->name;
1275+
}
1276+
}
1277+
11581278
/**
11591279
* @internal
11601280
*/

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

Lines 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+
publicfunctionsetOverriddenGetter($name,$returnValue)
324+
{
325+
if (!$name) {
326+
thrownewInvalidArgumentException(sprintf('Getter name cannot be empty.'));
327+
}
328+
$this->getters[strtolower($name)] =$returnValue;
329+
330+
return$this;
331+
}
332+
333+
publicfunctionsetOverriddenGetters(array$getters)
334+
{
335+
$this->getters =array_change_key_case($getters,CASE_LOWER);
336+
337+
return$this;
338+
}
339+
340+
publicfunctiongetOverriddenGetters()
341+
{
342+
return$this->getters;
343+
}
344+
322345
/**
323346
* Sets tags for this definition.
324347
*

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ public function dump(array $options = array())
8080
$this->findEdges($id,$call[1],false,$call[0].'()')
8181
);
8282
}
83+
84+
foreach ($definition->getOverriddenGetters()as$name =>$value) {
85+
$this->edges[$id] =array_merge(
86+
$this->edges[$id],
87+
$this->findEdges($id,$value,false,$name.'()')
88+
);
89+
}
8390
}
8491

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp