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 AnalyzeServiceReferencesPass extends AbstractRecursivePass implements RepeatablePassInterface
3331{
3432 private $ graph ;
3533 private $ currentDefinition ;
3634 private $ onlyConstructorArguments ;
3735 private $ 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 */
4342 public function __construct (bool $ onlyConstructorArguments = false )
4443 {
4544 $ this ->onlyConstructorArguments = $ onlyConstructorArguments ;
45+ $ this ->enableExpressionProcessing ();
4646 }
4747
4848 /**
4949 * {@inheritdoc}
5050 */
5151 public 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
8389 return $ value ;
8490 }
85- if ($ value instanceof Expression) {
86- $ this ->getExpressionLanguage ()->compile ((string ) $ value , array ('this ' => 'container ' ));
87-
88- return $ value ;
89- }
9091 if ($ value instanceof 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+
104117 return $ value ;
105118 }
106119 if (!$ value instanceof Definition) {
@@ -127,49 +140,12 @@ protected function processValue($value, $isRoot = false)
127140 return $ value ;
128141 }
129142
130- private function getDefinition (?string $ id ): ?Definition
131- {
132- return null === $ id ? null : $ this ->container ->getDefinition ($ id );
133- }
134-
135143 private 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}
0 commit comments