55namespace Codeception \Lib \Connector ;
66
77use InvalidArgumentException ;
8- use ReflectionClass ;
8+ use LogicException ;
99use ReflectionMethod ;
1010use ReflectionProperty ;
1111use Symfony \Bundle \FrameworkBundle \Test \TestContainer ;
1212use Symfony \Component \DependencyInjection \ContainerInterface ;
13- use Symfony \Component \HttpFoundation \Request ;
1413use Symfony \Component \HttpFoundation \Response ;
1514use Symfony \Component \HttpKernel \HttpKernelBrowser ;
1615use Symfony \Component \HttpKernel \Kernel ;
16+ use Symfony \Component \HttpKernel \KernelInterface ;
1717use Symfony \Component \HttpKernel \Profiler \Profiler ;
18- use function array_keys ;
18+
1919use function codecept_debug ;
2020
21+ /**
22+ * @property KernelInterface $kernel
23+ */
2124class Symfony extends HttpKernelBrowser
2225{
26+ private ContainerInterface $ container ;
2327 private bool $ hasPerformedRequest = false ;
24- private ?ContainerInterface $ container ;
2528
29+ /**
30+ * @param Kernel $kernel
31+ * @param array<string, object> $persistentServices
32+ */
2633 public function __construct (
27- Kernel $ kernel ,
34+ $ kernel ,
2835 public array $ persistentServices = [],
29- private readonly bool $ rebootable = true
36+ private bool $ reboot = true
3037 ) {
3138 parent ::__construct ($ kernel );
3239 $ this ->followRedirects ();
33- $ this ->container = $ this ->getContainer ();
40+ $ this ->container = $ this ->resolveContainer ();
3441 $ this ->rebootKernel ();
3542 }
3643
37- /** @param Request $request */
3844 protected function doRequest (object $ request ): Response
3945 {
40- if ($ this ->rebootable ) {
41- if ($ this ->hasPerformedRequest ) {
42- $ this ->rebootKernel ();
43- } else {
44- $ this ->hasPerformedRequest = true ;
45- }
46+ if ($ this ->reboot ) {
47+ $ this ->hasPerformedRequest ? $ this ->rebootKernel () : $ this ->hasPerformedRequest = true ;
4648 }
4749
4850 return parent ::doRequest ($ request );
@@ -57,30 +59,27 @@ protected function doRequest(object $request): Response
5759 */
5860 public function rebootKernel (): void
5961 {
60- if ($ this ->container ) {
61- foreach (array_keys ($ this ->persistentServices ) as $ serviceName ) {
62- if ($ service = $ this ->getService ($ serviceName )) {
63- $ this ->persistentServices [$ serviceName ] = $ service ;
64- }
62+ foreach (array_keys ($ this ->persistentServices ) as $ service ) {
63+ if ($ this ->container ->has ($ service )) {
64+ $ this ->persistentServices [$ service ] = $ this ->container ->get ($ service );
6565 }
6666 }
6767
6868 $ this ->persistDoctrineConnections ();
69- $ this ->ensureKernelShutdown ();
70- $ this ->kernel ->boot ();
71- $ this ->container = $ this ->getContainer ();
72-
73- foreach ($ this ->persistentServices as $ serviceName => $ service ) {
69+ if ($ this ->kernel instanceof Kernel) {
70+ $ this ->ensureKernelShutdown ();
71+ $ this ->kernel ->boot ();
72+ }
73+ $ this ->container = $ this ->resolveContainer ();
74+ foreach ($ this ->persistentServices as $ name => $ service ) {
7475 try {
75- $ this ->container ->set ($ serviceName , $ service );
76+ $ this ->container ->set ($ name , $ service );
7677 } catch (InvalidArgumentException $ e ) {
77- codecept_debug ("[Symfony] Can't set persistent service {$ serviceName }: " . $ e ->getMessage ());
78+ codecept_debug ("[Symfony] Can't set persistent service {$ name }: { $ e ->getMessage ()}" );
7879 }
7980 }
8081
81- if ($ profiler = $ this ->getProfiler ()) {
82- $ profiler ->enable ();
83- }
82+ $ this ->getProfiler ()?->enable();
8483 }
8584
8685 protected function ensureKernelShutdown (): void
@@ -89,27 +88,25 @@ protected function ensureKernelShutdown(): void
8988 $ this ->kernel ->shutdown ();
9089 }
9190
92- private function getContainer (): ? ContainerInterface
91+ private function resolveContainer (): ContainerInterface
9392 {
94- /** @var ContainerInterface $container */
9593 $ container = $ this ->kernel ->getContainer ();
96- return $ container ->has ('test.service_container ' )
97- ? $ container ->get ('test.service_container ' )
98- : $ container ;
99- }
10094
101- private function getProfiler (): ?Profiler
102- {
103- return $ this ->container ->has ('profiler ' )
104- ? $ this ->container ->get ('profiler ' )
105- : null ;
95+ if ($ container ->has ('test.service_container ' )) {
96+ $ testContainer = $ container ->get ('test.service_container ' );
97+ if (!$ testContainer instanceof ContainerInterface) {
98+ throw new LogicException ('Service "test.service_container" must implement ' . ContainerInterface::class);
99+ }
100+ $ container = $ testContainer ;
101+ }
102+
103+ return $ container ;
106104 }
107105
108- private function getService ( string $ serviceName ): ?object
106+ private function getProfiler ( ): ?Profiler
109107 {
110- return $ this ->container ->has ($ serviceName )
111- ? $ this ->container ->get ($ serviceName )
112- : null ;
108+ $ profiler = $ this ->container ->get ('profiler ' );
109+ return $ profiler instanceof Profiler ? $ profiler : null ;
113110 }
114111
115112 private function persistDoctrineConnections (): void
@@ -119,20 +116,27 @@ private function persistDoctrineConnections(): void
119116 }
120117
121118 if ($ this ->container instanceof TestContainer) {
122- $ reflectedTestContainer = new ReflectionMethod ($ this ->container , 'getPublicContainer ' );
123- $ reflectedTestContainer ->setAccessible (true );
124- $ publicContainer = $ reflectedTestContainer ->invoke ($ this ->container );
119+ $ method = new ReflectionMethod ($ this ->container , 'getPublicContainer ' );
120+ $ publicContainer = $ method ->invoke ($ this ->container );
125121 } else {
126122 $ publicContainer = $ this ->container ;
127123 }
128124
129- $ reflectedContainer = new ReflectionClass ($ publicContainer );
130- $ reflectionTarget = $ reflectedContainer ->hasProperty ('parameters ' ) ? $ publicContainer : $ publicContainer ->getParameterBag ();
125+ if (!is_object ($ publicContainer ) || !method_exists ($ publicContainer , 'getParameterBag ' )) {
126+ return ;
127+ }
128+
129+ $ target = property_exists ($ publicContainer , 'parameters ' )
130+ ? $ publicContainer
131+ : $ publicContainer ->getParameterBag ();
132+
133+ if (!is_object ($ target ) || !property_exists ($ target , 'parameters ' )) {
134+ return ;
135+ }
136+ $ prop = new ReflectionProperty ($ target , 'parameters ' );
131137
132- $ reflectedParameters = new ReflectionProperty ($ reflectionTarget , 'parameters ' );
133- $ reflectedParameters ->setAccessible (true );
134- $ parameters = $ reflectedParameters ->getValue ($ reflectionTarget );
135- unset($ parameters ['doctrine.connections ' ]);
136- $ reflectedParameters ->setValue ($ reflectionTarget , $ parameters );
138+ $ params = (array ) $ prop ->getValue ($ target );
139+ unset($ params ['doctrine.connections ' ]);
140+ $ prop ->setValue ($ target , $ params );
137141 }
138142}
0 commit comments