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 ;
15+ use Symfony \Component \HttpKernel \HttpKernelInterface ;
1616use Symfony \Component \HttpKernel \Kernel ;
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
2630 public function __construct (
27- Kernel $ kernel ,
31+ HttpKernelInterface $ kernel ,
32+ /** @var array<string, object> */
2833 public array $ persistentServices = [],
29- private readonly bool $ rebootable = true
34+ private bool $ reboot = true
3035 ) {
3136 parent ::__construct ($ kernel );
3237 $ this ->followRedirects ();
33- $ this ->container = $ this ->getContainer ();
38+ $ this ->container = $ this ->resolveContainer ();
3439 $ this ->rebootKernel ();
3540 }
3641
37- /** @param Request $request */
3842 protected function doRequest (object $ request ): Response
3943 {
40- if ($ this ->rebootable ) {
41- if ($ this ->hasPerformedRequest ) {
42- $ this ->rebootKernel ();
43- } else {
44- $ this ->hasPerformedRequest = true ;
45- }
44+ if ($ this ->reboot ) {
45+ $ this ->hasPerformedRequest ? $ this ->rebootKernel () : $ this ->hasPerformedRequest = true ;
4646 }
4747
4848 return parent ::doRequest ($ request );
@@ -57,30 +57,27 @@ protected function doRequest(object $request): Response
5757 */
5858 public function rebootKernel (): void
5959 {
60- if ($ this ->container ) {
61- foreach (array_keys ($ this ->persistentServices ) as $ serviceName ) {
62- if ($ service = $ this ->getService ($ serviceName )) {
63- $ this ->persistentServices [$ serviceName ] = $ service ;
64- }
60+ foreach (array_keys ($ this ->persistentServices ) as $ service ) {
61+ if ($ this ->container ->has ($ service )) {
62+ $ this ->persistentServices [$ service ] = $ this ->container ->get ($ service );
6563 }
6664 }
6765
6866 $ this ->persistDoctrineConnections ();
69- $ this ->ensureKernelShutdown ();
70- $ this ->kernel ->boot ();
71- $ this ->container = $ this ->getContainer ();
72-
73- foreach ($ this ->persistentServices as $ serviceName => $ service ) {
67+ if ($ this ->kernel instanceof Kernel) {
68+ $ this ->ensureKernelShutdown ();
69+ $ this ->kernel ->boot ();
70+ }
71+ $ this ->container = $ this ->resolveContainer ();
72+ foreach ($ this ->persistentServices as $ name => $ service ) {
7473 try {
75- $ this ->container ->set ($ serviceName , $ service );
74+ $ this ->container ->set ($ name , $ service );
7675 } catch (InvalidArgumentException $ e ) {
77- codecept_debug ("[Symfony] Can't set persistent service {$ serviceName }: " . $ e ->getMessage ());
76+ codecept_debug ("[Symfony] Can't set persistent service {$ name }: { $ e ->getMessage ()}" );
7877 }
7978 }
8079
81- if ($ profiler = $ this ->getProfiler ()) {
82- $ profiler ->enable ();
83- }
80+ $ this ->getProfiler ()?->enable();
8481 }
8582
8683 protected function ensureKernelShutdown (): void
@@ -89,27 +86,25 @@ protected function ensureKernelShutdown(): void
8986 $ this ->kernel ->shutdown ();
9087 }
9188
92- private function getContainer (): ? ContainerInterface
89+ private function resolveContainer (): ContainerInterface
9390 {
94- /** @var ContainerInterface $container */
9591 $ container = $ this ->kernel ->getContainer ();
96- return $ container ->has ('test.service_container ' )
97- ? $ container ->get ('test.service_container ' )
98- : $ container ;
99- }
10092
101- private function getProfiler (): ?Profiler
102- {
103- return $ this ->container ->has ('profiler ' )
104- ? $ this ->container ->get ('profiler ' )
105- : null ;
93+ if ($ container ->has ('test.service_container ' )) {
94+ $ testContainer = $ container ->get ('test.service_container ' );
95+ if (!$ testContainer instanceof ContainerInterface) {
96+ throw new LogicException ('Service "test.service_container" must implement ' . ContainerInterface::class);
97+ }
98+ $ container = $ testContainer ;
99+ }
100+
101+ return $ container ;
106102 }
107103
108- private function getService ( string $ serviceName ): ?object
104+ private function getProfiler ( ): ?Profiler
109105 {
110- return $ this ->container ->has ($ serviceName )
111- ? $ this ->container ->get ($ serviceName )
112- : null ;
106+ $ profiler = $ this ->container ->get ('profiler ' );
107+ return $ profiler instanceof Profiler ? $ profiler : null ;
113108 }
114109
115110 private function persistDoctrineConnections (): void
@@ -119,20 +114,27 @@ private function persistDoctrineConnections(): void
119114 }
120115
121116 if ($ this ->container instanceof TestContainer) {
122- $ reflectedTestContainer = new ReflectionMethod ($ this ->container , 'getPublicContainer ' );
123- $ reflectedTestContainer ->setAccessible (true );
124- $ publicContainer = $ reflectedTestContainer ->invoke ($ this ->container );
117+ $ method = new ReflectionMethod ($ this ->container , 'getPublicContainer ' );
118+ $ publicContainer = $ method ->invoke ($ this ->container );
125119 } else {
126120 $ publicContainer = $ this ->container ;
127121 }
128122
129- $ reflectedContainer = new ReflectionClass ($ publicContainer );
130- $ reflectionTarget = $ reflectedContainer ->hasProperty ('parameters ' ) ? $ publicContainer : $ publicContainer ->getParameterBag ();
123+ if (!is_object ($ publicContainer ) || !method_exists ($ publicContainer , 'getParameterBag ' )) {
124+ return ;
125+ }
126+
127+ $ target = property_exists ($ publicContainer , 'parameters ' )
128+ ? $ publicContainer
129+ : $ publicContainer ->getParameterBag ();
130+
131+ if (!is_object ($ target ) || !property_exists ($ target , 'parameters ' )) {
132+ return ;
133+ }
134+ $ prop = new ReflectionProperty ($ target , 'parameters ' );
131135
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 );
136+ $ params = (array ) $ prop ->getValue ($ target );
137+ unset($ params ['doctrine.connections ' ]);
138+ $ prop ->setValue ($ target , $ params );
137139 }
138140}
0 commit comments