14
14
use Symfony \Component \DependencyInjection \Argument \ArgumentInterface ;
15
15
use Symfony \Component \DependencyInjection \ContainerInterface ;
16
16
use Symfony \Component \DependencyInjection \Definition ;
17
- use Symfony \Component \DependencyInjection \Exception \RuntimeException ;
18
- use Symfony \Component \DependencyInjection \ExpressionLanguage ;
19
17
use Symfony \Component \DependencyInjection \Reference ;
20
18
use Symfony \Component \DependencyInjection \ContainerBuilder ;
21
19
use Symfony \Component \ExpressionLanguage \Expression ;
28
26
* retrieve the graph in other passes from the compiler.
29
27
*
30
28
* @author Johannes M. Schmitt <[email protected] >
29
+ * @author Nicolas Grekas <[email protected] >
31
30
*/
32
31
class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements RepeatablePassInterface
33
32
{
34
33
private $ graph ;
35
34
private $ currentDefinition ;
36
35
private $ onlyConstructorArguments ;
37
36
private $ lazy ;
38
- private $ expressionLanguage ;
37
+ private $ inExpression ;
38
+ private $ definitions ;
39
+ private $ aliases ;
39
40
40
41
/**
41
42
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
42
43
*/
43
44
public function __construct (bool $ onlyConstructorArguments = false )
44
45
{
45
46
$ this ->onlyConstructorArguments = $ onlyConstructorArguments ;
47
+ $ this ->enableExpressionProcessing ();
46
48
}
47
49
48
50
/**
49
51
* {@inheritdoc}
50
52
*/
51
53
public function setRepeatedPass (RepeatedPass $ repeatedPass )
52
54
{
53
- // no-op for BC
55
+ @ trigger_error ( sprintf ( ' The "%s" method is deprecated since Symfony 4.2. ' , __METHOD__ ), E_USER_DEPRECATED );
54
56
}
55
57
56
58
/**
@@ -62,13 +64,19 @@ public function process(ContainerBuilder $container)
62
64
$ this ->graph = $ container ->getCompiler ()->getServiceReferenceGraph ();
63
65
$ this ->graph ->clear ();
64
66
$ this ->lazy = false ;
67
+ $ this ->definitions = $ container ->getDefinitions ();
68
+ $ this ->aliases = $ container ->getAliases ();
65
69
66
- foreach ($ container -> getAliases () as $ id => $ alias ) {
70
+ foreach ($ this -> aliases as $ id => $ alias ) {
67
71
$ targetId = $ this ->getDefinitionId ((string ) $ alias );
68
- $ this ->graph ->connect ($ id , $ alias , $ targetId , $ this ->getDefinition ($ targetId ), null );
72
+ $ this ->graph ->connect ($ id , $ alias , $ targetId , null !== $ targetId ? $ this ->container -> getDefinition ($ targetId ) : null , null );
69
73
}
70
74
71
- parent ::process ($ container );
75
+ try {
76
+ parent ::process ($ container );
77
+ } finally {
78
+ $ this ->aliases = $ this ->definitions = array ();
79
+ }
72
80
}
73
81
74
82
protected function processValue ($ value , $ isRoot = false )
@@ -83,13 +91,16 @@ protected function processValue($value, $isRoot = false)
83
91
return $ value ;
84
92
}
85
93
if ($ value instanceof Expression) {
86
- $ this ->getExpressionLanguage ()->compile ((string ) $ value , array ('this ' => 'container ' ));
87
-
88
- return $ value ;
94
+ $ this ->inExpression = true ;
95
+ try {
96
+ return parent ::processValue ($ value );
97
+ } finally {
98
+ $ this ->inExpression = false ;
99
+ }
89
100
}
90
101
if ($ value instanceof Reference) {
91
102
$ targetId = $ this ->getDefinitionId ((string ) $ value );
92
- $ targetDefinition = $ this ->getDefinition ($ targetId );
103
+ $ targetDefinition = null !== $ targetId ? $ this ->container -> getDefinition ($ targetId ) : null ;
93
104
94
105
$ this ->graph ->connect (
95
106
$ this ->currentId ,
@@ -101,6 +112,19 @@ protected function processValue($value, $isRoot = false)
101
112
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $ value ->getInvalidBehavior ()
102
113
);
103
114
115
+ if ($ this ->inExpression ) {
116
+ $ this ->inExpression = false ;
117
+ $ this ->graph ->connect (
118
+ '.internal.reference_in_expression ' ,
119
+ null ,
120
+ $ targetId ,
121
+ $ targetDefinition ,
122
+ $ value ,
123
+ $ this ->lazy || ($ targetDefinition && $ targetDefinition ->isLazy ()),
124
+ true
125
+ );
126
+ }
127
+
104
128
return $ value ;
105
129
}
106
130
if (!$ value instanceof Definition) {
@@ -127,49 +151,12 @@ protected function processValue($value, $isRoot = false)
127
151
return $ value ;
128
152
}
129
153
130
- private function getDefinition (?string $ id ): ?Definition
131
- {
132
- return null === $ id ? null : $ this ->container ->getDefinition ($ id );
133
- }
134
-
135
154
private function getDefinitionId (string $ id ): ?string
136
155
{
137
- while ($ this ->container ->hasAlias ($ id )) {
138
- $ id = (string ) $ this ->container ->getAlias ($ id );
139
- }
140
-
141
- if (!$ this ->container ->hasDefinition ($ id )) {
142
- return null ;
143
- }
144
-
145
- return $ id ;
146
- }
147
-
148
- private function getExpressionLanguage ()
149
- {
150
- if (null === $ this ->expressionLanguage ) {
151
- if (!class_exists (ExpressionLanguage::class)) {
152
- throw new RuntimeException ('Unable to use expressions as the Symfony ExpressionLanguage component is not installed. ' );
153
- }
154
-
155
- $ providers = $ this ->container ->getExpressionLanguageProviders ();
156
- $ this ->expressionLanguage = new ExpressionLanguage (null , $ providers , function ($ arg ) {
157
- if ('"" ' === substr_replace ($ arg , '' , 1 , -1 )) {
158
- $ id = stripcslashes (substr ($ arg , 1 , -1 ));
159
- $ id = $ this ->getDefinitionId ($ id );
160
-
161
- $ this ->graph ->connect (
162
- $ this ->currentId ,
163
- $ this ->currentDefinition ,
164
- $ id ,
165
- $ this ->getDefinition ($ id )
166
- );
167
- }
168
-
169
- return sprintf ('$this->get(%s) ' , $ arg );
170
- });
156
+ while (isset ($ this ->aliases [$ id ])) {
157
+ $ id = (string ) $ this ->aliases [$ id ];
171
158
}
172
159
173
- return $ this ->expressionLanguage ;
160
+ return isset ( $ this ->definitions [ $ id ]) ? $ id : null ;
174
161
}
175
162
}
0 commit comments