Passed
Pull Request — master (#239)
by
unknown
09:19
created

LaravelSCommand::loadConfig()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 3
nc 2
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Hhxsv5\LaravelS\Illuminate;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Support\Arr;
7
8
class LaravelSCommand extends Command
9
{
10
    protected $signature = 'laravels {action? : publish|config|info}
11
    {--d|daemonize : Whether run as a daemon for "start & restart"}
12
    {--i|ignore : Whether ignore checking process pid for "start & restart"}';
13
14
    protected $description = 'LaravelS console tool';
15
16
    public function fire()
17
    {
18
        $this->handle();
19
    }
20
21
    public function handle()
22
    {
23
        $action = (string)$this->argument('action');
24
        switch ($action) {
25
            case 'publish':
26
                $this->publish();
27
                break;
28
            case 'config':
29
                $this->prepareConfig();
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
30
            case 'info':
31
                $this->showInfo();
32
                break;
33
            default:
34
                $this->info(sprintf('Usage: [%s] ./artisan laravels publish|config|info', PHP_BINARY));
35
                if (in_array($action, ['start', 'stop', 'restart', 'reload'], true)) {
36
                    $this->error(sprintf(
37
                        'The "%s" command has been migrated to "bin/laravels", %ssee https://github.com/hhxsv5/laravel-s#run',
38
                        $action,
39
                        file_exists(base_path('bin/laravels')) ? '' : 'please run `php artisan laravels publish` first, '
40
                    ));
41
                }
42
                break;
43
        }
44
    }
45
46
    protected function isLumen()
47
    {
48
        return stripos($this->getApplication()->getVersion(), 'Lumen') !== false;
49
    }
50
51
    protected function loadConfig()
52
    {
53
        // Load configuration laravel.php manually for Lumen
54
        $basePath = config('laravels.laravel_base_path') ?: base_path();
55
        if ($this->isLumen() && file_exists($basePath . '/config/laravels.php')) {
56
            $this->getLaravel()->configure('laravels');
0 ignored issues
show
Bug introduced by
The method configure() does not exist on Illuminate\Contracts\Foundation\Application. ( Ignorable by Annotation )

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

56
            $this->getLaravel()->/** @scrutinizer ignore-call */ 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...
57
        }
58
    }
59
60
    protected function showInfo()
61
    {
62
        $this->showLogo();
63
        $this->showComponents();
64
        $this->showProtocols();
65
        $this->comment('>>> Feedback: <options=underscore>https://github.com/hhxsv5/laravel-s</>');
66
    }
67
68
    protected function showLogo()
69
    {
70
        static $logo = <<<EOS
71
 _                               _  _____ 
72
| |                             | |/ ____|
73
| |     __ _ _ __ __ ___   _____| | (___  
74
| |    / _` | '__/ _` \ \ / / _ \ |\___ \ 
75
| |___| (_| | | | (_| |\ V /  __/ |____) |
76
|______\__,_|_|  \__,_| \_/ \___|_|_____/ 
77
                                           
78
EOS;
79
        $this->info($logo);
80
        $this->info('Speed up your Laravel/Lumen');
81
    }
82
83
    protected function showComponents()
84
    {
85
        $this->comment('>>> Components');
86
        $laravelSVersion = '-';
87
        $cfg = (array)json_decode(file_get_contents(base_path('composer.lock')), true);
88
        if (isset($cfg['packages'])) {
89
            $packages = array_merge($cfg['packages'], Arr::get($cfg, 'packages-dev', []));
90
            foreach ($packages as $package) {
91
                if (isset($package['name']) && $package['name'] === 'hhxsv5/laravel-s') {
92
                    $laravelSVersion = ltrim($package['version'], 'vV');
93
                    break;
94
                }
95
            }
96
        }
97
        $this->table(['Component', 'Version'], [
98
            [
99
                'PHP',
100
                phpversion(),
101
            ],
102
            [
103
                'Swoole',
104
                swoole_version(),
105
            ],
106
            [
107
                'LaravelS',
108
                $laravelSVersion,
109
            ],
110
            [
111
                $this->getApplication()->getName() . ' [<info>' . env('APP_ENV', config('app.env')) . '</info>]',
112
                $this->getApplication()->getVersion(),
113
            ],
114
        ]);
115
    }
116
117
    protected function showProtocols()
118
    {
119
        $this->comment('>>> Protocols');
120
121
        $config = (array)json_decode(file_get_contents(base_path('storage/laravels.json')), true);
122
        $socketType = isset($config['server']['socket_type']) ? $config['server']['socket_type'] : SWOOLE_SOCK_TCP;
123
        if (in_array($socketType, [SWOOLE_SOCK_UNIX_DGRAM, SWOOLE_SOCK_UNIX_STREAM])) {
124
            $listenAt = $config['server']['listen_ip'];
125
        } else {
126
            $listenAt = sprintf('%s:%s', $config['server']['listen_ip'], $config['server']['listen_port']);
127
        }
128
129
        $tableRows = [
130
            [
131
                'Main HTTP',
132
                '<info>On</info>',
133
                $this->getApplication()->getName(),
134
                $listenAt,
135
            ],
136
        ];
137
        if (!empty($config['server']['websocket']['enable'])) {
138
            $tableRows [] = [
139
                'Main WebSocket',
140
                '<info>On</info>',
141
                $config['server']['websocket']['handler'],
142
                $listenAt,
143
            ];
144
        }
145
146
        $socketTypeNames = [
147
            SWOOLE_SOCK_TCP         => 'TCP IPV4 Socket',
148
            SWOOLE_SOCK_TCP6        => 'TCP IPV6 Socket',
149
            SWOOLE_SOCK_UDP         => 'UDP IPV4 Socket',
150
            SWOOLE_SOCK_UDP6        => 'TCP IPV6 Socket',
151
            SWOOLE_SOCK_UNIX_DGRAM  => 'Unix Socket Dgram',
152
            SWOOLE_SOCK_UNIX_STREAM => 'Unix Socket Stream',
153
        ];
154
        $sockets = isset($config['server']['sockets']) ? $config['server']['sockets'] : [];
155
        foreach ($sockets as $key => $socket) {
156
            if (isset($socket['enable']) && !$socket['enable']) {
157
                continue;
158
            }
159
160
            $name = 'Port#' . $key . ' ';
161
            $name .= isset($socketTypeNames[$socket['type']]) ? $socketTypeNames[$socket['type']] : 'Unknown socket';
162
            $tableRows [] = [
163
                $name,
164
                '<info>On</info>',
165
                $socket['handler'],
166
                sprintf('%s:%s', $socket['host'], $socket['port']),
167
            ];
168
        }
169
        $this->table(['Protocol', 'Status', 'Handler', 'Listen At'], $tableRows);
170
    }
171
172
    protected function prepareConfig()
173
    {
174
        $this->loadConfig();
175
176
        $svrConf = config('laravels');
177
178
        $this->preSet($svrConf);
179
180
        $ret = $this->preCheck($svrConf);
181
        if ($ret !== 0) {
182
            return $ret;
183
        }
184
185
        $laravelConf = [
186
            'root_path'           => $svrConf['laravel_base_path'],
187
            'static_path'         => $svrConf['swoole']['document_root'],
188
            'cleaners'            => array_unique((array)Arr::get($svrConf, 'cleaners', [])),
189
            'register_providers'  => array_unique((array)Arr::get($svrConf, 'register_providers', [])),
190
            'destroy_controllers' => Arr::get($svrConf, 'destroy_controllers', []),
191
            'is_lumen'            => $this->isLumen(),
192
            '_SERVER'             => $_SERVER,
193
            '_ENV'                => $_ENV,
194
        ];
195
196
        $config = ['server' => $svrConf, 'laravel' => $laravelConf];
197
        $jsonConfig = json_encode($config, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
198
        return file_put_contents(base_path('storage/laravels.json'), $jsonConfig) > 0 ? 0 : 1;
199
    }
200
201
    protected function preSet(array &$svrConf)
202
    {
203
        if (!isset($svrConf['enable_gzip'])) {
204
            $svrConf['enable_gzip'] = false;
205
        }
206
        if (empty($svrConf['laravel_base_path'])) {
207
            $svrConf['laravel_base_path'] = base_path();
208
        }
209
        if (empty($svrConf['process_prefix'])) {
210
            $svrConf['process_prefix'] = $svrConf['laravel_base_path'];
211
        }
212
        if ($this->option('ignore')) {
213
            $svrConf['ignore_check_pid'] = true;
214
        } elseif (!isset($svrConf['ignore_check_pid'])) {
215
            $svrConf['ignore_check_pid'] = false;
216
        }
217
        if (empty($svrConf['swoole']['document_root'])) {
218
            $svrConf['swoole']['document_root'] = $svrConf['laravel_base_path'] . '/public';
219
        }
220
        if ($this->option('daemonize')) {
221
            $svrConf['swoole']['daemonize'] = true;
222
        } elseif (!isset($svrConf['swoole']['daemonize'])) {
223
            $svrConf['swoole']['daemonize'] = false;
224
        }
225
        if (empty($svrConf['swoole']['pid_file'])) {
226
            $svrConf['swoole']['pid_file'] = storage_path('laravels.pid');
227
        }
228
        if (empty($svrConf['timer']['max_wait_time'])) {
229
            $svrConf['timer']['max_wait_time'] = 5;
230
        }
231
        return 0;
232
    }
233
234
    protected function preCheck(array $svrConf)
235
    {
236
        if (!empty($svrConf['enable_gzip']) && version_compare(swoole_version(), '4.1.0', '>=')) {
237
            $this->error('enable_gzip is DEPRECATED since Swoole 4.1.0, set http_compression of Swoole instead, http_compression is disabled by default.');
238
            $this->info('If there is a proxy server like Nginx, suggest that enable gzip in Nginx and disable gzip in Swoole, to avoid the repeated gzip compression for response.');
239
            return 1;
240
        }
241
        if (!empty($svrConf['events'])) {
242
            if (empty($svrConf['swoole']['task_worker_num']) || $svrConf['swoole']['task_worker_num'] <= 0) {
243
                $this->error('Asynchronous event listening needs to set task_worker_num > 0');
244
                return 1;
245
            }
246
        }
247
        return 0;
248
    }
249
250
251
    public function publish()
252
    {
253
        $basePath = config('laravels.laravel_base_path') ?: base_path();
254
        $configPath = $basePath . '/config/laravels.php';
255
        $todoList = [
256
            [
257
                'from' => realpath(__DIR__ . '/../../config/laravels.php'),
258
                'to'   => $configPath,
259
                'mode' => 0644,
260
            ],
261
            [
262
                'from' => realpath(__DIR__ . '/../../bin/laravels'),
263
                'to'   => $basePath . '/bin/laravels',
264
                'mode' => 0755,
265
                'link' => true,
266
            ],
267
            [
268
                'from' => realpath(__DIR__ . '/../../bin/fswatch'),
269
                'to'   => $basePath . '/bin/fswatch',
270
                'mode' => 0755,
271
                'link' => true,
272
            ],
273
            [
274
                'from' => realpath(__DIR__ . '/../../bin/inotify'),
275
                'to'   => $basePath . '/bin/inotify',
276
                'mode' => 0755,
277
                'link' => true,
278
            ],
279
        ];
280
        if (file_exists($configPath)) {
281
            $choice = $this->anticipate($configPath . ' already exists, do you want to override it ? Y/N',
282
                ['Y', 'N'],
283
                'N'
284
            );
285
            if (!$choice || strtoupper($choice) !== 'Y') {
286
                array_shift($todoList);
287
            }
288
        }
289
290
        foreach ($todoList as $todo) {
291
            $toDir = dirname($todo['to']);
292
            if (!is_dir($toDir)) {
293
                mkdir($toDir, 0755, true);
294
            }
295
            if (file_exists($todo['to'])) {
296
                unlink($todo['to']);
297
            }
298
            $operation = 'Copied';
299
            if (empty($todo['link'])) {
300
                copy($todo['from'], $todo['to']);
301
            } else {
302
                if (@link($todo['from'], $todo['to'])) {
303
                    $operation = 'Linked';
304
                } else {
305
                    copy($todo['from'], $todo['to']);
306
                }
307
            }
308
            chmod($todo['to'], $todo['mode']);
309
            $this->line("<info>{$operation} file</info> <comment>[{$todo['from']}]</comment> <info>To</info> <comment>[{$todo['to']}]</comment>");
310
        }
311
        return 0;
312
    }
313
}
314