Command::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Encore\LumenSwoole;
4
5
use Error;
6
use ErrorException;
7
use Laravel\Lumen\Exceptions\Handler;
8
use Symfony\Component\Console\Output\ConsoleOutput;
9
use Symfony\Component\Debug\Exception\FatalErrorException;
10
use Symfony\Component\Debug\Exception\FatalThrowableError;
11
12
/**
13
 * Class Command.
14
 */
15
class Command
16
{
17
    /**
18
     * Pid file.
19
     *
20
     * @var string
21
     */
22
    protected $pidFile;
23
24
    /**
25
     * Command options.
26
     *
27
     * @var array
28
     */
29
    protected $options = [];
30
31
    /**
32
     * Server host.
33
     *
34
     * @var string
35
     */
36
    protected $host = '127.0.0.1';
37
38
    /**
39
     * Server port.
40
     *
41
     * @var int
42
     */
43
    protected $port = 8083;
44
45
    /**
46
     * Application bootstrap file.
47
     *
48
     * @var string
49
     */
50
    protected $bootstrap = 'bootstrap/app.php';
51
52
    /**
53
     * Http server options.
54
     *
55
     * @var array
56
     */
57
    protected $serverOptions = [];
58
59
    /**
60
     * Create a new Command instance.
61
     */
62
    public function __construct()
63
    {
64
        $this->registerErrorHandling();
65
    }
66
67
    /**
68
     * Main access.
69
     *
70
     * @param $argv
71
     *
72
     * @return mixed
73
     */
74
    public static function main($argv)
75
    {
76
        $command = new static();
77
78
        return $command->run($argv);
79
    }
80
81
    /**
82
     * Run up the server.
83
     *
84
     * @param string $argv
85
     *
86
     * @throws \Exception
87
     */
88
    public function run($argv)
89
    {
90
        if ($this->handleAction($argv)) {
0 ignored issues
show
Documentation introduced by
$argv is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
91
            return;
92
        }
93
94
        if (!$this->handleArguments()) {
95
            return;
96
        }
97
98
        echo "Swoole http server started on http://{$this->host}:{$this->port}/\r\n";
99
100
        $server = new Server($this->host, $this->port);
101
        $server->setApplication(require $this->bootstrap);
102
103
        $server->options($this->serverOptions)->run();
104
    }
105
106
    /**
107
     * Handle command action.
108
     *
109
     * @param array $argv
110
     *
111
     * @return bool
112
     */
113
    public function handleAction($argv)
114
    {
115
        if (count($argv) < 2) {
116
            return false;
117
        }
118
119
        if (in_array($argv[1], ['stop', 'reload', 'restart'])) {
120
            call_user_func([$this, $argv[1]]);
121
122
            return true;
123
        }
124
125
        return false;
126
    }
127
128
    /**
129
     * Handle Command arguments.
130
     *
131
     * @return bool
132
     */
133
    public function handleArguments()
134
    {
135
        $serverOptions = array_map(function ($option) {
136
            return "$option:";
137
        }, Server::$validServerOptions);
138
139
        $longOptions = array_merge(['host:', 'port:', 'help', 'version'], $serverOptions);
140
141
        $options = getopt('dvp:h::s:', $longOptions);
142
143
        foreach ($options as $option => $value) {
144
            switch ($option) {
145
                case 'h':
146
                case 'host':
147
                    if ($value) {
148
                        $this->host = $value;
149
                    } else {
150
                        $this->usage();
151
152
                        return false;
153
                    }
154
                    break;
155
156
                case 'help':
157
                    $this->usage();
158
159
                    return false;
160
161
                case 'p':
162
                case 'port':
163
                    if ($value) {
164
                        $this->port = (int) $value;
165
                    }
166
                    break;
167
168
                case 's':
169
                    if ($value) {
170
                        $this->bootstrap = $value;
171
                    }
172
                    break;
173
174
                case 'd':
175
                    $this->serverOptions['daemonize'] = true;
176
                    break;
177
178
                case 'v':
179
                case 'version':
180
                    echo Server::VERSION, "\r\n";
181
182
                    return false;
183
184
                default:
185
                    if (in_array($option, Server::$validServerOptions) && $value) {
186
                        $this->serverOptions[$option] = $value;
187
                    }
188
                    break;
189
            }
190
        }
191
192
        return true;
193
    }
194
195
    /**
196
     * Show usage.
197
     */
198
    public function usage()
199
    {
200
        $this->printVersionString();
201
202
        echo <<<'EOT'
203
204
Usage: vendor/bin/lumen-swoole {stop|restart|reload}
205
206
  -h <hostname>      Server hostname (default: 127.0.0.1).
207
  -p <port>          Server port (default: 6379).
208
  -s <script>        Application script.
209
  -d <daemon>        Run server in daemon mode.
210
  -v <version>       Output version and exit.
211
212
  --host             Server hostname (default: 127.0.0.1).
213
  --port             Server port (default: 6379).
214
  --help             Output this help and exit.
215
  --version          Output version and exit.
216
217
Examples:
218
  vendor/bin/lumen-swoole -d
219
  vendor/bin/lumen-swoole -h 127.0.0.1 -p 80 -d
220
  vendor/bin/lumen-swoole -h 127.0.0.1 -p 80 -d
221
  vendor/bin/lumen-swoole -s path/to/bootstrap/script.php
222
223
  vendor/bin/lumen-swoole restart
224
  vendor/bin/lumen-swoole reload
225
  vendor/bin/lumen-swoole restart
226
227
Other options please see http://wiki.swoole.com/wiki/page/274.html.
228
229
EOT;
230
    }
231
232
    /**
233
     * Print version string.
234
     */
235
    public function printVersionString()
236
    {
237
        echo Server::VERSION, "\r\n";
238
    }
239
240
    /**
241
     * Stop the server.
242
     *
243
     * @throws \Exception
244
     *
245
     * @return void
246
     */
247
    public function stop()
248
    {
249
        $pid = $this->getPid();
250
251
        echo "Server is stopping...\r\n";
252
253
        posix_kill($pid, SIGTERM);
254
255
        usleep(500);
256
257
        posix_kill($pid, SIGKILL);
258
259
        unlink($this->pidFile);
260
    }
261
262
    /**
263
     * Reload the server.
264
     *
265
     * @throws \Exception
266
     *
267
     * @return void
268
     */
269
    public function reload()
270
    {
271
        posix_kill($this->getPid(), SIGUSR1);
272
    }
273
274
    /**
275
     * Restart the server.
276
     *
277
     * @throws \Exception
278
     *
279
     * @return void
280
     */
281
    public function restart()
282
    {
283
        $pid = $this->getPid();
284
285
        $cmd = exec("ps -p $pid -o args | grep lumen-swoole");
286
287
        if (empty($cmd)) {
288
            throw new \Exception('Cannot find server process.');
289
        }
290
291
        $this->stop();
292
293
        usleep(2000);
294
295
        echo "Server is starting...\r\n";
296
297
        exec($cmd);
298
    }
299
300
    /**
301
     * Get process identifier of this server.
302
     *
303
     * @throws \Exception
304
     *
305
     * @return string|false
306
     */
307
    protected function getPid()
308
    {
309
        $app = require $this->bootstrap;
310
311
        $this->pidFile = $app->storagePath('lumen-swoole.pid');
312
313
        if (!file_exists($this->pidFile)) {
314
            throw new \Exception('The Server is not running.');
315
        }
316
317
        $pid = file_get_contents($this->pidFile);
318
319
        if (posix_getpgid($pid)) {
320
            return $pid;
321
        }
322
323
        unlink($this->pidFile);
324
325
        return false;
326
    }
327
328
    /**
329
     * Set the error handling for the application.
330
     *
331
     * @return void
332
     */
333
    protected function registerErrorHandling()
334
    {
335
        error_reporting(-1);
336
337
        set_error_handler(function ($level, $message, $file = '', $line = 0) {
338
            if (error_reporting() & $level) {
339
                throw new ErrorException($message, 0, $level, $file, $line);
340
            }
341
        });
342
343
        set_exception_handler(function ($e) {
344
            $this->handleUncaughtException($e);
345
        });
346
347
        register_shutdown_function(function () {
348
            $this->handleShutdown();
349
        });
350
    }
351
352
    /**
353
     * Handle an uncaught exception instance.
354
     *
355
     * @param \Exception $e
356
     *
357
     * @return void
358
     */
359
    protected function handleUncaughtException($e)
360
    {
361
        if ($e instanceof Error) {
362
            $e = new FatalThrowableError($e);
363
        }
364
365
        (new Handler())->renderForConsole(new ConsoleOutput(), $e);
366
    }
367
368
    /**
369
     * Handle the application shutdown routine.
370
     *
371
     * @return void
372
     */
373
    protected function handleShutdown()
374
    {
375
        if (!is_null($error = error_get_last()) && $this->isFatalError($error['type'])) {
376
            $this->handleUncaughtException(new FatalErrorException(
377
                $error['message'],
378
                $error['type'],
379
                0,
380
                $error['file'],
381
                $error['line']
382
            ));
383
        }
384
    }
385
386
    /**
387
     * Determine if the error type is fatal.
388
     *
389
     * @param int $type
390
     *
391
     * @return bool
392
     */
393
    protected function isFatalError($type)
394
    {
395
        $errorCodes = [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE];
396
397
        if (defined('FATAL_ERROR')) {
398
            $errorCodes[] = FATAL_ERROR;
399
        }
400
401
        return in_array($type, $errorCodes);
402
    }
403
}
404