Completed
Push — master ( d40078...2e1252 )
by Biao
04:33
created

Laravel::autoload()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 7
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 $laravelKernel
18
     */
19
    protected $laravelKernel;
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
        $this->autoload();
46
        $this->createApp();
47
        $this->createKernel();
48
        $this->setLaravel();
49
        $this->loadAllConfigurations();
50
        $this->consoleKernelBootstrap();
51
        $this->saveSnapshots();
52
    }
53
54
    protected function autoload()
55
    {
56
        $autoload = $this->conf['root_path'] . '/bootstrap/autoload.php';
57
        if (file_exists($autoload)) {
58
            require_once $autoload;
59
        } else {
60
            require_once $this->conf['root_path'] . '/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->laravelKernel = $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 consoleKernelBootstrap()
90
    {
91
        if (!$this->conf['is_lumen']) {
92
            $this->app->make(ConsoleKernel::class)->bootstrap();
93
        }
94
    }
95
96
    public function loadAllConfigurations()
97
    {
98
        if (!$this->conf['is_lumen']) {
99
            return;
100
        }
101
102
        $cfgPaths = [
103
            // Framework default configuration
104
            $this->conf['root_path'] . '/vendor/laravel/lumen-framework/config/',
105
            // App configuration
106
            $this->conf['root_path'] . '/config/',
107
        ];
108
        $keys = [];
109
        foreach ($cfgPaths as $cfgPath) {
110
            $configs = (array)glob($cfgPath . '*.php');
111
            foreach ($configs as $config) {
112
                $config = substr(basename($config), 0, -4);
113
                $keys[$config] = $config;
114
            }
115
        }
116
        foreach ($keys as $key) {
117
            $this->app->configure($key);
118
        }
119
    }
120
121
    protected function saveSnapshots()
122
    {
123
        $this->snapshots['config'] = $this->app['config']->all();
124
    }
125
126
    protected function applySnapshots()
127
    {
128
        $this->app['config']->set($this->snapshots['config']);
129
        if (isset($this->app['cookie'])) {
130
            foreach ($this->app['cookie']->getQueuedCookies() as $name => $cookie) {
131
                $this->app['cookie']->unqueue($name);
132
            }
133
        }
134
    }
135
136
    public function getRawGlobals()
137
    {
138
        return $this->rawGlobals;
139
    }
140
141
    public function handleDynamic(IlluminateRequest $request)
142
    {
143
        $this->applySnapshots();
144
145
        ob_start();
146
147
        if ($this->conf['is_lumen']) {
148
            $response = $this->app->dispatch($request);
149
            if ($response instanceof SymfonyResponse) {
150
                $content = $response->getContent();
151
            } else {
152
                $content = (string)$response;
153
            }
154
155
            $laravelReflect = new \ReflectionObject($this->app);
156
            $middleware = $laravelReflect->getProperty('middleware');
157
            $middleware->setAccessible(true);
158
            if (!empty($middleware->getValue($this->app))) {
159
                $callTerminableMiddleware = $laravelReflect->getMethod('callTerminableMiddleware');
160
                $callTerminableMiddleware->setAccessible(true);
161
                $callTerminableMiddleware->invoke($this->app, $response);
162
            }
163
        } else {
164
            $response = $this->laravelKernel->handle($request);
165
            $content = $response->getContent();
166
            $this->laravelKernel->terminate($request, $response);
167
        }
168
169
        // prefer content in response, secondly ob
170
        if (strlen($content) === 0 && ob_get_length() > 0) {
171
            $response->setContent(ob_get_contents());
172
        }
173
174
        ob_end_clean();
175
176
        return $response;
177
    }
178
179
    public function handleStatic(IlluminateRequest $request)
180
    {
181
        $uri = $request->getRequestUri();
182
        if (isset(self::$staticBlackList[$uri])) {
183
            return false;
184
        }
185
186
        $publicPath = $this->conf['static_path'];
187
        $requestFile = $publicPath . $uri;
188
        if (is_file($requestFile)) {
189
            return $this->createStaticResponse($requestFile, $request);
190
        } elseif (is_dir($requestFile)) {
191
            $indexFile = $this->lookupIndex($requestFile);
192
            if ($indexFile === false) {
193
                return false;
194
            } else {
195
                return $this->createStaticResponse($indexFile, $request);
196
            }
197
        } else {
198
            return false;
199
        }
200
    }
201
202
    protected function lookupIndex($folder)
203
    {
204
        $folder = rtrim($folder, '/') . '/';
205
        foreach (['index.html', 'index.htm'] as $index) {
206
            $tmpFile = $folder . $index;
207
            if (is_file($tmpFile)) {
208
                return $tmpFile;
209
            }
210
        }
211
        return false;
212
    }
213
214
    public function createStaticResponse($requestFile, IlluminateRequest $request)
215
    {
216
        $response = new BinaryFileResponse($requestFile);
217
        $response->prepare($request);
218
        $response->isNotModified($request);
219
        return $response;
220
    }
221
222
    public function reRegisterServiceProvider($providerCls, array $clearFacades = [], $force = false)
223
    {
224
        if (class_exists($providerCls, false) || $force) {
225
            if ($this->conf['is_lumen']) {
226
                $laravelReflect = new \ReflectionObject($this->app);
227
                $loadedProviders = $laravelReflect->getProperty('loadedProviders');
228
                $loadedProviders->setAccessible(true);
229
                $oldLoadedProviders = $loadedProviders->getValue($this->app);
230
                unset($oldLoadedProviders[get_class(new $providerCls($this->app))]);
231
                $loadedProviders->setValue($this->app, $oldLoadedProviders);
232
            }
233
            foreach ($clearFacades as $facade) {
234
                Facade::clearResolvedInstance($facade);
235
            }
236
            $this->app->register($providerCls, [], true);
237
        }
238
    }
239
240
    public function cleanRequest(IlluminateRequest $request)
241
    {
242
        // Clean laravel session
243
        if ($request->hasSession()) {
244
            $session = $request->getSession();
245
            if (method_exists($session, 'clear')) {
246
                $session->clear();
247
            } elseif (method_exists($session, 'flush')) {
248
                $session->flush();
249
            }
250
            // TODO: clear session for other versions
251
        }
252
253
        // Re-register auth
254
        //$this->reRegisterServiceProvider('\Illuminate\Auth\AuthServiceProvider', ['auth', 'auth.driver']);
255
        //$this->reRegisterServiceProvider('\Illuminate\Auth\Passwords\PasswordResetServiceProvider', ['auth.password']);
256
257
        // Re-register passport
258
        $this->reRegisterServiceProvider('\Laravel\Passport\PassportServiceProvider');
259
260
        // Re-register some singleton providers
261
        foreach ($this->conf['register_providers'] as $provider) {
262
            $this->reRegisterServiceProvider($provider);
263
        }
264
265
        // Clear request
266
        $this->app->forgetInstance('request');
267
        Facade::clearResolvedInstance('request');
268
269
        //...
270
    }
271
272
    public function fireEvent($name, array $params = [])
273
    {
274
        $params[] = $this->app;
275
        return $this->app->events->fire($name, $params);
276
    }
277
278
    public function bindRequest(IlluminateRequest $request)
279
    {
280
        $this->app->instance('request', $request);
281
    }
282
283
    public function bindSwoole($swoole)
284
    {
285
        $this->app->singleton('swoole', function () use ($swoole) {
286
            return $swoole;
287
        });
288
    }
289
290
    public function make($abstract, array $parameters = [])
291
    {
292
        return $this->app->make($abstract, $parameters);
293
    }
294
295
    public function resetSession()
296
    {
297
        if (!empty($this->app['session'])) {
298
            $reflection = new \ReflectionObject($this->app['session']);
299
            $drivers = $reflection->getProperty('drivers');
300
            $drivers->setAccessible(true);
301
            $drivers->setValue($this->app['session'], []);
302
        }
303
    }
304
305
    public function saveSession()
306
    {
307
        if (!empty($this->app['session'])) {
308
            $this->app['session']->save();
309
        }
310
    }
311
}
312