Completed
Push — master ( 0bf44a...86cb0e )
by Biao
04:20 queued 52s
created

Laravel::bootstrap()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 3
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Hhxsv5\LaravelS\Illuminate;
4
5
use Hhxsv5\LaravelS\Illuminate\Cleaners\SessionCleaner;
6
use Illuminate\Container\Container;
7
use Illuminate\Contracts\Console\Kernel as ConsoleKernel;
8
use Illuminate\Contracts\Http\Kernel as HttpKernel;
9
use Illuminate\Http\Request as IlluminateRequest;
10
use Symfony\Component\HttpFoundation\BinaryFileResponse;
11
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
12
13
class Laravel
14
{
15
    /**@var Container */
16
    protected $app;
17
18
    /**@var HttpKernel */
19
    protected $kernel;
20
21
    /**@var array */
22
    protected $snapshots = [];
23
24
    /**@var array */
25
    protected $conf = [];
26
27
    /**@var array */
28
    protected static $staticBlackList = [
29
        '/index.php'  => 1,
30
        '/.htaccess'  => 1,
31
        '/web.config' => 1,
32
    ];
33
34
    /**@var array */
35
    private $rawGlobals = [];
36
37
    public function __construct(array $conf = [])
38
    {
39
        $this->conf = $conf;
40
    }
41
42
    public function prepareLaravel()
43
    {
44
        static::autoload($this->conf['root_path']);
45
        $this->createApp();
46
        $this->createKernel();
47
        $this->setLaravel();
48
        $this->loadAllConfigurations();
49
        $this->bootstrap();
50
        $this->saveSnapshots();
51
    }
52
53
    public static function autoload($rootPath)
54
    {
55
        $autoload = $rootPath . '/bootstrap/autoload.php';
56
        if (file_exists($autoload)) {
57
            require_once $autoload;
58
        } else {
59
            require_once $rootPath . '/vendor/autoload.php';
60
        }
61
    }
62
63
    protected function createApp()
64
    {
65
        $this->app = require $this->conf['root_path'] . '/bootstrap/app.php';
66
    }
67
68
    protected function createKernel()
69
    {
70
        if (!$this->conf['is_lumen']) {
71
            $this->kernel = $this->app->make(HttpKernel::class);
72
        }
73
    }
74
75
    protected function setLaravel()
76
    {
77
        // Load configuration laravel.php manually for Lumen
78
        if ($this->conf['is_lumen'] && file_exists($this->conf['root_path'] . '/config/laravels.php')) {
79
            $this->app->configure('laravels');
0 ignored issues
show
Bug introduced by
The method configure() does not exist on Illuminate\Container\Container. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

79
            $this->app->/** @scrutinizer ignore-call */ 
80
                        configure('laravels');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
80
        }
81
82
        $server = isset($this->conf['_SERVER']) ? $this->conf['_SERVER'] : [];
83
        $env = isset($this->conf['_ENV']) ? $this->conf['_ENV'] : [];
84
        $this->rawGlobals['_SERVER'] = array_merge($_SERVER, $server);
85
        $this->rawGlobals['_ENV'] = array_merge($_ENV, $env);
86
    }
87
88
    protected function bootstrap()
89
    {
90
        if ($this->conf['is_lumen']) {
91
            if (method_exists($this->app, 'boot')) {
92
                $this->app->boot();
93
            }
94
        } else {
95
            $this->app->make(ConsoleKernel::class)->bootstrap();
96
        }
97
    }
98
99
    public function loadAllConfigurations()
100
    {
101
        if (!$this->conf['is_lumen']) {
102
            return;
103
        }
104
105
        $cfgPaths = [
106
            // Framework default configuration
107
            $this->conf['root_path'] . '/vendor/laravel/lumen-framework/config/',
108
            // App configuration
109
            $this->conf['root_path'] . '/config/',
110
        ];
111
        $keys = [];
112
        foreach ($cfgPaths as $cfgPath) {
113
            $configs = (array)glob($cfgPath . '*.php');
114
            foreach ($configs as $config) {
115
                $config = substr(basename($config), 0, -4);
116
                $keys[$config] = $config;
117
            }
118
        }
119
        foreach ($keys as $key) {
120
            $this->app->configure($key);
121
        }
122
    }
123
124
    protected function saveSnapshots()
125
    {
126
        $this->snapshots['config'] = $this->app['config']->all();
127
    }
128
129
    protected function applySnapshots()
130
    {
131
        $this->app['config']->set($this->snapshots['config']);
132
        if (isset($this->app['cookie'])) {
133
            foreach ($this->app['cookie']->getQueuedCookies() as $name => $cookie) {
134
                $this->app['cookie']->unqueue($name);
135
            }
136
        }
137
    }
138
139
    public function getRawGlobals()
140
    {
141
        return $this->rawGlobals;
142
    }
143
144
    public function handleDynamic(IlluminateRequest $request)
145
    {
146
        $this->applySnapshots();
147
148
        ob_start();
149
150
        if ($this->conf['is_lumen']) {
151
            $response = $this->app->dispatch($request);
0 ignored issues
show
Bug introduced by
The method dispatch() does not exist on Illuminate\Container\Container. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

151
            /** @scrutinizer ignore-call */ 
152
            $response = $this->app->dispatch($request);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
152
            if ($response instanceof SymfonyResponse) {
153
                $content = $response->getContent();
154
            } else {
155
                $content = (string)$response;
156
            }
157
158
            $laravelReflect = new \ReflectionObject($this->app);
159
            $middleware = $laravelReflect->getProperty('middleware');
160
            $middleware->setAccessible(true);
161
            if (!empty($middleware->getValue($this->app))) {
162
                $callTerminableMiddleware = $laravelReflect->getMethod('callTerminableMiddleware');
163
                $callTerminableMiddleware->setAccessible(true);
164
                $callTerminableMiddleware->invoke($this->app, $response);
165
            }
166
        } else {
167
            $response = $this->kernel->handle($request);
168
            $content = $response->getContent();
169
            $this->kernel->terminate($request, $response);
170
        }
171
172
        // prefer content in response, secondly ob
173
        if (strlen($content) === 0 && ob_get_length() > 0) {
174
            $response->setContent(ob_get_contents());
175
        }
176
177
        ob_end_clean();
178
179
        return $response;
180
    }
181
182
    public function handleStatic(IlluminateRequest $request)
183
    {
184
        $uri = $request->getRequestUri();
185
        if (isset(self::$staticBlackList[$uri])) {
186
            return false;
187
        }
188
189
        $publicPath = $this->conf['static_path'];
190
        $requestFile = $publicPath . $uri;
191
        if (is_file($requestFile)) {
192
            return $this->createStaticResponse($requestFile, $request);
193
        } elseif (is_dir($requestFile)) {
194
            $indexFile = $this->lookupIndex($requestFile);
195
            if ($indexFile === false) {
196
                return false;
197
            } else {
198
                return $this->createStaticResponse($indexFile, $request);
199
            }
200
        } else {
201
            return false;
202
        }
203
    }
204
205
    protected function lookupIndex($folder)
206
    {
207
        $folder = rtrim($folder, '/') . '/';
208
        foreach (['index.html', 'index.htm'] as $index) {
209
            $tmpFile = $folder . $index;
210
            if (is_file($tmpFile)) {
211
                return $tmpFile;
212
            }
213
        }
214
        return false;
215
    }
216
217
    public function createStaticResponse($requestFile, IlluminateRequest $request)
218
    {
219
        $response = new BinaryFileResponse($requestFile);
220
        $response->prepare($request);
221
        $response->isNotModified($request);
222
        return $response;
223
    }
224
225
    protected function cleanProviders(array $providers, $force = false)
226
    {
227
        if ($this->conf['is_lumen']) {
228
            $laravelReflect = new \ReflectionObject($this->app);
229
            $loadedProviders = $laravelReflect->getProperty('loadedProviders');
230
            $loadedProviders->setAccessible(true);
231
            $oldLoadedProviders = $loadedProviders->getValue($this->app);
232
        }
233
234
        foreach ($providers as $provider) {
235
            if ($force || class_exists($provider, false)) {
236
                if ($this->conf['is_lumen']) {
237
                    unset($oldLoadedProviders[get_class(new $provider($this->app))]);
238
                }
239
                $this->app->register($provider, [], true);
0 ignored issues
show
introduced by
The method register() does not exist on Illuminate\Container\Container. Are you sure you never get this type here, but always one of the subclasses? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

239
                $this->app->/** @scrutinizer ignore-call */ 
240
                            register($provider, [], true);
Loading history...
240
            }
241
        }
242
243
        if ($this->conf['is_lumen']) {
244
            $loadedProviders->setValue($this->app, $oldLoadedProviders);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $loadedProviders does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $oldLoadedProviders does not seem to be defined for all execution paths leading up to this point.
Loading history...
245
        }
246
    }
247
248
    public function clean()
249
    {
250
        foreach ($this->conf['cleaners'] as $cleanerCls) {
251
            /**@var \Hhxsv5\LaravelS\Illuminate\Cleaners\CleanerInterface $cleaner */
252
            $cleaner = $this->app->make($cleanerCls);
253
            $cleaner->clean($this->app);
254
        }
255
        $this->cleanProviders($this->conf['register_providers']);
256
    }
257
258
    public function fireEvent($name, array $params = [])
259
    {
260
        $params[] = $this->app;
261
        return method_exists('dispatch', $this->app['events']) ?
0 ignored issues
show
Bug introduced by
$this->app['events'] of type Illuminate\Events\Dispatcher is incompatible with the type string expected by parameter $method_name of method_exists(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

261
        return method_exists('dispatch', /** @scrutinizer ignore-type */ $this->app['events']) ?
Loading history...
262
            $this->app['events']->dispatch($name, $params) : $this->app['events']->fire($name, $params);
0 ignored issues
show
Bug introduced by
The method dispatch() does not exist on Illuminate\Events\Dispatcher. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

262
            $this->app['events']->/** @scrutinizer ignore-call */ 
263
                                  dispatch($name, $params) : $this->app['events']->fire($name, $params);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
263
    }
264
265
    public function bindRequest(IlluminateRequest $request)
266
    {
267
        $this->app->instance('request', $request);
268
    }
269
270
    public function bindSwoole($swoole)
271
    {
272
        $this->app->singleton('swoole', function () use ($swoole) {
273
            return $swoole;
274
        });
275
    }
276
277
    public function make($abstract, array $parameters = [])
278
    {
279
        return $this->app->make($abstract, $parameters);
280
    }
281
282
    public function cleanSession()
283
    {
284
        /**@var \Hhxsv5\LaravelS\Illuminate\Cleaners\CleanerInterface $cleaner */
285
        $cleaner = $this->app->make(SessionCleaner::class);
286
        $cleaner->clean($this->app);
287
    }
288
289
    public function saveSession()
290
    {
291
        if ($this->app->offsetExists('session')) {
292
            $this->app['session']->save();
293
        }
294
    }
295
}
296