Completed
Push — master ( e5c732...8e3e30 )
by Ekin
03:31
created

Handler   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Test Coverage

Coverage 68.75%

Importance

Changes 16
Bugs 2 Features 0
Metric Value
eloc 41
dl 0
loc 100
ccs 33
cts 48
cp 0.6875
rs 10
c 16
b 2
f 0
wmc 12

8 Methods

Rating   Name   Duplication   Size   Complexity  
A handleHandshake() 0 7 2
A __construct() 0 5 1
A onStart() 0 13 2
A emit() 0 9 2
A handleClient() 0 18 2
A sendConnectedUsersCount() 0 3 1
A processDisconnectingClient() 0 14 1
A onStop() 0 3 1
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\Provider\Listener;
17
use ekinhbayar\GitAmp\Response\Results;
18
use Psr\Log\LoggerInterface;
19
use function Amp\asyncCall;
20
use function Amp\call;
21
22
class Handler implements ClientHandler, WebsocketServerObserver
23
{
24
    private Gateway $gateway;
25
26
    private string $origin;
27
28
    private Listener $provider;
29
30
    private ?Results $lastEvents = null;
31
32
    private LoggerInterface $logger;
33
34 6
    public function __construct(string $origin, Listener $provider, LoggerInterface $logger)
35
    {
36 6
        $this->origin   = $origin;
37 6
        $this->provider = $provider;
38 6
        $this->logger   = $logger;
39
    }
40
41 2
    public function handleHandshake(Gateway $gateway, Request $request, Response $response): Promise
42
    {
43 2
        if ($request->getHeader('origin') !== $this->origin) {
44 1
            return $gateway->getErrorHandler()->handleError(Status::FORBIDDEN, 'Forbidden Origin', $request);
45
        }
46
47 1
        return new Success($response);
48
    }
49
50 1
    public function handleClient(Gateway $gateway, Client $client, Request $request, Response $response): Promise
51
    {
52 1
        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...
53 1
            $client->onClose(function (Client $client, int $code, string $reason) use ($gateway) {
54
                yield $this->processDisconnectingClient($gateway, $client, $code, $reason);
55 1
            });
56
57 1
            $this->logger->info(
58 1
                \sprintf('Client %d connected. Total clients: %d', $client->getId(), count($gateway->getClients())),
59
            );
60
61 1
            yield $this->sendConnectedUsersCount(\count($gateway->getClients()));
62
63
            if ($this->lastEvents) {
64
                $client->send($this->lastEvents->jsonEncode());
65
            }
66
67
            yield $client->receive();
68 1
        });
69
    }
70
71
    private function processDisconnectingClient(Gateway $gateway, Client  $client, int $code, string $reason): Promise
72
    {
73
        return call(function () use ($gateway, $client, $code, $reason) {
74
            $this->logger->info(
75
                \sprintf(
76
                    'Client %d disconnected. Code: %d Reason: %s. Total clients: %d',
77
                    $client->getId(),
78
                    $code,
79
                    $reason,
80
                    count($gateway->getClients()),
81
                )
82
            );
83
84
            yield $this->sendConnectedUsersCount(count($gateway->getClients()));
85
        });
86
    }
87
88 3
    private function emit(Results $events): Promise
89
    {
90 3
        if (!$events->hasEvents()) {
91 2
            return new Success();
92
        }
93
94 1
        $this->lastEvents = $events;
95
96 1
        return $this->gateway->broadcast($events->jsonEncode());
97
    }
98
99 1
    private function sendConnectedUsersCount(int $count): Promise
100
    {
101 1
        return $this->gateway->broadcast(\json_encode(['connectedUsers' => $count]));
102
    }
103
104 3
    public function onStart(HttpServer $server, Gateway $gateway): Promise
105
    {
106 3
        $this->gateway = $gateway;
107
108 3
        asyncCall(function () {
109 3
            while (true) {
110 3
                $this->emit(yield $this->provider->listen());
111
112 3
                yield new Delayed(25000);
113
            }
114 3
        });
115
116 3
        return new Success();
117
    }
118
119 1
    public function onStop(HttpServer $server, Gateway $gateway): Promise
120
    {
121 1
        return new Success();
122
    }
123
}
124