Completed
Push — master ( 01c9a5...19083c )
by Biao
04:36
created

Laravel::__clone()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
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 = [];
124
        foreach (self::$snapshotKeys as $key) {
125
            if (isset($this->app[$key])) {
126
                if (is_object($this->app[$key])) {
127
                    $this->snapshots[$key] = clone $this->app[$key];
128
                } else {
129
                    $this->snapshots[$key] = $this->app[$key];
130
                }
131
            }
132
        }
133
    }
134
135
    protected function applySnapshots()
136
    {
137
        foreach ($this->snapshots as $key => $value) {
138
            if (is_object($value)) {
139
                $this->app[$key] = clone $value;
140
            } else {
141
                $this->app[$key] = $value;
142
            }
143
            Facade::clearResolvedInstance($key);
144
        }
145
    }
146
147
    public function getRawGlobals()
148
    {
149
        return $this->rawGlobals;
150
    }
151
152
    public function handleDynamic(IlluminateRequest $request)
153
    {
154
        $this->applySnapshots();
155
156
        ob_start();
157
158
        if ($this->conf['is_lumen']) {
159
            $response = $this->app->dispatch($request);
160
            if ($response instanceof SymfonyResponse) {
161
                $content = $response->getContent();
162
            } else {
163
                $content = (string)$response;
164
            }
165
166
            $laravelReflect = new \ReflectionObject($this->app);
167
            $middleware = $laravelReflect->getProperty('middleware');
168
            $middleware->setAccessible(true);
169
            if (!empty($middleware->getValue($this->app))) {
170
                $callTerminableMiddleware = $laravelReflect->getMethod('callTerminableMiddleware');
171
                $callTerminableMiddleware->setAccessible(true);
172
                $callTerminableMiddleware->invoke($this->app, $response);
173
            }
174
        } else {
175
            $response = $this->laravelKernel->handle($request);
176
            $content = $response->getContent();
177
            $this->laravelKernel->terminate($request, $response);
178
        }
179
180
        // prefer content in response, secondly ob
181
        if (strlen($content) === 0 && ob_get_length() > 0) {
182
            $response->setContent(ob_get_contents());
183
        }
184
185
        ob_end_clean();
186
187
        return $response;
188
    }
189
190
    public function handleStatic(IlluminateRequest $request)
191
    {
192
        $uri = $request->getRequestUri();
193
        if (isset(self::$staticBlackList[$uri])) {
194
            return false;
195
        }
196
197
        $publicPath = $this->conf['static_path'];
198
        $requestFile = $publicPath . $uri;
199
        if (is_file($requestFile)) {
200
            return $this->createStaticResponse($requestFile, $request);
201
        } elseif (is_dir($requestFile)) {
202
            $indexFile = $this->lookupIndex($requestFile);
203
            if ($indexFile === false) {
204
                return false;
205
            } else {
206
                return $this->createStaticResponse($indexFile, $request);
207
            }
208
        } else {
209
            return false;
210
        }
211
    }
212
213
    protected function lookupIndex($folder)
214
    {
215
        $folder = rtrim($folder, '/') . '/';
216
        foreach (['index.html', 'index.htm'] as $index) {
217
            $tmpFile = $folder . $index;
218
            if (is_file($tmpFile)) {
219
                return $tmpFile;
220
            }
221
        }
222
        return false;
223
    }
224
225
    public function createStaticResponse($requestFile, IlluminateRequest $request)
226
    {
227
        $response = new BinaryFileResponse($requestFile);
228
        $response->prepare($request);
229
        $response->isNotModified($request);
230
        return $response;
231
    }
232
233
    public function reRegisterServiceProvider($providerCls, array $clearFacades = [], $force = false)
234
    {
235
        if (class_exists($providerCls, false) || $force) {
236
            if ($this->conf['is_lumen']) {
237
                $laravelReflect = new \ReflectionObject($this->app);
238
                $loadedProviders = $laravelReflect->getProperty('loadedProviders');
239
                $loadedProviders->setAccessible(true);
240
                $oldLoadedProviders = $loadedProviders->getValue($this->app);
241
                unset($oldLoadedProviders[get_class(new $providerCls($this->app))]);
242
                $loadedProviders->setValue($this->app, $oldLoadedProviders);
243
            }
244
            foreach ($clearFacades as $facade) {
245
                Facade::clearResolvedInstance($facade);
246
            }
247
            $this->app->register($providerCls, [], true);
248
        }
249
    }
250
251
    public function cleanRequest(IlluminateRequest $request)
252
    {
253
        // Clean laravel session
254
        if ($request->hasSession()) {
255
            $session = $request->getSession();
256
            if (method_exists($session, 'clear')) {
257
                $session->clear();
258
            } elseif (method_exists($session, 'flush')) {
259
                $session->flush();
260
            }
261
            // TODO: clear session for other versions
262
        }
263
264
        // Re-register auth
265
        //$this->reRegisterServiceProvider('\Illuminate\Auth\AuthServiceProvider', ['auth', 'auth.driver']);
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
266
        //$this->reRegisterServiceProvider('\Illuminate\Auth\Passwords\PasswordResetServiceProvider', ['auth.password']);
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
267
268
        // Re-register passport
269
        $this->reRegisterServiceProvider('\Laravel\Passport\PassportServiceProvider');
270
271
        // Re-register some singleton providers
272
        foreach ($this->conf['register_providers'] as $provider) {
273
            $this->reRegisterServiceProvider($provider);
274
        }
275
276
        // Clear request
277
        $this->app->forgetInstance('request');
278
        Facade::clearResolvedInstance('request');
279
280
        //...
281
    }
282
283
    public function fireEvent($name, array $params = [])
284
    {
285
        $params[] = $this->app;
286
        return $this->app->events->fire($name, $params);
287
    }
288
289
    public function bindRequest(IlluminateRequest $request)
290
    {
291
        $this->app->instance('request', $request);
292
    }
293
294
    public function bindSwoole($swoole)
295
    {
296
        $this->app->singleton('swoole', function () use ($swoole) {
297
            return $swoole;
298
        });
299
    }
300
301
    public function make($abstract, array $parameters = [])
302
    {
303
        return $this->app->make($abstract, $parameters);
304
    }
305
306
    public function resetSession()
307
    {
308
        if (!empty($this->app['session'])) {
309
            $reflection = new \ReflectionObject($this->app['session']);
310
            $drivers = $reflection->getProperty('drivers');
311
            $drivers->setAccessible(true);
312
            $drivers->setValue($this->app['session'], []);
313
        }
314
    }
315
316
    public function saveSession()
317
    {
318
        if (!empty($this->app['session'])) {
319
            $this->app['session']->save();
320
        }
321
    }
322
323
    public function __clone()
324
    {
325
        $this->app = clone $this->app;
326
        $this->laravelKernel = clone $this->laravelKernel;
327
    }
328
}
329