Passed
Push — master ( 7a52f3...2a21c4 )
by Biao
04:15
created

Laravel::createStaticResponse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Hhxsv5\LaravelS\Illuminate;
4
5
use Illuminate\Support\Facades\Facade;
6
use Illuminate\Http\Request as IlluminateRequest;
7
use Illuminate\Contracts\Http\Kernel as HttpKernel;
8
use Illuminate\Contracts\Console\Kernel as ConsoleKernel;
9
use Symfony\Component\HttpFoundation\BinaryFileResponse;
10
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
11
12
class Laravel
13
{
14
    protected $app;
15
16
    /**
17
     * @var HttpKernel $kernel
18
     */
19
    protected $kernel;
20
21
    protected static $snapshotKeys = ['config', 'cookie', 'auth', /*'auth.password'*/];
22
23
    /**
24
     * @var array $snapshots
25
     */
26
    protected $snapshots = [];
27
28
    protected $conf = [];
29
30
    protected static $staticBlackList = [
31
        '/index.php'  => 1,
32
        '/.htaccess'  => 1,
33
        '/web.config' => 1,
34
    ];
35
36
    private $rawGlobals = [];
37
38
    public function __construct(array $conf = [])
39
    {
40
        $this->conf = $conf;
41
    }
42
43
    public function prepareLaravel()
44
    {
45
        static::autoload($this->conf['root_path']);
46
        $this->createApp();
47
        $this->createKernel();
48
        $this->setLaravel();
49
        $this->loadAllConfigurations();
50
        $this->bootstrap();
51
        $this->saveSnapshots();
52
    }
53
54
    public static function autoload($rootPath)
55
    {
56
        $autoload = $rootPath . '/bootstrap/autoload.php';
57
        if (file_exists($autoload)) {
58
            require_once $autoload;
59
        } else {
60
            require_once $rootPath . '/vendor/autoload.php';
61
        }
62
    }
63
64
    protected function createApp()
65
    {
66
        $this->app = require $this->conf['root_path'] . '/bootstrap/app.php';
67
    }
68
69
    protected function createKernel()
70
    {
71
        if (!$this->conf['is_lumen']) {
72
            $this->kernel = $this->app->make(HttpKernel::class);
73
        }
74
    }
75
76
    protected function setLaravel()
77
    {
78
        // Load configuration laravel.php manually for Lumen
79
        if ($this->conf['is_lumen'] && file_exists($this->conf['root_path'] . '/config/laravels.php')) {
80
            $this->app->configure('laravels');
81
        }
82
83
        $server = isset($this->conf['_SERVER']) ? $this->conf['_SERVER'] : [];
84
        $env = isset($this->conf['_ENV']) ? $this->conf['_ENV'] : [];
85
        $this->rawGlobals['_SERVER'] = array_merge($_SERVER, $server);
86
        $this->rawGlobals['_ENV'] = array_merge($_ENV, $env);
87
    }
88
89
    protected function bootstrap()
90
    {
91
        if ($this->conf['is_lumen']) {
92
            if (method_exists($this->app, 'boot')) {
93
                $this->app->boot();
94
            }
95
        } else {
96
            $this->app->make(ConsoleKernel::class)->bootstrap();
97
        }
98
    }
99
100
    public function loadAllConfigurations()
101
    {
102
        if (!$this->conf['is_lumen']) {
103
            return;
104
        }
105
106
        $cfgPaths = [
107
            // Framework default configuration
108
            $this->conf['root_path'] . '/vendor/laravel/lumen-framework/config/',
109
            // App configuration
110
            $this->conf['root_path'] . '/config/',
111
        ];
112
        $keys = [];
113
        foreach ($cfgPaths as $cfgPath) {
114
            $configs = (array)glob($cfgPath . '*.php');
115
            foreach ($configs as $config) {
116
                $config = substr(basename($config), 0, -4);
117
                $keys[$config] = $config;
118
            }
119
        }
120
        foreach ($keys as $key) {
121
            $this->app->configure($key);
122
        }
123
    }
124
125
    protected function saveSnapshots()
126
    {
127
        $this->snapshots['config'] = $this->app['config']->all();
128
    }
129
130
    protected function applySnapshots()
131
    {
132
        $this->app['config']->set($this->snapshots['config']);
133
        if (isset($this->app['cookie'])) {
134
            foreach ($this->app['cookie']->getQueuedCookies() as $name => $cookie) {
135
                $this->app['cookie']->unqueue($name);
136
            }
137
        }
138
    }
139
140
    public function getRawGlobals()
141
    {
142
        return $this->rawGlobals;
143
    }
144
145
    public function handleDynamic(IlluminateRequest $request)
146
    {
147
        $this->applySnapshots();
148
149
        ob_start();
150
151
        if ($this->conf['is_lumen']) {
152
            $response = $this->app->dispatch($request);
153
            if ($response instanceof SymfonyResponse) {
154
                $content = $response->getContent();
155
            } else {
156
                $content = (string)$response;
157
            }
158
159
            $laravelReflect = new \ReflectionObject($this->app);
160
            $middleware = $laravelReflect->getProperty('middleware');
161
            $middleware->setAccessible(true);
162
            if (!empty($middleware->getValue($this->app))) {
163
                $callTerminableMiddleware = $laravelReflect->getMethod('callTerminableMiddleware');
164
                $callTerminableMiddleware->setAccessible(true);
165
                $callTerminableMiddleware->invoke($this->app, $response);
166
            }
167
        } else {
168
            $response = $this->kernel->handle($request);
169
            $content = $response->getContent();
170
            $this->kernel->terminate($request, $response);
171
        }
172
173
        // prefer content in response, secondly ob
174
        if (strlen($content) === 0 && ob_get_length() > 0) {
175
            $response->setContent(ob_get_contents());
176
        }
177
178
        ob_end_clean();
179
180
        return $response;
181
    }
182
183
    public function handleStatic(IlluminateRequest $request)
184
    {
185
        $uri = $request->getRequestUri();
186
        if (isset(self::$staticBlackList[$uri])) {
187
            return false;
188
        }
189
190
        $publicPath = $this->conf['static_path'];
191
        $requestFile = $publicPath . $uri;
192
        if (is_file($requestFile)) {
193
            return $this->createStaticResponse($requestFile, $request);
194
        } elseif (is_dir($requestFile)) {
195
            $indexFile = $this->lookupIndex($requestFile);
196
            if ($indexFile === false) {
197
                return false;
198
            } else {
199
                return $this->createStaticResponse($indexFile, $request);
200
            }
201
        } else {
202
            return false;
203
        }
204
    }
205
206
    protected function lookupIndex($folder)
207
    {
208
        $folder = rtrim($folder, '/') . '/';
209
        foreach (['index.html', 'index.htm'] as $index) {
210
            $tmpFile = $folder . $index;
211
            if (is_file($tmpFile)) {
212
                return $tmpFile;
213
            }
214
        }
215
        return false;
216
    }
217
218
    public function createStaticResponse($requestFile, IlluminateRequest $request)
219
    {
220
        $response = new BinaryFileResponse($requestFile);
221
        $response->prepare($request);
222
        $response->isNotModified($request);
223
        return $response;
224
    }
225
226
    public function reRegisterServiceProvider($providerCls, array $clearFacades = [], $force = false)
227
    {
228
        if (class_exists($providerCls, false) || $force) {
229
            if ($this->conf['is_lumen']) {
230
                $laravelReflect = new \ReflectionObject($this->app);
231
                $loadedProviders = $laravelReflect->getProperty('loadedProviders');
232
                $loadedProviders->setAccessible(true);
233
                $oldLoadedProviders = $loadedProviders->getValue($this->app);
234
                unset($oldLoadedProviders[get_class(new $providerCls($this->app))]);
235
                $loadedProviders->setValue($this->app, $oldLoadedProviders);
236
            }
237
            foreach ($clearFacades as $facade) {
238
                Facade::clearResolvedInstance($facade);
239
            }
240
            $this->app->register($providerCls, [], true);
241
        }
242
    }
243
244
    public function cleanRequest(IlluminateRequest $request)
245
    {
246
        // Clean laravel session
247
        if ($request->hasSession()) {
248
            $session = $request->getSession();
249
            if (method_exists($session, 'clear')) {
250
                $session->clear();
251
            } elseif (method_exists($session, 'flush')) {
252
                $session->flush();
253
            }
254
            // TODO: clear session for other versions
255
        }
256
257
        // Re-register auth
258
        //$this->reRegisterServiceProvider('\Illuminate\Auth\AuthServiceProvider', ['auth', 'auth.driver']);
259
        //$this->reRegisterServiceProvider('\Illuminate\Auth\Passwords\PasswordResetServiceProvider', ['auth.password']);
260
261
        // Re-register passport
262
        $this->reRegisterServiceProvider('\Laravel\Passport\PassportServiceProvider');
263
264
        // Re-register some singleton providers
265
        foreach ($this->conf['register_providers'] as $provider) {
266
            $this->reRegisterServiceProvider($provider);
267
        }
268
269
        // Clear request
270
        $this->app->forgetInstance('request');
271
        Facade::clearResolvedInstance('request');
272
273
        //...
274
    }
275
276
    public function fireEvent($name, array $params = [])
277
    {
278
        $params[] = $this->app;
279
        return $this->app->events->fire($name, $params);
280
    }
281
282
    public function bindRequest(IlluminateRequest $request)
283
    {
284
        $this->app->instance('request', $request);
285
    }
286
287
    public function bindSwoole($swoole)
288
    {
289
        $this->app->singleton('swoole', function () use ($swoole) {
290
            return $swoole;
291
        });
292
    }
293
294
    public function make($abstract, array $parameters = [])
295
    {
296
        return $this->app->make($abstract, $parameters);
297
    }
298
299
    public function resetSession()
300
    {
301
        if (!empty($this->app['session'])) {
302
            $reflection = new \ReflectionObject($this->app['session']);
303
            $drivers = $reflection->getProperty('drivers');
304
            $drivers->setAccessible(true);
305
            $drivers->setValue($this->app['session'], []);
306
        }
307
    }
308
309
    public function saveSession()
310
    {
311
        if (!empty($this->app['session'])) {
312
            $this->app['session']->save();
313
        }
314
    }
315
}
316