1414use Symfony \Component \DependencyInjection \Argument \ArgumentInterface ;
1515use Symfony \Component \DependencyInjection \ContainerInterface ;
1616use Symfony \Component \DependencyInjection \Definition ;
17- use Symfony \Component \DependencyInjection \Exception \RuntimeException ;
18- use Symfony \Component \DependencyInjection \ExpressionLanguage ;
1917use Symfony \Component \DependencyInjection \Reference ;
2018use Symfony \Component \DependencyInjection \ContainerBuilder ;
21- use Symfony \Component \ExpressionLanguage \Expression ;
2219
2320/**
2421 * Run this pass before passes that need to know more about the relation of
2825 * retrieve the graph in other passes from the compiler.
2926 *
3027 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
28+ * @author Nicolas Grekas <p@tchwork.com>
3129 */
3230class AnalyzeServiceReferencesPassextends AbstractRecursivePassimplements RepeatablePassInterface
3331{
3432private $ graph ;
3533private $ currentDefinition ;
3634private $ onlyConstructorArguments ;
3735private $ lazy ;
38- private $ expressionLanguage ;
36+ private $ definitions ;
37+ private $ aliases ;
3938
4039/**
4140 * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
4241 */
4342public function __construct (bool $ onlyConstructorArguments =false )
4443 {
4544$ this ->onlyConstructorArguments =$ onlyConstructorArguments ;
45+ $ this ->enableExpressionProcessing ();
4646 }
4747
4848/**
4949 * {@inheritdoc}
5050 */
5151public function setRepeatedPass (RepeatedPass $ repeatedPass )
5252 {
53- // no-op for BC
53+ @ trigger_error ( sprintf ( ' The "%s" method is deprecated since Symfony 4.2. ' , __METHOD__ ), E_USER_DEPRECATED );
5454 }
5555
5656/**
@@ -62,16 +62,22 @@ public function process(ContainerBuilder $container)
6262$ this ->graph =$ container ->getCompiler ()->getServiceReferenceGraph ();
6363$ this ->graph ->clear ();
6464$ this ->lazy =false ;
65+ $ this ->definitions =$ container ->getDefinitions ();
66+ $ this ->aliases =$ container ->getAliases ();
6567
66- foreach ($ container -> getAliases () as $ id =>$ alias ) {
68+ foreach ($ this -> aliases as $ id =>$ alias ) {
6769$ targetId =$ this ->getDefinitionId ((string )$ alias );
68- $ this ->graph ->connect ($ id ,$ alias ,$ targetId ,$ this ->getDefinition ($ targetId ),null );
70+ $ this ->graph ->connect ($ id ,$ alias ,$ targetId ,null !== $ targetId ? $ this ->container -> getDefinition ($ targetId ) : null ,null );
6971 }
7072
71- parent ::process ($ container );
73+ try {
74+ parent ::process ($ container );
75+ }finally {
76+ $ this ->aliases =$ this ->definitions =array ();
77+ }
7278 }
7379
74- protected function processValue ($ value ,$ isRoot =false )
80+ protected function processValue ($ value ,$ isRoot =false , $ inExpression = false )
7581 {
7682$ lazy =$ this ->lazy ;
7783
@@ -82,14 +88,9 @@ protected function processValue($value, $isRoot = false)
8288
8389return $ value ;
8490 }
85- if ($ valueinstanceof Expression) {
86- $ this ->getExpressionLanguage ()->compile ((string )$ value ,array ('this ' =>'container ' ));
87-
88- return $ value ;
89- }
9091if ($ valueinstanceof Reference) {
9192$ targetId =$ this ->getDefinitionId ((string )$ value );
92- $ targetDefinition =$ this ->getDefinition ($ targetId );
93+ $ targetDefinition =null !== $ targetId ? $ this ->container -> getDefinition ($ targetId ) : null ;
9394
9495$ this ->graph ->connect (
9596$ this ->currentId ,
@@ -101,6 +102,18 @@ protected function processValue($value, $isRoot = false)
101102 ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE ===$ value ->getInvalidBehavior ()
102103 );
103104
105+ if ($ inExpression ) {
106+ $ this ->graph ->connect (
107+ '.internal.reference_in_expression ' ,
108+ null ,
109+ $ targetId ,
110+ $ targetDefinition ,
111+ $ value ,
112+ $ this ->lazy || ($ targetDefinition &&$ targetDefinition ->isLazy ()),
113+ true
114+ );
115+ }
116+
104117return $ value ;
105118 }
106119if (!$ valueinstanceof Definition) {
@@ -127,49 +140,12 @@ protected function processValue($value, $isRoot = false)
127140return $ value ;
128141 }
129142
130- private function getDefinition (?string $ id ): ?Definition
131- {
132- return null ===$ id ?null :$ this ->container ->getDefinition ($ id );
133- }
134-
135143private function getDefinitionId (string $ id ): ?string
136144 {
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- });
145+ while (isset ($ this ->aliases [$ id ])) {
146+ $ id = (string )$ this ->aliases [$ id ];
171147 }
172148
173- return $ this ->expressionLanguage ;
149+ return isset ( $ this ->definitions [ $ id ]) ? $ id : null ;
174150 }
175151}