@@ -211,15 +211,15 @@ public function testCreateDefinition()
211211 $ pass ->process ($ container );
212212
213213 $ this ->assertCount (1 , $ container ->getDefinition ('coop_tilleuls ' )->getArguments ());
214- $ this ->assertEquals ('autowired.symfony\component\dependencyinjection\tests\compiler\dunglas ' , $ container ->getDefinition ('coop_tilleuls ' )->getArgument (0 ));
214+ $ this ->assertEquals ('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas ' , $ container ->getDefinition ('coop_tilleuls ' )->getArgument (0 ));
215215
216- $ dunglasDefinition = $ container ->getDefinition ('autowired.symfony\component\dependencyinjection\tests\compiler\dunglas ' );
216+ $ dunglasDefinition = $ container ->getDefinition ('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas ' );
217217 $ this ->assertEquals (__NAMESPACE__ .'\Dunglas ' , $ dunglasDefinition ->getClass ());
218218 $ this ->assertFalse ($ dunglasDefinition ->isPublic ());
219219 $ this ->assertCount (1 , $ dunglasDefinition ->getArguments ());
220- $ this ->assertEquals ('autowired.symfony\component\dependencyinjection\tests\compiler\lille ' , $ dunglasDefinition ->getArgument (0 ));
220+ $ this ->assertEquals ('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Lille ' , $ dunglasDefinition ->getArgument (0 ));
221221
222- $ lilleDefinition = $ container ->getDefinition ('autowired.symfony\component\dependencyinjection\tests\compiler\lille ' );
222+ $ lilleDefinition = $ container ->getDefinition ('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Lille ' );
223223 $ this ->assertEquals (__NAMESPACE__ .'\Lille ' , $ lilleDefinition ->getClass ());
224224 }
225225
@@ -429,6 +429,107 @@ public function testOptionalScalarArgsNotPassedIfLast()
429429 );
430430 }
431431
432+ public function testSetterInjection ()
433+ {
434+ $ container = new ContainerBuilder ();
435+ $ container ->register ('app_foo ' , Foo::class);
436+ $ container ->register ('app_a ' , A::class);
437+ $ container ->register ('app_collision_a ' , CollisionA::class);
438+ $ container ->register ('app_collision_b ' , CollisionB::class);
439+
440+ // manually configure *one* call, to override autowiring
441+ $ container
442+ ->register ('setter_injection ' , SetterInjection::class)
443+ ->setAutowiredMethods (array ('__construct ' , 'set* ' ))
444+ ->addMethodCall ('setWithCallsConfigured ' , array ('manual_arg1 ' , 'manual_arg2 ' ))
445+ ;
446+
447+ $ pass = new AutowirePass ();
448+ $ pass ->process ($ container );
449+
450+ $ methodCalls = $ container ->getDefinition ('setter_injection ' )->getMethodCalls ();
451+
452+ // grab the call method names
453+ $ actualMethodNameCalls = array_map (function ($ call ) {
454+ return $ call [0 ];
455+ }, $ methodCalls );
456+ $ this ->assertEquals (
457+ array ('setWithCallsConfigured ' , 'setFoo ' , 'setDependencies ' ),
458+ $ actualMethodNameCalls
459+ );
460+
461+ // test setWithCallsConfigured args
462+ $ this ->assertEquals (
463+ array ('manual_arg1 ' , 'manual_arg2 ' ),
464+ $ methodCalls [0 ][1 ]
465+ );
466+ // test setFoo args
467+ $ this ->assertEquals (
468+ array (new Reference ('app_foo ' )),
469+ $ methodCalls [1 ][1 ]
470+ );
471+ }
472+
473+ public function testExplicitMethodInjection ()
474+ {
475+ $ container = new ContainerBuilder ();
476+ $ container ->register ('app_foo ' , Foo::class);
477+ $ container ->register ('app_a ' , A::class);
478+ $ container ->register ('app_collision_a ' , CollisionA::class);
479+ $ container ->register ('app_collision_b ' , CollisionB::class);
480+
481+ $ container
482+ ->register ('setter_injection ' , SetterInjection::class)
483+ ->setAutowiredMethods (array ('setFoo ' , 'notASetter ' ))
484+ ;
485+
486+ $ pass = new AutowirePass ();
487+ $ pass ->process ($ container );
488+
489+ $ methodCalls = $ container ->getDefinition ('setter_injection ' )->getMethodCalls ();
490+
491+ $ actualMethodNameCalls = array_map (function ($ call ) {
492+ return $ call [0 ];
493+ }, $ methodCalls );
494+ $ this ->assertEquals (
495+ array ('setFoo ' , 'notASetter ' ),
496+ $ actualMethodNameCalls
497+ );
498+ }
499+
500+ /**
501+ * @dataProvider getCreateResourceTests
502+ */
503+ public function testCreateResourceForClass ($ className , $ isEqual )
504+ {
505+ $ startingResource = AutowirePass::createResourceForClass (
506+ new \ReflectionClass (__NAMESPACE__ .'\ClassForResource ' )
507+ );
508+ $ newResource = AutowirePass::createResourceForClass (
509+ new \ReflectionClass (__NAMESPACE__ .'\\' .$ className )
510+ );
511+
512+ // hack so the objects don't differ by the class name
513+ $ startingReflObject = new \ReflectionObject ($ startingResource );
514+ $ reflProp = $ startingReflObject ->getProperty ('class ' );
515+ $ reflProp ->setAccessible (true );
516+ $ reflProp ->setValue ($ startingResource , __NAMESPACE__ .'\\' .$ className );
517+
518+ if ($ isEqual ) {
519+ $ this ->assertEquals ($ startingResource , $ newResource );
520+ } else {
521+ $ this ->assertNotEquals ($ startingResource , $ newResource );
522+ }
523+ }
524+
525+ public function getCreateResourceTests ()
526+ {
527+ return array (
528+ array ('IdenticalClassResource ' , true ),
529+ array ('ClassChangedConstructorArgs ' , false ),
530+ );
531+ }
532+
432533 public function testIgnoreServiceWithClassNotExisting ()
433534 {
434535 $ container = new ContainerBuilder ();
@@ -443,6 +544,37 @@ public function testIgnoreServiceWithClassNotExisting()
443544
444545 $ this ->assertTrue ($ container ->hasDefinition ('bar ' ));
445546 }
547+
548+ /**
549+ * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
550+ * @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "setter_injection_collision". Multiple services exist for this interface (c1, c2).
551+ * @expectedExceptionCode 1
552+ */
553+ public function testSetterInjectionCollisionThrowsException ()
554+ {
555+ $ container = new ContainerBuilder ();
556+
557+ $ container ->register ('c1 ' , CollisionA::class);
558+ $ container ->register ('c2 ' , CollisionB::class);
559+ $ aDefinition = $ container ->register ('setter_injection_collision ' , SetterInjectionCollision::class);
560+ $ aDefinition ->setAutowiredMethods (array ('__construct ' , 'set* ' ));
561+
562+ $ pass = new AutowirePass ();
563+ $ pass ->process ($ container );
564+ }
565+
566+ public function testLogUnusedPatterns ()
567+ {
568+ $ container = new ContainerBuilder ();
569+
570+ $ definition = $ container ->register ('foo ' , Foo::class);
571+ $ definition ->setAutowiredMethods (array ('not ' , 'exist* ' ));
572+
573+ $ pass = new AutowirePass ();
574+ $ pass ->process ($ container );
575+
576+ $ this ->assertEquals (array (AutowirePass::class.': Autowiring \'s patterns "not", "exist*" for service "foo" don \'t match any method. ' ), $ container ->getCompiler ()->getLog ());
577+ }
446578}
447579
448580class Foo
@@ -598,3 +730,91 @@ public function __construct(A $a, $foo = 'default_val', Lille $lille)
598730 {
599731 }
600732}
733+
734+ /*
735+ * Classes used for testing createResourceForClass
736+ */
737+ class ClassForResource
738+ {
739+ public function __construct ($ foo , Bar $ bar = null )
740+ {
741+ }
742+
743+ public function setBar (Bar $ bar )
744+ {
745+ }
746+ }
747+ class IdenticalClassResource extends ClassForResource
748+ {
749+ }
750+
751+ class ClassChangedConstructorArgs extends ClassForResource
752+ {
753+ public function __construct ($ foo , Bar $ bar , $ baz )
754+ {
755+ }
756+ }
757+
758+ class SetterInjection
759+ {
760+ public function setFoo (Foo $ foo )
761+ {
762+ // should be called
763+ }
764+
765+ public function setDependencies (Foo $ foo , A $ a )
766+ {
767+ // should be called
768+ }
769+
770+ public function setBar ()
771+ {
772+ // should not be called
773+ }
774+
775+ public function setNotAutowireable (NotARealClass $ n )
776+ {
777+ // should not be called
778+ }
779+
780+ public function setArgCannotAutowire ($ foo )
781+ {
782+ // should not be called
783+ }
784+
785+ public function setOptionalNotAutowireable (NotARealClass $ n = null )
786+ {
787+ // should not be called
788+ }
789+
790+ public function setOptionalNoTypeHint ($ foo = null )
791+ {
792+ // should not be called
793+ }
794+
795+ public function setOptionalArgNoAutowireable ($ other = 'default_val ' )
796+ {
797+ // should not be called
798+ }
799+
800+ public function setWithCallsConfigured (A $ a )
801+ {
802+ // this method has a calls configured on it
803+ // should not be called
804+ }
805+
806+ public function notASetter (A $ a )
807+ {
808+ // should be called only when explicitly specified
809+ }
810+ }
811+
812+ class SetterInjectionCollision
813+ {
814+ public function setMultipleInstancesForOneArg (CollisionInterface $ collision )
815+ {
816+ // The CollisionInterface cannot be autowired - there are multiple
817+
818+ // should throw an exception
819+ }
820+ }
0 commit comments