11<?php
22namespace Codeception \Lib \Connector ;
33
4+ use Illuminate \Database \Eloquent \Model ;
45use Illuminate \Foundation \Application ;
6+ use Symfony \Component \BrowserKit \Request as BrowserKitRequest ;
57use Symfony \Component \HttpFoundation \Request ;
68use Symfony \Component \HttpFoundation \Response ;
79use Symfony \Component \HttpKernel \Client ;
8- use Symfony \Component \HttpKernel \HttpKernelInterface ;
9- use Symfony \Component \HttpKernel \TerminableInterface ;
1010
11- class Laravel4 extends Client implements HttpKernelInterface, TerminableInterface
11+ class Laravel4 extends Client
1212{
1313
1414 /**
15- * @var Application
15+ * @var \Illuminate\Foundation\ Application
1616 */
1717 private $ app ;
1818
1919 /**
20- * @var HttpKernelInterface
20+ * @var \Codeception\Module\Laravel4
2121 */
22- private $ httpKernel ;
22+ private $ module ;
2323
2424 /**
2525 * Constructor.
2626 *
27- * @param Application $app
27+ * @param \Codeception\Module\Laravel4 $module
2828 */
29- public function __construct (Application $ app )
29+ public function __construct ($ module )
3030 {
31- $ this ->app = $ app ;
32- $ this ->app ->boot ();
33- $ this ->httpKernel = $ this ->getStackedClient ();
31+ $ this ->module = $ module ;
32+ $ this ->initialize ();
3433
35- parent ::__construct ($ this );
34+ parent ::__construct ($ this ->kernel );
35+
36+ // Parent constructor defaults to not following redirects
37+ $ this ->followRedirects (true );
3638 }
3739
3840 /**
39- * Handle a request.
40- *
4141 * @param Request $request
42- * @param int $type
43- * @param bool $catch
4442 * @return Response
4543 */
46- public function handle ( Request $ request, $ type = self :: MASTER_REQUEST , $ catch = true )
44+ protected function doRequest ( $ request )
4745 {
48- // Populate the $errors object of the view. Normally this is done in the ViewServiceProvider,
49- // but the ViewServiceProvider is executed before the session data is loaded
50- // in the /Illuminate/Session/Middleware class.
51- if ($ this ->app ['session.store ' ]->has ('errors ' )) {
52- $ this ->app ['view ' ]->share ('errors ' , $ this ->app ['session.store ' ]->get ('errors ' ));
53- }
46+ $ this ->initialize ();
5447
55- return $ this ->httpKernel ->handle ($ request );
48+ return $ this ->kernel ->handle ($ request );
5649 }
5750
5851 /**
59- * Terminates a request/response cycle.
52+ * @param BrowserKitRequest $request
53+ * @return Request
54+ */
55+ protected function filterRequest (BrowserKitRequest $ request )
56+ {
57+ $ request = parent ::filterRequest ($ request );
58+
59+ return $ this ->addSessionCookiesToRequest ($ request );
60+ }
61+
62+ /**
63+ * Initialize the Laravel Framework.
6064 *
65+ * @throws ModuleConfig
66+ */
67+ private function initialize ()
68+ {
69+ // Store a reference to the database object
70+ // so the database connection can be reused during tests
71+ $ oldDb = null ;
72+ if ($ this ->app ['db ' ] && $ this ->app ['db ' ]->connection ()) {
73+ $ oldDb = $ this ->app ['db ' ];
74+ }
75+
76+ $ this ->app = $ this ->loadApplication ();
77+ $ this ->kernel = $ this ->getStackedClient ();
78+ $ this ->app ->boot ();
79+
80+ // Reset the booted flag of the Application object
81+ // so the app will be booted again if it receives a new Request
82+ $ property = new \ReflectionProperty (get_class ($ this ->app ), 'booted ' );
83+ $ property ->setAccessible (true );
84+ $ property ->setValue ($ this ->app , false );
85+
86+ if ($ oldDb ) {
87+ $ this ->app ['db ' ] = $ oldDb ;
88+ Model::setConnectionResolver ($ this ->app ['db ' ]);
89+ }
90+
91+ $ this ->module ->setApplication ($ this ->app );
92+ }
93+
94+ /**
95+ * Boot the Laravel application object.
96+ * @return Application
97+ * @throws ModuleConfig
98+ */
99+ protected function loadApplication ()
100+ {
101+
102+ $ projectDir = explode ('workbench ' , \Codeception \Configuration::projectDir ())[0 ];
103+ $ projectDir .= $ this ->module ->config ['root ' ];
104+ require $ projectDir . 'vendor ' . DIRECTORY_SEPARATOR . 'autoload.php ' ;
105+
106+ \Illuminate \Support \ClassLoader::register ();
107+
108+ if (is_dir ($ workbench = $ projectDir . 'workbench ' )) {
109+ \Illuminate \Workbench \Starter::start ($ workbench );
110+ }
111+
112+ $ startFile = $ projectDir . $ this ->module ->config ['start ' ];
113+
114+ if (! file_exists ($ startFile )) {
115+ throw new ModuleConfig (
116+ $ this , "Laravel bootstrap start.php file not found in $ startFile. \nPlease provide a valid path to it using 'start' config param. "
117+ );
118+ }
119+
120+ // The following two variables are used in the Illuminate/Foundation/start.php file
121+ // which is included in the bootstrap start file.
122+ $ unitTesting = $ this ->module ->config ['unit ' ];
123+ $ testEnvironment = $ this ->module ->config ['environment ' ];
124+
125+ $ app = require $ startFile ;
126+ $ this ->setConfiguredSessionDriver ($ app );
127+
128+ return $ app ;
129+ }
130+
131+ /**
61132 * @param Request $request
62- * @param Response $response
133+ * @return Request
134+ */
135+ private function addSessionCookiesToRequest (Request $ request )
136+ {
137+ $ session = $ this ->app ['session ' ];
138+ $ sessionIsPersistent = ! in_array ($ session ->getSessionConfig ()['driver ' ], array (null , 'array ' ));
139+
140+ if ($ sessionIsPersistent ) {
141+ $ encryptedSessionId = $ this ->app ['encrypter ' ]->encrypt ($ session ->getId ());
142+ $ request ->cookies ->add ([$ session ->getName () => $ encryptedSessionId ]);
143+ }
144+
145+ return $ request ;
146+ }
147+
148+ /**
149+ * Get the configured session driver.
150+ * Laravel 4 forces the array session driver if the application is run from the console.
151+ * This happens in \Illuminate\Session\SessionServiceProvider::setupDefaultDriver() method.
152+ * This method is used to set the correct session driver that is configured in the config files.
153+ *
154+ * @param Application $app
63155 */
64- public function terminate ( Request $ request , Response $ response )
156+ private function setConfiguredSessionDriver ( Application $ app )
65157 {
66- $ this ->httpKernel ->terminate ($ request , $ response );
158+ $ configDir = $ app ['path ' ] . DIRECTORY_SEPARATOR . 'config ' ;
159+ $ configFiles = array (
160+ $ configDir . DIRECTORY_SEPARATOR . $ this ->module ->config ['environment ' ] . DIRECTORY_SEPARATOR . 'session.php ' ,
161+ $ configDir . DIRECTORY_SEPARATOR . 'session.php ' ,
162+
163+ );
164+
165+ foreach ($ configFiles as $ configFile ) {
166+ if (file_exists ($ configFile )) {
167+ $ sessionConfig = require $ configFile ;
168+
169+ if (is_array ($ sessionConfig ) && isset ($ sessionConfig ['driver ' ])) {
170+ $ app ['config ' ]['session.driver ' ] = $ sessionConfig ['driver ' ];
171+ break ;
172+ }
173+ }
174+ }
67175 }
68176
69177 /**
@@ -72,7 +180,7 @@ public function terminate(Request $request, Response $response)
72180 * @see Illuminate\Foundation\Application::getStackedClient()
73181 * @return \Stack\StackedHttpKernel
74182 */
75- protected function getStackedClient ()
183+ private function getStackedClient ()
76184 {
77185 $ method = new \ReflectionMethod (get_class ($ this ->app ), 'getStackedClient ' );
78186 $ method ->setAccessible (true );
0 commit comments