2424use Symfony \Component \DependencyInjection \Reference ;
2525use Symfony \Component \DependencyInjection \ServiceLocator ;
2626use Symfony \Component \DependencyInjection \Tests \Fixtures \CustomDefinition ;
27+ use Symfony \Component \DependencyInjection \Tests \Fixtures \LegacyTestServiceSubscriberChild ;
28+ use Symfony \Component \DependencyInjection \Tests \Fixtures \LegacyTestServiceSubscriberParent ;
2729use Symfony \Component \DependencyInjection \Tests \Fixtures \TestDefinition1 ;
2830use Symfony \Component \DependencyInjection \Tests \Fixtures \TestDefinition2 ;
2931use Symfony \Component \DependencyInjection \Tests \Fixtures \TestDefinition3 ;
3032use Symfony \Component \DependencyInjection \Tests \Fixtures \TestServiceSubscriber ;
3133use Symfony \Component \DependencyInjection \Tests \Fixtures \TestServiceSubscriberChild ;
3234use Symfony \Component \DependencyInjection \Tests \Fixtures \TestServiceSubscriberParent ;
3335use Symfony \Component \DependencyInjection \TypedReference ;
36+ use Symfony \Contracts \Service \Attribute \SubscribedService ;
3437use Symfony \Contracts \Service \ServiceSubscriberInterface ;
3538use Symfony \Contracts \Service \ServiceSubscriberTrait ;
3639
@@ -143,11 +146,14 @@ public function testExtraServiceSubscriber()
143146 $ container ->compile ();
144147 }
145148
149+ /**
150+ * @group legacy
151+ */
146152 public function testServiceSubscriberTrait ()
147153 {
148154 $ container = new ContainerBuilder ();
149155
150- $ container ->register ('foo ' , TestServiceSubscriberChild ::class)
156+ $ container ->register ('foo ' , LegacyTestServiceSubscriberChild ::class)
151157 ->addMethodCall ('setContainer ' , [new Reference (PsrContainerInterface::class)])
152158 ->addTag ('container.service_subscriber ' )
153159 ;
@@ -159,15 +165,18 @@ public function testServiceSubscriberTrait()
159165 $ locator = $ container ->getDefinition ((string ) $ foo ->getMethodCalls ()[0 ][1 ][0 ]);
160166
161167 $ expected = [
162- TestServiceSubscriberChild ::class.'::invalidDefinition ' => new ServiceClosureArgument (new TypedReference ('Symfony\Component\DependencyInjection\Tests\Fixtures\InvalidDefinition ' , 'Symfony\Component\DependencyInjection\Tests\Fixtures\InvalidDefinition ' , ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
163- TestServiceSubscriberChild ::class.'::testDefinition2 ' => new ServiceClosureArgument (new TypedReference (TestDefinition2::class, TestDefinition2::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
164- TestServiceSubscriberChild ::class.'::testDefinition3 ' => new ServiceClosureArgument (new TypedReference (TestDefinition3::class, TestDefinition3::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
165- TestServiceSubscriberParent ::class.'::testDefinition1 ' => new ServiceClosureArgument (new TypedReference (TestDefinition1::class, TestDefinition1::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
168+ LegacyTestServiceSubscriberChild ::class.'::invalidDefinition ' => new ServiceClosureArgument (new TypedReference ('Symfony\Component\DependencyInjection\Tests\Fixtures\InvalidDefinition ' , 'Symfony\Component\DependencyInjection\Tests\Fixtures\InvalidDefinition ' , ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
169+ LegacyTestServiceSubscriberChild ::class.'::testDefinition2 ' => new ServiceClosureArgument (new TypedReference (TestDefinition2::class, TestDefinition2::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
170+ LegacyTestServiceSubscriberChild ::class.'::testDefinition3 ' => new ServiceClosureArgument (new TypedReference (TestDefinition3::class, TestDefinition3::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
171+ LegacyTestServiceSubscriberParent ::class.'::testDefinition1 ' => new ServiceClosureArgument (new TypedReference (TestDefinition1::class, TestDefinition1::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
166172 ];
167173
168174 $ this ->assertEquals ($ expected , $ container ->getDefinition ((string ) $ locator ->getFactory ()[0 ])->getArgument (0 ));
169175 }
170176
177+ /**
178+ * @group legacy
179+ */
171180 public function testServiceSubscriberTraitWithGetter ()
172181 {
173182 $ container = new ContainerBuilder ();
@@ -195,6 +204,108 @@ public function getFoo(): \stdClass
195204 $ this ->assertEquals ($ expected , $ container ->getDefinition ((string ) $ locator ->getFactory ()[0 ])->getArgument (0 ));
196205 }
197206
207+ /**
208+ * @requires PHP 8
209+ */
210+ public function testServiceSubscriberTraitWithSubscribedServiceAttribute ()
211+ {
212+ if (!class_exists (SubscribedService::class)) {
213+ $ this ->markTestSkipped ('SubscribedService attribute not available. ' );
214+ }
215+
216+ $ container = new ContainerBuilder ();
217+
218+ $ container ->register ('foo ' , TestServiceSubscriberChild::class)
219+ ->addMethodCall ('setContainer ' , [new Reference (PsrContainerInterface::class)])
220+ ->addTag ('container.service_subscriber ' )
221+ ;
222+
223+ (new RegisterServiceSubscribersPass ())->process ($ container );
224+ (new ResolveServiceSubscribersPass ())->process ($ container );
225+
226+ $ foo = $ container ->getDefinition ('foo ' );
227+ $ locator = $ container ->getDefinition ((string ) $ foo ->getMethodCalls ()[0 ][1 ][0 ]);
228+
229+ $ expected = [
230+ TestServiceSubscriberChild::class.'::invalidDefinition ' => new ServiceClosureArgument (new TypedReference ('Symfony\Component\DependencyInjection\Tests\Fixtures\InvalidDefinition ' , 'Symfony\Component\DependencyInjection\Tests\Fixtures\InvalidDefinition ' )),
231+ TestServiceSubscriberChild::class.'::testDefinition2 ' => new ServiceClosureArgument (new TypedReference (TestDefinition2::class, TestDefinition2::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE )),
232+ TestServiceSubscriberChild::class.'::testDefinition4 ' => new ServiceClosureArgument (new TypedReference (TestDefinition3::class, TestDefinition3::class)),
233+ TestServiceSubscriberParent::class.'::testDefinition1 ' => new ServiceClosureArgument (new TypedReference (TestDefinition1::class, TestDefinition1::class)),
234+ 'custom_name ' => new ServiceClosureArgument (new TypedReference (TestDefinition3::class, TestDefinition3::class, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE , 'custom_name ' )),
235+ ];
236+
237+ $ this ->assertEquals ($ expected , $ container ->getDefinition ((string ) $ locator ->getFactory ()[0 ])->getArgument (0 ));
238+ }
239+
240+ /**
241+ * @requires PHP 8
242+ */
243+ public function testServiceSubscriberTraitWithSubscribedServiceAttributeOnStaticMethod ()
244+ {
245+ if (!class_exists (SubscribedService::class)) {
246+ $ this ->markTestSkipped ('SubscribedService attribute not available. ' );
247+ }
248+
249+ $ subscriber = new class () implements ServiceSubscriberInterface {
250+ use ServiceSubscriberTrait;
251+
252+ #[SubscribedService]
253+ public static function method (): TestDefinition1
254+ {
255+ }
256+ };
257+
258+ $ this ->expectException (\LogicException::class);
259+
260+ $ subscriber ::getSubscribedServices ();
261+ }
262+
263+ /**
264+ * @requires PHP 8
265+ */
266+ public function testServiceSubscriberTraitWithSubscribedServiceAttributeOnMethodWithRequiredParameters ()
267+ {
268+ if (!class_exists (SubscribedService::class)) {
269+ $ this ->markTestSkipped ('SubscribedService attribute not available. ' );
270+ }
271+
272+ $ subscriber = new class () implements ServiceSubscriberInterface {
273+ use ServiceSubscriberTrait;
274+
275+ #[SubscribedService]
276+ public function method ($ param1 , $ param2 = null ): TestDefinition1
277+ {
278+ }
279+ };
280+
281+ $ this ->expectException (\LogicException::class);
282+
283+ $ subscriber ::getSubscribedServices ();
284+ }
285+
286+ /**
287+ * @requires PHP 8
288+ */
289+ public function testServiceSubscriberTraitWithSubscribedServiceAttributeOnMethodMissingReturnType ()
290+ {
291+ if (!class_exists (SubscribedService::class)) {
292+ $ this ->markTestSkipped ('SubscribedService attribute not available. ' );
293+ }
294+
295+ $ subscriber = new class () implements ServiceSubscriberInterface {
296+ use ServiceSubscriberTrait;
297+
298+ #[SubscribedService]
299+ public function method ()
300+ {
301+ }
302+ };
303+
304+ $ this ->expectException (\LogicException::class);
305+
306+ $ subscriber ::getSubscribedServices ();
307+ }
308+
198309 public function testServiceSubscriberWithSemanticId ()
199310 {
200311 $ container = new ContainerBuilder ();
0 commit comments