Completed
Push — master ( 5b05fa...1d7f97 )
by Dawid
13s queued 10s
created

Server::start()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 5.0187

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 8
nop 0
dl 0
loc 22
rs 8.6737
c 0
b 0
f 0
ccs 10
cts 11
cp 0.9091
crap 5.0187
1
<?php declare(strict_types=1);
2
3
namespace Igni\Http;
4
5
use Igni\Exception\RuntimeException;
6
use Igni\Http\Server\ClientStats;
7
use Igni\Http\Server\OnConnect;
8
use Igni\Http\Server\OnShutdown;
9
use Igni\Http\Server\OnStart;
10
use Igni\Http\Server\ServerStats;
11
use Igni\Http\Server\HttpConfiguration;
12
use Igni\Http\Server\Listener;
13
use Igni\Http\Server\OnClose;
14
use Igni\Http\Server\OnRequest;
15
use Swoole;
0 ignored issues
show
Bug introduced by
The type Swoole was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
17
/**
18
 * Http server implementation based on swoole extension.
19
 *
20
 * @package Igni\Http
21
 */
22
class Server
23
{
24
    private const SWOOLE_EXT_NAME = 'swoole';
25
26
    /**
27
     * @var Swoole\Server|null
0 ignored issues
show
Bug introduced by
The type Swoole\Server was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
     */
29
    private $handler;
30
31
    /**
32
     * @var HttpConfiguration
33
     */
34
    private $settings;
35
36
    /**
37
     * @var Listener[]
38
     */
39
    private $listeners = [];
40
41 5
    public function __construct(HttpConfiguration $settings = null)
42
    {
43 5
        if (!extension_loaded(self::SWOOLE_EXT_NAME)) {
44
            throw new RuntimeException('Could not run server without swoole extension.');
45
        }
46
47 5
        if ($settings === null) {
48 4
            $settings = new HttpConfiguration();
49
        }
50
51 5
        $this->settings = $settings;
52 5
    }
53
54
    /**
55
     * Adds listener that is attached to server once it is run.
56
     *
57
     * @param Listener $listener
58
     */
59 1
    public function addListener(Listener $listener): void
60
    {
61 1
        $this->listeners[] = $listener;
62 1
        if ($this->handler !== null) {
63 1
            $this->attachListener($listener);
64
        }
65 1
    }
66
67
    /**
68
     * Checks if listener exists.
69
     *
70
     * @param Listener $listener
71
     * @return bool
72
     */
73 1
    public function hasListener(Listener $listener): bool
74
    {
75 1
        return in_array($listener, $this->listeners);
76
    }
77
78
    /**
79
     * Returns information about client.
80
     *
81
     * @param int $clientId
82
     * @return ClientStats
83
     */
84 1
    public function getClientStats(int $clientId): ClientStats
85
    {
86 1
        return new ClientStats($this->handler->getClientInfo($clientId));
0 ignored issues
show
Bug introduced by
The method getClientInfo() does not exist on null. ( Ignorable by Annotation )

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

86
        return new ClientStats($this->handler->/** @scrutinizer ignore-call */ getClientInfo($clientId));

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...
87
    }
88
89
    /**
90
     * Returns information about server.
91
     *
92
     * @return ServerStats
93
     */
94 1
    public function getServerStats(): ServerStats
95
    {
96 1
        return new ServerStats($this->handler->stats());
97
    }
98
99
    /**
100
     * Starts the server.
101
     */
102 2
    public function start(): void
103
    {
104 2
        if ($this->settings->isSslEnabled()) {
105 1
            $flags = SWOOLE_SOCK_TCP | SWOOLE_SSL;
0 ignored issues
show
Bug introduced by
The constant Igni\Http\SWOOLE_SOCK_TCP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
106
        } else {
107 1
            $flags = SWOOLE_SOCK_TCP;
108
        }
109
110 2
        $settings = $this->settings->getSettings();
111
112 2
        if (!defined('IS_TEST') || IS_TEST !== true) {
113
            $this->handler = new Swoole\Http\Server($settings['address'], $settings['port'], SWOOLE_PROCESS, $flags);
0 ignored issues
show
Bug introduced by
The constant Igni\Http\SWOOLE_PROCESS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The type Swoole\Http\Server was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
114
        }
115 2
        $this->handler->set($settings);
116
117
        // Attach listeners.
118 2
        foreach ($this->listeners as $listener) {
119 1
            $this->attachListener($listener);
120
        }
121
122
        // Start the server.
123 2
        $this->handler->start();
124 2
    }
125
126
    /**
127
     * Stops the server.
128
     */
129
    public function stop(): void
130
    {
131
        $this->handler->shutdown();
132
        $this->handler = null;
133
    }
134
135 1
    private function attachListener(Listener $listener): void
136
    {
137 1
        if ($listener instanceof OnRequest) {
138 1
            $this->attachOnRequestListener($listener);
139
        }
140
141 1
        if ($listener instanceof OnConnect) {
142 1
            $this->attachOnConnectListener($listener);
143
        }
144
145 1
        if ($listener instanceof OnClose) {
146
            $this->attachOnCloseListener($listener);
147
        }
148
149 1
        if ($listener instanceof OnShutdown) {
150 1
            $this->attachOnShutdownListener($listener);
151
        }
152
153 1
        if ($listener instanceof OnStart) {
154 1
            $this->attachOnStartListener($listener);
155
        }
156 1
    }
157
158 1
    private function attachOnRequestListener(OnRequest $listener): void
159
    {
160
        $this->handler->on('Request', function(Swoole\Http\Request $request, Swoole\Http\Response $response) use ($listener) {
0 ignored issues
show
Bug introduced by
The type Swoole\Http\Response was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type Swoole\Http\Request was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
161
            $psrRequest = ServerRequest::fromSwooleRequest($request);
162
            $psrResponse = $listener->onRequest($psrRequest);
163
164
            // Set headers
165
            foreach ($psrResponse->getHeaders() as $name => $values) {
166
                foreach ($values as $value) {
167
                    $response->header($name, $value);
168
                }
169
            }
170
171
            // Status code
172
            $response->status($psrResponse->getStatusCode());
173
174
            // Protect server software header.
175
            $response->header('software-server', '');
176
177
            // End.
178
            $response->end($psrResponse->getBody()->getContents());
179 1
        });
180 1
    }
181
182 1
    private function attachOnConnectListener(OnConnect $listener): void
183
    {
184
        $this->handler->on('Connect', function($handler, $clientId) use ($listener) {
185
            $listener->onConnect($this, $clientId);
186 1
        });
187 1
    }
188
189
    private function attachOnCloseListener(OnClose $listener): void
190
    {
191
        $this->handler->on('Close', function($handler, $clientId) use ($listener) {
192
            $listener->onClose($this, $clientId);
193
        });
194
    }
195
196 1
    private function attachOnShutdownListener(OnShutdown $listener): void
197
    {
198
        $this->handler->on('Shutdown', function() use ($listener) {
199
            $listener->onShutdown($this);
200 1
        });
201 1
    }
202
203 1
    private function attachOnStartListener(OnStart $listener): void
204
    {
205
        $this->handler->on('Start', function() use ($listener) {
206
            $listener->onStart($this);
207 1
        });
208 1
    }
209
}
210