Completed
Push — master ( dda272...0c6154 )
by Biao
04:08
created

LaravelSCommand::start()   F

Complexity

Conditions 15
Paths 308

Size

Total Lines 60
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 39
nc 308
nop 0
dl 0
loc 60
rs 3.7333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Hhxsv5\LaravelS\Illuminate;
4
5
use Illuminate\Console\Command;
6
use Illuminate\Filesystem\Filesystem;
7
8
class LaravelSCommand extends Command
9
{
10
    protected $signature = 'laravels';
11
12
    protected $description = 'LaravelS console tool';
13
14
    protected $actions;
15
16
    protected $isLumen = false;
17
18
    public function __construct()
19
    {
20
        $this->actions = ['start', 'stop', 'restart', 'reload', 'publish'];
21
        $actions = implode('|', $this->actions);
22
        $this->signature .= sprintf(' {action : %s} {--d|daemonize : Whether run as a daemon for start & restart}', $actions);
23
        $this->description .= ': ' . $actions;
24
25
        parent::__construct();
26
    }
27
28
    public function fire()
29
    {
30
        $this->handle();
31
    }
32
33
    public function handle()
34
    {
35
        $action = (string)$this->argument('action');
36
        if (!in_array($action, $this->actions, true)) {
37
            $this->warn(sprintf('LaravelS: action %s is not available, only support %s', $action, implode('|', $this->actions)));
38
            return;
39
        }
40
41
        $this->isLumen = stripos($this->getApplication()->getVersion(), 'Lumen') !== false;
42
        $this->loadConfigManually();
43
        $this->{$action}();
44
    }
45
46
    protected function loadConfigManually()
47
    {
48
        // Load configuration laravel.php manually for Lumen
49
        $basePath = config('laravels.laravel_base_path') ?: base_path();
50
        if ($this->isLumen && file_exists($basePath . '/config/laravels.php')) {
51
            $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

51
            $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...
52
        }
53
    }
54
55
    protected function outputLogo()
56
    {
57
        static $logo = <<<EOS
58
 _                               _  _____ 
59
| |                             | |/ ____|
60
| |     __ _ _ __ __ ___   _____| | (___  
61
| |    / _` | '__/ _` \ \ / / _ \ |\___ \ 
62
| |___| (_| | | | (_| |\ V /  __/ |____) |
63
|______\__,_|_|  \__,_| \_/ \___|_|_____/ 
64
                                           
65
EOS;
66
        $this->info($logo);
67
        $this->info('Speed up your Laravel/Lumen');
68
        $this->table(['Component', 'Version'], [
69
            ['Component' => 'PHP', 'Version' => phpversion()],
70
            ['Component' => 'Swoole', 'Version' => \swoole_version()],
71
            ['Component' => $this->getApplication()->getName(), 'Version' => $this->getApplication()->getVersion()],
72
        ]);
73
    }
74
75
    protected function start()
76
    {
77
        $this->outputLogo();
78
79
        $svrConf = config('laravels');
80
        $basePath = array_get($svrConf, 'laravel_base_path', base_path());
81
82
        if (empty($svrConf['swoole']['document_root'])) {
83
            $svrConf['swoole']['document_root'] = $basePath . '/public';
84
        }
85
        if (empty($svrConf['process_prefix'])) {
86
            $svrConf['process_prefix'] = $basePath;
87
        }
88
        if (!empty($svrConf['events'])) {
89
            if (empty($svrConf['swoole']['task_worker_num']) || $svrConf['swoole']['task_worker_num'] <= 0) {
90
                $this->error('LaravelS: Asynchronous event listening needs to set task_worker_num > 0');
91
                return;
92
            }
93
        }
94
        if ($this->option('daemonize')) {
95
            $svrConf['swoole']['daemonize'] = true;
96
        }
97
98
        $laravelConf = [
99
            'root_path'          => $basePath,
100
            'static_path'        => $svrConf['swoole']['document_root'],
101
            'register_providers' => array_unique((array)array_get($svrConf, 'register_providers', [])),
102
            'is_lumen'           => $this->isLumen,
103
            '_SERVER'            => $_SERVER,
104
            '_ENV'               => $_ENV,
105
        ];
106
107
        if (file_exists($svrConf['swoole']['pid_file'])) {
108
            $pid = (int)file_get_contents($svrConf['swoole']['pid_file']);
109
            if ($pid > 0 && $this->killProcess($pid, 0)) {
110
                $this->warn(sprintf('LaravelS: PID[%s] is already running at %s:%s.', $pid, $svrConf['listen_ip'], $svrConf['listen_port']));
111
                return;
112
            }
113
        }
114
115
        // Implements gracefully reload, avoid including laravel's files before worker start
116
        $cmd = sprintf('%s %s/../GoLaravelS.php', PHP_BINARY, __DIR__);
117
        $ret = $this->popen($cmd, json_encode(compact('svrConf', 'laravelConf')));
118
        if ($ret === false) {
119
            $this->error('LaravelS: popen ' . $cmd . ' failed');
120
            return;
121
        }
122
123
        $pidFile = empty($svrConf['swoole']['pid_file']) ? storage_path('laravels.pid') : $svrConf['swoole']['pid_file'];
124
125
        // Make sure that master process started
126
        $time = 0;
127
        while (!file_exists($pidFile) && $time <= 20) {
128
            usleep(100000);
129
            $time++;
130
        }
131
        if (file_exists($pidFile)) {
132
            $this->info(sprintf('LaravelS: PID[%s] is running at %s:%s.', file_get_contents($pidFile), $svrConf['listen_ip'], $svrConf['listen_port']));
133
        } else {
134
            $this->error(sprintf('LaravelS: PID file[%s] does not exist.', $pidFile));
135
        }
136
    }
137
138
    protected function popen($cmd, $input = null)
139
    {
140
        $fp = popen($cmd, 'w');
141
        if ($fp === false) {
142
            return false;
143
        }
144
        if ($input !== null) {
145
            fwrite($fp, $input);
146
        }
147
        pclose($fp);
148
        return true;
149
    }
150
151
    protected function stop()
152
    {
153
        $pidFile = config('laravels.swoole.pid_file') ?: storage_path('laravels.pid');
154
        if (file_exists($pidFile)) {
155
            $pid = (int)file_get_contents($pidFile);
156
            if ($this->killProcess($pid, 0)) {
157
                if ($this->killProcess($pid, SIGTERM)) {
158
                    // Make sure that master process quit
159
                    $time = 0;
160
                    while ($this->killProcess($pid, 0) && $time <= 20) {
161
                        usleep(100000);
162
                        $this->killProcess($pid, SIGTERM);
163
                        $time++;
164
                    }
165
                    if (file_exists($pidFile)) {
166
                        unlink($pidFile);
167
                    }
168
                    $this->info("LaravelS: PID[{$pid}] is stopped.");
169
                } else {
170
                    $this->error("LaravelS: PID[{$pid}] is stopped failed.");
171
                }
172
            } else {
173
                $this->warn("LaravelS: PID[{$pid}] does not exist, or permission denied.");
174
                if (file_exists($pidFile)) {
175
                    unlink($pidFile);
176
                }
177
            }
178
        } else {
179
            $this->info('LaravelS: already stopped.');
180
        }
181
    }
182
183
    protected function restart()
184
    {
185
        $this->stop();
186
        $this->start();
187
    }
188
189
    protected function reload()
190
    {
191
        $pidFile = config('laravels.swoole.pid_file') ?: storage_path('laravels.pid');
192
        if (!file_exists($pidFile)) {
193
            $this->error('LaravelS: it seems that LaravelS is not running.');
194
            return;
195
        }
196
197
        $pid = (int)file_get_contents($pidFile);
198
        if (!$this->killProcess($pid, 0)) {
199
            $this->error("LaravelS: PID[{$pid}] does not exist, or permission denied.");
200
            return;
201
        }
202
203
        if ($this->killProcess($pid, SIGUSR1)) {
204
            $this->info("LaravelS: PID[{$pid}] is reloaded.");
205
        } else {
206
            $this->error("LaravelS: PID[{$pid}] is reloaded failed.");
207
        }
208
    }
209
210
    protected function publish()
211
    {
212
        $basePath = config('laravels.laravel_base_path') ?: base_path();
213
        $to = $basePath . '/config/laravels.php';
214
        if (file_exists($to)) {
215
            $choice = $this->anticipate($to . ' already exists, do you want to override it ? Y/N', ['Y', 'N'], 'N');
216
            if (!$choice || strtoupper($choice) !== 'Y') {
217
                $this->info('Publishing skipped.');
218
                return;
219
            }
220
        }
221
222
        try {
223
            $this->call('vendor:publish', ['--provider' => LaravelSServiceProvider::class, '--force' => true]);
224
            return;
225
        } catch (\Exception $e) {
226
            if (!($e instanceof \InvalidArgumentException)) {
227
                throw $e;
228
            }
229
        }
230
        $from = __DIR__ . '/../../config/laravels.php';
231
232
        $toDir = dirname($to);
233
234
235
        /**
236
         * @var Filesystem $files
237
         */
238
        $files = app(Filesystem::class);
239
240
        if (!$files->isDirectory($toDir)) {
241
            $files->makeDirectory($toDir, 0755, true);
242
        }
243
244
        $files->copy($from, $to);
245
246
        $from = str_replace($basePath, '', realpath($from));
247
248
        $to = str_replace($basePath, '', realpath($to));
249
250
        $this->line('<info>Copied File</info> <comment>[' . $from . ']</comment> <info>To</info> <comment>[' . $to . ']</comment>');
251
    }
252
253
    protected function killProcess($pid, $sig)
254
    {
255
        try {
256
            return \swoole_process::kill($pid, $sig);
257
        } catch (\Exception $e) {
258
            return false;
259
        }
260
    }
261
}
262