2828use function explode ;
2929use function implode ;
3030use function is_array ;
31+ use function is_bool ;
32+ use function preg_match ;
3133use function preg_split ;
3234use function sprintf ;
3335use function strcasecmp ;
3941final class AutowiredAttributeServicesExtension extends CompilerExtension
4042{
4143
44+ /** @var list<array{ServiceDefinition, string, string}> */
45+ private array $ conditionalTags = [];
46+
4247 #[Override]
4348 public function getConfigSchema (): Schema
4449 {
@@ -140,9 +145,9 @@ public function loadConfiguration(): void
140145
141146 $ definition = $ builder ->addDefinition (null )
142147 ->setFactory ($ class ->name )
143- ->setAutowired ($ class ->name )
144- ->addTag (LazyRegistry::RULE_TAG );
148+ ->setAutowired ($ class ->name );
145149
150+ $ this ->tag ($ definition , LazyRegistry::RULE_TAG , $ attribute ->enabledBy );
146151 self ::processConstructorParameters ($ builder , $ class ->name , $ definition , $ constructorParameters );
147152 }
148153
@@ -154,13 +159,59 @@ public function loadConfiguration(): void
154159
155160 $ definition = $ builder ->addDefinition (null )
156161 ->setFactory ($ class ->name )
157- ->setAutowired ($ class ->name )
158- ->addTag (RegistryFactory::COLLECTOR_TAG );
162+ ->setAutowired ($ class ->name );
159163
164+ $ this ->tag ($ definition , RegistryFactory::COLLECTOR_TAG , $ attribute ->enabledBy );
160165 self ::processConstructorParameters ($ builder , $ class ->name , $ definition , $ constructorParameters );
161166 }
162167 }
163168
169+ private function tag (ServiceDefinition $ definition , string $ tag , ?string $ enabledBy ): void
170+ {
171+ if ($ enabledBy === null ) {
172+ $ definition ->addTag ($ tag );
173+
174+ return ;
175+ }
176+
177+ $ this ->conditionalTags [] = [$ definition , $ tag , $ enabledBy ];
178+ }
179+
180+ #[Override]
181+ public function beforeCompile (): void
182+ {
183+ $ builder = $ this ->getContainerBuilder ();
184+ foreach ($ this ->conditionalTags as [$ definition , $ tag , $ enabledBy ]) {
185+ if (!self ::resolveCondition ($ builder , $ enabledBy )) {
186+ continue ;
187+ }
188+
189+ $ definition ->addTag ($ tag );
190+ }
191+ }
192+
193+ private static function resolveCondition (ContainerBuilder $ builder , string $ enabledBy ): bool
194+ {
195+ if (preg_match ('#^%([\w.-]+)%$#D ' , $ enabledBy , $ matches ) !== 1 ) {
196+ throw new ShouldNotHappenException (sprintf ('enabledBy must be a parameter reference, %s given. ' , $ enabledBy ));
197+ }
198+
199+ $ parameter = $ builder ->parameters ;
200+ foreach (explode ('. ' , $ matches [1 ]) as $ key ) {
201+ if (!is_array ($ parameter ) || !array_key_exists ($ key , $ parameter )) {
202+ throw new ShouldNotHappenException (sprintf ("Missing parameter '%s'. " , $ matches [1 ]));
203+ }
204+
205+ $ parameter = $ parameter [$ key ];
206+ }
207+
208+ if (!is_bool ($ parameter )) {
209+ throw new ShouldNotHappenException (sprintf ('Parameter %s referenced by enabledBy must be bool. ' , $ enabledBy ));
210+ }
211+
212+ return $ parameter ;
213+ }
214+
164215 /**
165216 * @param class-string $className
166217 * @param array<lowercase-string, non-empty-list<TargetMethodParameter<AutowiredParameter>>> $constructorParameters
0 commit comments