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 \HttpKernelInterface ;
17+ use Symfony \Component \HttpKernel \KernelInterface ;
1718use Symfony \Component \HttpKernel \Profiler \Profiler ;
18- use function array_keys ;
19+
1920use function codecept_debug ;
2021
22+ /**
23+ * @property KernelInterface $kernel
24+ */
2125class Symfony extends HttpKernelBrowser
2226{
27+ private ContainerInterface $ container ;
2328 private bool $ hasPerformedRequest = false ;
24- private ?ContainerInterface $ container ;
2529
30+ /**
31+ * @param Kernel $kernel
32+ * @param array<string, object> $persistentServices
33+ */
2634 public function __construct (
27- Kernel $ kernel ,
35+ $ kernel ,
2836 public array $ persistentServices = [],
29- private readonly bool $ rebootable = true
37+ private bool $ reboot = true
3038 ) {
3139 parent ::__construct ($ kernel );
3240 $ this ->followRedirects ();
33- $ this ->container = $ this ->getContainer ();
41+ $ this ->container = $ this ->resolveContainer ();
3442 $ this ->rebootKernel ();
3543 }
3644
37- /** @param Request $request */
3845 protected function doRequest (object $ request ): Response
3946 {
40- if ($ this ->rebootable ) {
41- if ($ this ->hasPerformedRequest ) {
42- $ this ->rebootKernel ();
43- } else {
44- $ this ->hasPerformedRequest = true ;
45- }
47+ if ($ this ->reboot ) {
48+ $ this ->hasPerformedRequest ? $ this ->rebootKernel () : $ this ->hasPerformedRequest = true ;
4649 }
4750
4851 return parent ::doRequest ($ request );
@@ -57,30 +60,27 @@ protected function doRequest(object $request): Response
5760 */
5861 public function rebootKernel (): void
5962 {
60- if ($ this ->container ) {
61- foreach (array_keys ($ this ->persistentServices ) as $ serviceName ) {
62- if ($ service = $ this ->getService ($ serviceName )) {
63- $ this ->persistentServices [$ serviceName ] = $ service ;
64- }
63+ foreach (array_keys ($ this ->persistentServices ) as $ service ) {
64+ if ($ this ->container ->has ($ service )) {
65+ $ this ->persistentServices [$ service ] = $ this ->container ->get ($ service );
6566 }
6667 }
6768
6869 $ this ->persistDoctrineConnections ();
69- $ this ->ensureKernelShutdown ();
70- $ this ->kernel ->boot ();
71- $ this ->container = $ this ->getContainer ();
72-
73- foreach ($ this ->persistentServices as $ serviceName => $ service ) {
70+ if ($ this ->kernel instanceof Kernel) {
71+ $ this ->ensureKernelShutdown ();
72+ $ this ->kernel ->boot ();
73+ }
74+ $ this ->container = $ this ->resolveContainer ();
75+ foreach ($ this ->persistentServices as $ name => $ service ) {
7476 try {
75- $ this ->container ->set ($ serviceName , $ service );
77+ $ this ->container ->set ($ name , $ service );
7678 } catch (InvalidArgumentException $ e ) {
77- codecept_debug ("[Symfony] Can't set persistent service {$ serviceName }: " . $ e ->getMessage ());
79+ codecept_debug ("[Symfony] Can't set persistent service {$ name }: { $ e ->getMessage ()}" );
7880 }
7981 }
8082
81- if ($ profiler = $ this ->getProfiler ()) {
82- $ profiler ->enable ();
83- }
83+ $ this ->getProfiler ()?->enable();
8484 }
8585
8686 protected function ensureKernelShutdown (): void
@@ -89,27 +89,25 @@ protected function ensureKernelShutdown(): void
8989 $ this ->kernel ->shutdown ();
9090 }
9191
92- private function getContainer (): ? ContainerInterface
92+ private function resolveContainer (): ContainerInterface
9393 {
94- /** @var ContainerInterface $container */
9594 $ container = $ this ->kernel ->getContainer ();
96- return $ container ->has ('test.service_container ' )
97- ? $ container ->get ('test.service_container ' )
98- : $ container ;
99- }
10095
101- private function getProfiler (): ?Profiler
102- {
103- return $ this ->container ->has ('profiler ' )
104- ? $ this ->container ->get ('profiler ' )
105- : null ;
96+ if ($ container ->has ('test.service_container ' )) {
97+ $ testContainer = $ container ->get ('test.service_container ' );
98+ if (!$ testContainer instanceof ContainerInterface) {
99+ throw new LogicException ('Service "test.service_container" must implement ' . ContainerInterface::class);
100+ }
101+ $ container = $ testContainer ;
102+ }
103+
104+ return $ container ;
106105 }
107106
108- private function getService ( string $ serviceName ): ?object
107+ private function getProfiler ( ): ?Profiler
109108 {
110- return $ this ->container ->has ($ serviceName )
111- ? $ this ->container ->get ($ serviceName )
112- : null ;
109+ $ profiler = $ this ->container ->get ('profiler ' );
110+ return $ profiler instanceof Profiler ? $ profiler : null ;
113111 }
114112
115113 private function persistDoctrineConnections (): void
@@ -119,20 +117,27 @@ private function persistDoctrineConnections(): void
119117 }
120118
121119 if ($ this ->container instanceof TestContainer) {
122- $ reflectedTestContainer = new ReflectionMethod ($ this ->container , 'getPublicContainer ' );
123- $ reflectedTestContainer ->setAccessible (true );
124- $ publicContainer = $ reflectedTestContainer ->invoke ($ this ->container );
120+ $ method = new ReflectionMethod ($ this ->container , 'getPublicContainer ' );
121+ $ publicContainer = $ method ->invoke ($ this ->container );
125122 } else {
126123 $ publicContainer = $ this ->container ;
127124 }
128125
129- $ reflectedContainer = new ReflectionClass ($ publicContainer );
130- $ reflectionTarget = $ reflectedContainer ->hasProperty ('parameters ' ) ? $ publicContainer : $ publicContainer ->getParameterBag ();
126+ if (!is_object ($ publicContainer ) || !method_exists ($ publicContainer , 'getParameterBag ' )) {
127+ return ;
128+ }
129+
130+ $ target = property_exists ($ publicContainer , 'parameters ' )
131+ ? $ publicContainer
132+ : $ publicContainer ->getParameterBag ();
133+
134+ if (!is_object ($ target ) || !property_exists ($ target , 'parameters ' )) {
135+ return ;
136+ }
137+ $ prop = new ReflectionProperty ($ target , 'parameters ' );
131138
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 );
139+ $ params = (array ) $ prop ->getValue ($ target );
140+ unset($ params ['doctrine.connections ' ]);
141+ $ prop ->setValue ($ target , $ params );
137142 }
138143}
0 commit comments