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

Commitd905d51

Browse files
[DI] Allow creating ServiceLocator-based services in extensions
1 parent6bfa483 commitd905d51

19 files changed

+602
-31
lines changed

‎src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
useSymfony\Component\DependencyInjection\Alias;
1515
useSymfony\Component\DependencyInjection\Argument\ArgumentInterface;
16+
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1617
useSymfony\Component\DependencyInjection\ContainerBuilder;
1718
useSymfony\Component\DependencyInjection\Definition;
1819
useSymfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -388,6 +389,10 @@ private function describeValue($value, $omitTags, $showArguments)
388389
return$data;
389390
}
390391

392+
if ($valueinstanceof ServiceClosureArgument) {
393+
$value =$value->getValues()[0];
394+
}
395+
391396
if ($valueinstanceof Reference) {
392397
returnarray(
393398
'type' =>'service',

‎src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
useSymfony\Component\DependencyInjection\Alias;
1717
useSymfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
1818
useSymfony\Component\DependencyInjection\Argument\IteratorArgument;
19+
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1920
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
2021
useSymfony\Component\DependencyInjection\ContainerBuilder;
2122
useSymfony\Component\DependencyInjection\Definition;
@@ -324,6 +325,9 @@ protected function describeContainerDefinition(Definition $definition, array $op
324325
$argumentsInformation =array();
325326
if ($showArguments && ($arguments =$definition->getArguments())) {
326327
foreach ($argumentsas$argument) {
328+
if ($argumentinstanceof ServiceClosureArgument) {
329+
$argument =$argument->getValues()[0];
330+
}
327331
if ($argumentinstanceof Reference) {
328332
$argumentsInformation[] =sprintf('Service(%s)', (string)$argument);
329333
}elseif ($argumentinstanceof IteratorArgument) {

‎src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
useSymfony\Component\DependencyInjection\Alias;
1515
useSymfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
1616
useSymfony\Component\DependencyInjection\Argument\IteratorArgument;
17+
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1718
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1819
useSymfony\Component\DependencyInjection\ContainerBuilder;
1920
useSymfony\Component\DependencyInjection\Definition;
@@ -425,6 +426,10 @@ private function getArgumentNodes(array $arguments, \DOMDocument $dom)
425426
$argumentXML->setAttribute('key',$argumentKey);
426427
}
427428

429+
if ($argumentinstanceof ServiceClosureArgument) {
430+
$argument =$argument->getValues()[0];
431+
}
432+
428433
if ($argumentinstanceof Reference) {
429434
$argumentXML->setAttribute('type','service');
430435
$argumentXML->setAttribute('id', (string)$argument);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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\Argument;
13+
14+
useSymfony\Component\DependencyInjection\Reference;
15+
useSymfony\Component\DependencyInjection\Exception\InvalidArgumentException;
16+
17+
/**
18+
* Represents a service wrapped in a memoizing closure.
19+
*
20+
* @author Nicolas Grekas <p@tchwork.com>
21+
*
22+
* @experimental in version 3.3
23+
*/
24+
class ServiceClosureArgumentimplements ArgumentInterface
25+
{
26+
private$values;
27+
28+
publicfunction__construct(Reference$reference)
29+
{
30+
$this->values =array($reference);
31+
}
32+
33+
publicfunctiongetValues()
34+
{
35+
return$this->values;
36+
}
37+
38+
publicfunctionsetValues(array$values)
39+
{
40+
if (array(0) !==array_keys($values) || !($values[0]instanceof Reference ||null ===$values[0])) {
41+
thrownewInvalidArgumentException('A ServiceClosureArgument must hold one and only one Reference.');
42+
}
43+
44+
$this->values =$values;
45+
}
46+
}

‎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 "TypedReference" and "ServiceClosureArgument" for creating service-locator services
78
*[EXPERIMENTAL] added "instanceof" section for local interface-defined configs
89
* added "service-locator" argument for lazy loading a set of identified values and services
910
*[EXPERIMENTAL] added prototype services for PSR4-based discovery and registration

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

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
useSymfony\Component\DependencyInjection\Exception\RuntimeException;
1818
useSymfony\Component\DependencyInjection\LazyProxy\InheritanceProxyHelper;
1919
useSymfony\Component\DependencyInjection\Reference;
20+
useSymfony\Component\DependencyInjection\TypedReference;
2021

2122
/**
2223
* Guesses constructor arguments of services definitions and try to instantiate services if necessary.
@@ -39,6 +40,7 @@ class AutowirePass extends AbstractRecursivePass
3940
private$types;
4041
private$ambiguousServiceTypes =array();
4142
private$usedTypes =array();
43+
private$currentDefinition;
4244

4345
/**
4446
* {@inheritdoc}
@@ -100,43 +102,55 @@ public static function createResourceForClass(\ReflectionClass $reflectionClass)
100102
*/
101103
protectedfunctionprocessValue($value,$isRoot =false)
102104
{
103-
if (!$valueinstanceof Definition || !$value->isAutowired()) {
104-
returnparent::processValue($value,$isRoot);
105+
if ($valueinstanceof TypedReference &&$this->currentDefinition->isAutowired() && !$this->container->has((string)$value)) {
106+
if ($ref =$this->getAutowiredReference($value->getType(),$value->canBeAutoregistered())) {
107+
$value =newTypedReference((string)$ref,$value->getType());
108+
}
105109
}
106-
107-
if (!$reflectionClass =$this->container->getReflectionClass($value->getClass())) {
110+
if (!$valueinstanceof Definition) {
108111
returnparent::processValue($value,$isRoot);
109112
}
110113

111-
$autowiredMethods =$this->getMethodsToAutowire($reflectionClass);
112-
$methodCalls =$value->getMethodCalls();
114+
$parentDefinition =$this->currentDefinition;
115+
$this->currentDefinition =$value;
113116

114-
if ($constructor =$reflectionClass->getConstructor()) {
115-
array_unshift($methodCalls,array($constructor->name,$value->getArguments()));
116-
}elseif ($value->getArguments()) {
117-
thrownewRuntimeException(sprintf('Cannot autowire service "%s": class %s has no constructor but arguments are defined.',$this->currentId,$reflectionClass->name));
118-
}
117+
try {
118+
if (!$value->isAutowired() || !$reflectionClass =$this->container->getReflectionClass($value->getClass())) {
119+
returnparent::processValue($value,$isRoot);
120+
}
121+
122+
$autowiredMethods =$this->getMethodsToAutowire($reflectionClass);
123+
$methodCalls =$value->getMethodCalls();
124+
125+
if ($constructor =$reflectionClass->getConstructor()) {
126+
array_unshift($methodCalls,array($constructor->name,$value->getArguments()));
127+
}elseif ($value->getArguments()) {
128+
thrownewRuntimeException(sprintf('Cannot autowire service "%s": class %s has no constructor but arguments are defined.',$this->currentId,$reflectionClass->name));
129+
}
119130

120-
$methodCalls =$this->autowireCalls($reflectionClass,$methodCalls,$autowiredMethods);
121-
$overriddenGetters =$this->autowireOverridenGetters($value->getOverriddenGetters(),$autowiredMethods);
131+
$methodCalls =$this->autowireCalls($reflectionClass,$methodCalls,$autowiredMethods);
132+
$overriddenGetters =$this->autowireOverridenGetters($value->getOverriddenGetters(),$autowiredMethods);
122133

123-
if ($constructor) {
124-
list(,$arguments) =array_shift($methodCalls);
134+
if ($constructor) {
135+
list(,$arguments) =array_shift($methodCalls);
125136

126-
if ($arguments !==$value->getArguments()) {
127-
$value->setArguments($arguments);
137+
if ($arguments !==$value->getArguments()) {
138+
$value->setArguments($arguments);
139+
}
128140
}
129-
}
130141

131-
if ($methodCalls !==$value->getMethodCalls()) {
132-
$value->setMethodCalls($methodCalls);
133-
}
142+
if ($methodCalls !==$value->getMethodCalls()) {
143+
$value->setMethodCalls($methodCalls);
144+
}
134145

135-
if ($overriddenGetters !==$value->getOverriddenGetters()) {
136-
$value->setOverriddenGetters($overriddenGetters);
137-
}
146+
if ($overriddenGetters !==$value->getOverriddenGetters()) {
147+
$value->setOverriddenGetters($overriddenGetters);
148+
}
138149

139-
returnparent::processValue($value,$isRoot);
150+
returnparent::processValue($value,$isRoot);
151+
}finally {
152+
$this->currentDefinition =$parentDefinition;
153+
}
140154
}
141155

142156
/**
@@ -465,7 +479,7 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint)
465479

466480
$this->populateAvailableType($argumentId,$argumentDefinition);
467481

468-
$this->processValue($argumentDefinition);
482+
$this->processValue($argumentDefinition,true);
469483
$this->currentId =$currentId;
470484

471485
returnnewReference($argumentId);

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespaceSymfony\Component\DependencyInjection\Compiler;
1313

1414
useSymfony\Component\DependencyInjection\Argument\ArgumentInterface;
15+
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1516
useSymfony\Component\DependencyInjection\ContainerInterface;
1617
useSymfony\Component\DependencyInjection\Definition;
1718
useSymfony\Component\DependencyInjection\Reference;
@@ -53,7 +54,9 @@ public function process(ContainerBuilder $container)
5354
*/
5455
privatefunctionprocessValue($value,$rootLevel =0,$level =0)
5556
{
56-
if ($valueinstanceof ArgumentInterface) {
57+
if ($valueinstanceof ServiceClosureArgument) {
58+
$value->setValues($this->processValue($value->getValues(),1,1));
59+
}elseif ($valueinstanceof ArgumentInterface) {
5760
$value->setValues($this->processValue($value->getValues(),$rootLevel,1 +$level));
5861
}elseif ($valueinstanceof Definition) {
5962
if ($value->isSynthetic() ||$value->isAbstract()) {

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
useSymfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
1616
useSymfony\Component\DependencyInjection\Argument\IteratorArgument;
1717
useSymfony\Component\DependencyInjection\Argument\RewindableGenerator;
18+
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1819
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1920
useSymfony\Component\DependencyInjection\Compiler\Compiler;
2021
useSymfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
@@ -1140,11 +1141,16 @@ public function resolveServices($value)
11401141
foreach ($valueas$k =>$v) {
11411142
$value[$k] =$this->resolveServices($v);
11421143
}
1144+
}elseif ($valueinstanceof ServiceClosureArgument) {
1145+
$reference =$value->getValues()[0];
1146+
$value =function ()use ($reference) {
1147+
return$this->resolveServices($reference);
1148+
};
11431149
}elseif ($valueinstanceof ServiceLocatorArgument) {
11441150
$parameterBag =$this->getParameterBag();
11451151
$services =array();
11461152
foreach ($value->getValues()as$k =>$v) {
1147-
if ($v->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE && !$this->has((string)$v)) {
1153+
if ($v &&$v->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE && !$this->has((string)$v)) {
11481154
continue;
11491155
}
11501156
$services[$k] =function ()use ($v,$parameterBag) {

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

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
useSymfony\Component\DependencyInjection\Argument\ArgumentInterface;
1515
useSymfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
1616
useSymfony\Component\DependencyInjection\Argument\IteratorArgument;
17+
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1718
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1819
useSymfony\Component\DependencyInjection\Variable;
1920
useSymfony\Component\DependencyInjection\Definition;
2021
useSymfony\Component\DependencyInjection\ContainerBuilder;
2122
useSymfony\Component\DependencyInjection\Container;
2223
useSymfony\Component\DependencyInjection\ContainerInterface;
2324
useSymfony\Component\DependencyInjection\Reference;
25+
useSymfony\Component\DependencyInjection\TypedReference;
2426
useSymfony\Component\DependencyInjection\Parameter;
2527
useSymfony\Component\DependencyInjection\Exception\EnvParameterException;
2628
useSymfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@@ -1540,10 +1542,12 @@ private function dumpValue($value, $interpolate = true)
15401542
}
15411543

15421544
returnsprintf('array(%s)',implode(',',$code));
1545+
}elseif ($valueinstanceof ServiceClosureArgument) {
1546+
return$this->dumpServiceClosure($value->getValues()[0],$interpolate,false);
15431547
}elseif ($valueinstanceof ServiceLocatorArgument) {
15441548
$code ="\n";
15451549
foreach ($value->getValues()as$k =>$v) {
1546-
$code .=sprintf(" %s =>function () { return %s; },\n",$this->dumpValue($k,$interpolate),$this->dumpValue($v,$interpolate));
1550+
$code .=sprintf(" %s =>%s,\n",$this->dumpValue($k,$interpolate),$this->dumpServiceClosure($v,$interpolate,true));
15471551
}
15481552
$code .='';
15491553

@@ -1681,6 +1685,27 @@ private function dumpValue($value, $interpolate = true)
16811685
return$this->export($value);
16821686
}
16831687

1688+
privatefunctiondumpServiceClosure(Reference$reference,$interpolate,$oneLine)
1689+
{
1690+
$type ='';
1691+
if (PHP_VERSION_ID >=70000 &&$referenceinstanceof TypedReference) {
1692+
$type =$reference->getType();
1693+
if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE ===$reference->getInvalidBehavior()) {
1694+
$type =':\\'.$type;
1695+
}elseif (PHP_VERSION_ID >=70100) {
1696+
$type =': ?\\'.$type;
1697+
}else {
1698+
$type ='';
1699+
}
1700+
}
1701+
1702+
if ($oneLine) {
1703+
returnsprintf('function ()%s { return %s; }',$type,$this->dumpValue($reference,$interpolate));
1704+
}
1705+
1706+
returnsprintf("function ()%s {\n return %s;\n }",$type,$this->dumpValue($reference,$interpolate));
1707+
}
1708+
16841709
/**
16851710
* Dumps a string to a literal (aka PHP Code) class value.
16861711
*

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
useSymfony\Component\DependencyInjection\Argument\ClosureProxyArgument;
1515
useSymfony\Component\DependencyInjection\Argument\IteratorArgument;
16+
useSymfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1617
useSymfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1718
useSymfony\Component\DependencyInjection\ContainerInterface;
1819
useSymfony\Component\DependencyInjection\Parameter;
@@ -289,6 +290,9 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent
289290
$element->setAttribute($keyAttribute,$key);
290291
}
291292

293+
if ($valueinstanceof ServiceClosureArgument) {
294+
$value =$value->getValues()[0];
295+
}
292296
if (is_array($value)) {
293297
$element->setAttribute('type','collection');
294298
$this->convertParameters($value,$type,$element,'key');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp