Passed
Push — master ( 9f628c...437dce )
by Biao
09:13
created

Server::bindBaseEvents()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 10
rs 10
1
<?php
2
0 ignored issues
show
Coding Style introduced by
Missing file doc comment
Loading history...
3
namespace Hhxsv5\LaravelS\Swoole;
4
5
use Hhxsv5\LaravelS\Illuminate\LogTrait;
6
use Hhxsv5\LaravelS\Swoole\Process\ProcessTitleTrait;
7
use Hhxsv5\LaravelS\Swoole\Socket\PortInterface;
8
use Hhxsv5\LaravelS\Swoole\Task\BaseTask;
9
use Hhxsv5\LaravelS\Swoole\Task\Event;
10
use Hhxsv5\LaravelS\Swoole\Task\Listener;
11
use Hhxsv5\LaravelS\Swoole\Task\Task;
12
use Swoole\Http\Request as SwooleRequest;
13
use Swoole\Http\Response as SwooleResponse;
14
use Swoole\Http\Server as HttpServer;
15
use Swoole\Server\Port;
16
use Swoole\Table;
17
use Swoole\WebSocket\Server as WebSocketServer;
18
19
class Server
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class Server
Loading history...
20
{
21
    use LogTrait;
22
    use ProcessTitleTrait;
23
24
    /**@var array */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
25
    protected $conf;
26
27
    /**@var HttpServer|WebSocketServer */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
28
    protected $swoole;
29
30
    /**@var bool */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
31
    protected $enableWebSocket = false;
32
33
    protected function __construct(array $conf)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
34
    {
35
        $this->conf = $conf;
36
        $this->enableWebSocket = !empty($this->conf['websocket']['enable']);
37
38
        $ip = isset($conf['listen_ip']) ? $conf['listen_ip'] : '127.0.0.1';
39
        $port = isset($conf['listen_port']) ? $conf['listen_port'] : 5200;
40
        $socketType = isset($conf['socket_type']) ? (int)$conf['socket_type'] : SWOOLE_SOCK_TCP;
41
42
        if ($socketType === SWOOLE_SOCK_UNIX_STREAM) {
43
            $socketDir = dirname($ip);
44
            if (!file_exists($socketDir) && !mkdir($socketDir) && !is_dir($socketDir)) {
45
                throw new \RuntimeException(sprintf('Directory "%s" was not created', $socketDir));
46
            }
47
        }
48
49
        $settings = isset($conf['swoole']) ? $conf['swoole'] : [];
50
        $settings['enable_static_handler'] = !empty($conf['handle_static']);
51
52
        $serverClass = $this->enableWebSocket ? WebSocketServer::class : HttpServer::class;
53
        if (isset($settings['ssl_cert_file'], $settings['ssl_key_file'])) {
54
            $this->swoole = new $serverClass($ip, $port, SWOOLE_PROCESS, $socketType | SWOOLE_SSL);
55
        } else {
56
            $this->swoole = new $serverClass($ip, $port, SWOOLE_PROCESS, $socketType);
57
        }
58
59
        // Disable Coroutine
60
        $settings['enable_coroutine'] = false;
61
62
        $this->swoole->set($settings);
63
64
        $this->bindBaseEvents();
65
        $this->bindHttpEvents();
66
        $this->bindTaskEvents();
67
        $this->bindWebSocketEvents();
68
        $this->bindPortEvents();
69
        $this->bindSwooleTables();
70
71
        // Disable Hook
72
        class_exists('Swoole\Coroutine') && \Swoole\Coroutine::set(['hook_flags' => false]);
73
    }
74
75
    protected function bindBaseEvents()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function bindBaseEvents()
Loading history...
76
    {
77
        $this->swoole->on('Start', [$this, 'onStart']);
78
        $this->swoole->on('Shutdown', [$this, 'onShutdown']);
79
        $this->swoole->on('ManagerStart', [$this, 'onManagerStart']);
80
        $this->swoole->on('ManagerStop', [$this, 'onManagerStop']);
81
        $this->swoole->on('WorkerStart', [$this, 'onWorkerStart']);
82
        $this->swoole->on('WorkerStop', [$this, 'onWorkerStop']);
83
        $this->swoole->on('WorkerError', [$this, 'onWorkerError']);
84
        $this->swoole->on('PipeMessage', [$this, 'onPipeMessage']);
85
    }
86
87
    protected function bindHttpEvents()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function bindHttpEvents()
Loading history...
88
    {
89
        $this->swoole->on('Request', [$this, 'onRequest']);
90
    }
91
92
    protected function bindTaskEvents()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function bindTaskEvents()
Loading history...
93
    {
94
        if (!empty($this->conf['swoole']['task_worker_num'])) {
95
            $this->swoole->on('Task', [$this, 'onTask']);
96
            $this->swoole->on('Finish', [$this, 'onFinish']);
97
        }
98
    }
99
100
    protected function triggerWebSocketEvent($event, array $params)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function triggerWebSocketEvent()
Loading history...
101
    {
102
        return $this->callWithCatchException(function () use ($event, $params) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
103
            $handler = $this->getWebSocketHandler();
104
105
            if (method_exists($handler, $event)) {
106
                call_user_func_array([$handler, $event], $params);
107
            } elseif ($event === 'onHandShake') {
108
                // Set default HandShake
109
                call_user_func_array([$this, 'onHandShake'], $params);
110
            }
111
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
112
    }
113
114
    protected function bindWebSocketEvents()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function bindWebSocketEvents()
Loading history...
115
    {
116
        if ($this->enableWebSocket) {
117
            $this->swoole->on('HandShake', function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
118
                return $this->triggerWebSocketEvent('onHandShake', func_get_args());
119
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
120
121
            $this->swoole->on('Open', function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
122
                $this->triggerWebSocketEvent('onOpen', func_get_args());
123
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
124
125
            $this->swoole->on('Message', function () {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
126
                $this->triggerWebSocketEvent('onMessage', func_get_args());
127
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
128
129
            $this->swoole->on('Close', function (WebSocketServer $server, $fd, $reactorId) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
130
                $clientInfo = $server->getClientInfo($fd);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $clientInfo is correct as $server->getClientInfo($fd) targeting Swoole\Server::getClientInfo() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
131
                if (isset($clientInfo['websocket_status']) && $clientInfo['websocket_status'] === \WEBSOCKET_STATUS_FRAME) {
132
                    $this->triggerWebSocketEvent('onClose', func_get_args());
133
                }
134
                // else ignore the close event for http server
135
            });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
136
        }
137
    }
138
139
    protected function triggerPortEvent(Port $port, $handlerClass, $event, array $params)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function triggerPortEvent()
Loading history...
140
    {
141
        return $this->callWithCatchException(function () use ($port, $handlerClass, $event, $params) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
142
            $handler = $this->getSocketHandler($port, $handlerClass);
143
144
            if (method_exists($handler, $event)) {
145
                call_user_func_array([$handler, $event], $params);
146
            } elseif ($event === 'onHandShake') {
147
                // Set default HandShake
148
                call_user_func_array([$this, 'onHandShake'], $params);
149
            }
150
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
151
    }
152
153
    protected function bindPortEvents()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function bindPortEvents()
Loading history...
154
    {
155
        $sockets = empty($this->conf['sockets']) ? [] : $this->conf['sockets'];
156
        foreach ($sockets as $socket) {
157
            if (isset($socket['enable']) && !$socket['enable']) {
158
                continue;
159
            }
160
161
            $port = $this->swoole->addListener($socket['host'], $socket['port'], $socket['type']);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $port is correct as $this->swoole->addListen...ort'], $socket['type']) targeting Swoole\Server::addlistener() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
162
            if (!($port instanceof Port)) {
163
                $errno = method_exists($this->swoole, 'getLastError') ? $this->swoole->getLastError() : 'unknown';
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->swoole->getLastError() targeting Swoole\Server::getLastError() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
164
                $errstr = sprintf('listen %s:%s failed: errno=%s', $socket['host'], $socket['port'], $errno);
165
                $this->error($errstr);
166
                continue;
167
            }
168
169
            $port->set(empty($socket['settings']) ? [] : $socket['settings']);
170
171
            $handlerClass = $socket['handler'];
172
173
            $events = [
174
                'Open',
175
                'HandShake',
176
                'Request',
177
                'Message',
178
                'Connect',
179
                'Close',
180
                'Receive',
181
                'Packet',
182
                'BufferFull',
183
                'BufferEmpty',
184
            ];
185
            foreach ($events as $event) {
186
                $port->on($event, function () use ($port, $handlerClass, $event) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
187
                    $this->triggerPortEvent($port, $handlerClass, 'on' . $event, func_get_args());
188
                });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
189
            }
190
        }
191
    }
192
193
    protected function getWebSocketHandler()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getWebSocketHandler()
Loading history...
194
    {
195
        static $handler = null;
196
        if ($handler !== null) {
197
            return $handler;
198
        }
199
200
        $handlerClass = $this->conf['websocket']['handler'];
201
        $t = new $handlerClass();
202
        if (!($t instanceof WebSocketHandlerInterface)) {
203
            throw new \InvalidArgumentException(sprintf('%s must implement the interface %s', get_class($t), WebSocketHandlerInterface::class));
204
        }
205
        $handler = $t;
206
        return $handler;
207
    }
208
209
    protected function getSocketHandler(Port $port, $handlerClass)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getSocketHandler()
Loading history...
210
    {
211
        static $handlers = [];
212
        $portHash = spl_object_hash($port);
213
        if (isset($handlers[$portHash])) {
214
            return $handlers[$portHash];
215
        }
216
        $t = new $handlerClass($port);
217
        if (!($t instanceof PortInterface)) {
218
            throw new \InvalidArgumentException(sprintf('%s must extend the abstract class TcpSocket/UdpSocket', get_class($t)));
219
        }
220
        $handlers[$portHash] = $t;
221
        return $handlers[$portHash];
222
    }
223
224
    protected function bindSwooleTables()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function bindSwooleTables()
Loading history...
225
    {
226
        $tables = isset($this->conf['swoole_tables']) ? (array)$this->conf['swoole_tables'] : [];
227
        foreach ($tables as $name => $table) {
228
            $t = new Table($table['size']);
229
            foreach ($table['column'] as $column) {
230
                if (isset($column['size'])) {
231
                    $t->column($column['name'], $column['type'], $column['size']);
232
                } else {
233
                    $t->column($column['name'], $column['type']);
234
                }
235
            }
236
            $t->create();
237
            $name .= 'Table'; // Avoid naming conflicts
238
            $this->swoole->{$name} = $t;
239
        }
240
    }
241
242
    public function onStart(HttpServer $server)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onStart()
Loading history...
243
    {
244
        $this->setProcessTitle(sprintf('%s laravels: master process', $this->conf['process_prefix']));
245
246
        if (version_compare(swoole_version(), '1.9.5', '<')) {
0 ignored issues
show
Bug introduced by
swoole_version() of type null is incompatible with the type string expected by parameter $version1 of version_compare(). ( Ignorable by Annotation )

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

246
        if (version_compare(/** @scrutinizer ignore-type */ swoole_version(), '1.9.5', '<')) {
Loading history...
Bug introduced by
Are you sure the usage of swoole_version() is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
247
            file_put_contents($this->conf['swoole']['pid_file'], $server->master_pid);
248
        }
249
    }
250
251
    public function onShutdown(HttpServer $server)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onShutdown()
Loading history...
252
    {
253
    }
254
255
    public function onManagerStart(HttpServer $server)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onManagerStart()
Loading history...
256
    {
257
        $this->setProcessTitle(sprintf('%s laravels: manager process', $this->conf['process_prefix']));
258
    }
259
260
    public function onManagerStop(HttpServer $server)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onManagerStop()
Loading history...
261
    {
262
    }
263
264
    public function onWorkerStart(HttpServer $server, $workerId)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onWorkerStart()
Loading history...
265
    {
266
        $processName = $workerId >= $server->setting['worker_num'] ? 'task worker' : 'worker';
267
        $this->setProcessTitle(sprintf('%s laravels: %s process %d', $this->conf['process_prefix'], $processName, $workerId));
268
269
        if (function_exists('opcache_reset')) {
270
            opcache_reset();
271
        }
272
        if (function_exists('apc_clear_cache')) {
273
            apc_clear_cache();
274
        }
275
276
        clearstatcache();
277
278
        // Disable Hook
279
        class_exists('Swoole\Runtime') && \Swoole\Runtime::enableCoroutine(false);
280
    }
281
282
    public function onWorkerStop(HttpServer $server, $workerId)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onWorkerStop()
Loading history...
283
    {
284
    }
285
286
    public function onWorkerError(HttpServer $server, $workerId, $workerPId, $exitCode, $signal)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onWorkerError()
Loading history...
287
    {
288
        $this->error(sprintf('worker[%d] error: exitCode=%s, signal=%s', $workerId, $exitCode, $signal));
289
    }
290
291
    public function onPipeMessage(HttpServer $server, $srcWorkerId, $message)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onPipeMessage()
Loading history...
292
    {
293
        if ($message instanceof BaseTask) {
294
            $this->onTask($server, null, $srcWorkerId, $message);
295
        }
296
    }
297
298
    public function onRequest(SwooleRequest $swooleRequest, SwooleResponse $swooleResponse)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onRequest()
Loading history...
299
    {
300
    }
301
302
    public function onHandShake(SwooleRequest $request, SwooleResponse $response)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onHandShake()
Loading history...
303
    {
304
        if (!isset($request->header['sec-websocket-key'])) {
305
            // Bad protocol implementation: it is not RFC6455.
306
            $response->end();
307
            return;
308
        }
309
        $secKey = $request->header['sec-websocket-key'];
310
        if (!preg_match('#^[+/0-9A-Za-z]{21}[AQgw]==$#', $secKey) || 16 !== strlen(base64_decode($secKey))) {
311
            // Header Sec-WebSocket-Key is illegal;
312
            $response->end();
313
            return;
314
        }
315
316
        $headers = [
317
            'Upgrade'               => 'websocket',
318
            'Connection'            => 'Upgrade',
319
            'Sec-WebSocket-Accept'  => base64_encode(sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true)),
320
            'Sec-WebSocket-Version' => '13',
321
        ];
322
323
        // WebSocket connection to 'ws://127.0.0.1:5200/'
324
        // failed: Error during WebSocket handshake:
325
        // Response must not include 'Sec-WebSocket-Protocol' header if not present in request: websocket
326
        if (isset($request->header['sec-websocket-protocol'])) {
327
            $headers['Sec-WebSocket-Protocol'] = $request->header['sec-websocket-protocol'];
328
        }
329
330
        foreach ($headers as $key => $value) {
331
            $response->header($key, $value);
332
        }
333
334
        $response->status(101);
335
        $response->end();
336
    }
337
338
    public function onTask(HttpServer $server, $taskId, $srcWorkerId, $data)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onTask()
Loading history...
339
    {
340
        if ($data instanceof Event) {
341
            $this->handleEvent($data);
342
        } elseif ($data instanceof Task) {
343
            if ($this->handleTask($data) && method_exists($data, 'finish')) {
344
                return $data;
345
            }
346
        }
347
    }
348
349
    public function onFinish(HttpServer $server, $taskId, $data)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function onFinish()
Loading history...
350
    {
351
        if ($data instanceof Task) {
352
            $data->finish();
353
        }
354
    }
355
356
    protected function handleEvent(Event $event)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function handleEvent()
Loading history...
357
    {
358
        $listenerClasses = $event->getListeners();
359
        foreach ($listenerClasses as $listenerClass) {
360
            /**@var Listener $listener */
0 ignored issues
show
Coding Style introduced by
The open comment tag must be the only content on the line
Loading history...
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
The close comment tag must be the only content on the line
Loading history...
361
            $listener = new $listenerClass($event);
362
            if (!($listener instanceof Listener)) {
363
                throw new \InvalidArgumentException(sprintf('%s must extend the abstract class %s', $listenerClass, Listener::class));
364
            }
365
            $this->callWithCatchException(function () use ($listener) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
366
                $listener->handle();
367
            }, [], $event->getTries());
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
368
        }
369
        return true;
370
    }
371
372
    protected function handleTask(Task $task)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function handleTask()
Loading history...
373
    {
374
        return $this->callWithCatchException(function () use ($task) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
375
            $task->handle();
376
            return true;
377
        }, [], $task->getTries());
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
378
    }
379
380
    protected function fireEvent($event, $interface, array $arguments)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function fireEvent()
Loading history...
381
    {
382
        if (isset($this->conf['event_handlers'][$event])) {
383
            $eventHandlers = (array)$this->conf['event_handlers'][$event];
384
            foreach ($eventHandlers as $eventHandler) {
385
                if (!isset(class_implements($eventHandler)[$interface])) {
386
                    throw new \InvalidArgumentException(sprintf(
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
387
                            '%s must implement the interface %s',
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 24 spaces, but found 28.
Loading history...
388
                            $eventHandler,
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 24 spaces, but found 28.
Loading history...
389
                            $interface
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 24 spaces, but found 28.
Loading history...
390
                        )
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 20 spaces, but found 24.
Loading history...
391
                    );
392
                }
393
                $this->callWithCatchException(function () use ($eventHandler, $arguments) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
394
                    call_user_func_array([(new $eventHandler), 'handle'], $arguments);
395
                });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
396
            }
397
        }
398
    }
399
400
    public function run()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function run()
Loading history...
401
    {
402
        $this->swoole->start();
403
    }
404
}
405