Passed
Push — master ( 767d18...65c593 )
by Ekin
11:48
created

Handler::handleClient()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1.027

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 4
dl 0
loc 16
ccs 7
cts 10
cp 0.7
crap 1.027
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace ekinhbayar\GitAmp\Websocket;
4
5
use Amp\Delayed;
6
use Amp\Http\Server\HttpServer;
7
use Amp\Http\Server\Request;
8
use Amp\Http\Server\Response;
9
use Amp\Http\Status;
10
use Amp\Promise;
11
use Amp\Success;
12
use Amp\Websocket\Client;
13
use Amp\Websocket\Server\ClientHandler;
14
use Amp\Websocket\Server\Gateway;
15
use Amp\Websocket\Server\WebsocketServerObserver;
16
use ekinhbayar\GitAmp\Configuration;
17
use ekinhbayar\GitAmp\Provider\Listener;
18
use ekinhbayar\GitAmp\Response\Results;
19
use Psr\Log\LoggerInterface;
20
use function Amp\asyncCall;
21
use function Amp\call;
22
23
class Handler implements ClientHandler, WebsocketServerObserver
24
{
25
    private Gateway $gateway;
26
27
    private Listener $provider;
28
29
    private Configuration $configuration;
30
31
    private Results $lastEvents;
32
33
    private LoggerInterface $logger;
34
35 8
    public function __construct(
36
        Listener $provider,
37
        Configuration $configuration,
38
        Results $results,
39
        LoggerInterface $logger
40
    ) {
41 8
        $this->provider      = $provider;
42 8
        $this->configuration = $configuration;
43 8
        $this->lastEvents    = $results;
44 8
        $this->logger        = $logger;
45 8
    }
46
47 2
    public function handleHandshake(Gateway $gateway, Request $request, Response $response): Promise
48
    {
49 2
        if (!$this->configuration->websocketAddressExists($request->getHeader('origin'))) {
0 ignored issues
show
Bug introduced by
It seems like $request->getHeader('origin') can also be of type null; however, parameter $origin of ekinhbayar\GitAmp\Config...ebsocketAddressExists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

49
        if (!$this->configuration->websocketAddressExists(/** @scrutinizer ignore-type */ $request->getHeader('origin'))) {
Loading history...
50 1
            return $gateway->getErrorHandler()->handleError(Status::FORBIDDEN, 'Forbidden Origin', $request);
51
        }
52
53 1
        return new Success($response);
54
    }
55
56 2
    public function handleClient(Gateway $gateway, Client $client, Request $request, Response $response): Promise
57
    {
58 2
        return call(function () use ($gateway, $client, $request, $response) {
0 ignored issues
show
Unused Code introduced by
The import $response is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
Unused Code introduced by
The import $request is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
59 2
            $client->onClose(function (Client $client, int $code, string $reason) use ($gateway) {
60
                yield $this->processDisconnectingClient($gateway, $client, $code, $reason);
61 2
            });
62
63 2
            $this->logger->info(
64 2
                \sprintf('Client %d connected. Total clients: %d', $client->getId(), count($gateway->getClients())),
65
            );
66
67 2
            yield $this->sendConnectedUsersCount(\count($gateway->getClients()));
68
69
            $client->send($this->lastEvents->jsonEncode());
70
71
            yield $client->receive();
72 2
        });
73
    }
74
75
    private function processDisconnectingClient(Gateway $gateway, Client  $client, int $code, string $reason): Promise
76
    {
77
        return call(function () use ($gateway, $client, $code, $reason) {
78
            $this->logger->info(
79
                \sprintf(
80
                    'Client %d disconnected. Code: %d Reason: %s. Total clients: %d',
81
                    $client->getId(),
82
                    $code,
83
                    $reason,
84
                    count($gateway->getClients()),
85
                )
86
            );
87
88
            yield $this->sendConnectedUsersCount(count($gateway->getClients()));
89
        });
90
    }
91
92 4
    private function emit(Results $events): Promise
93
    {
94 4
        if (!$events->hasEvents()) {
95 2
            return new Success();
96
        }
97
98 2
        $this->lastEvents = $events;
99
100 2
        return $this->gateway->broadcast($events->jsonEncode());
101
    }
102
103 2
    private function sendConnectedUsersCount(int $count): Promise
104
    {
105 2
        return $this->gateway->broadcast(\json_encode(['connectedUsers' => $count]));
106
    }
107
108 5
    public function onStart(HttpServer $server, Gateway $gateway): Promise
109
    {
110 5
        $this->gateway = $gateway;
111
112 5
        asyncCall(function () {
113 5
            while (true) {
114 5
                $this->emit(yield $this->provider->listen());
115
116 4
                yield new Delayed(25000);
117
            }
118 5
        });
119
120 5
        return new Success();
121
    }
122
123 1
    public function onStop(HttpServer $server, Gateway $gateway): Promise
124
    {
125 1
        return new Success();
126
    }
127
}
128