Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.33% covered (success)
93.33%
28 / 30
50.00% covered (danger)
50.00%
2 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
AbstractClient
93.33% covered (success)
93.33%
28 / 30
50.00% covered (danger)
50.00%
2 / 4
17.09
0.00% covered (danger)
0.00%
0 / 1
 context
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 run
94.44% covered (success)
94.44%
17 / 18
0.00% covered (danger)
0.00%
0 / 1
10.02
 processMessage
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 resolveEvents
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace AqwSocketClient\Clients;
6
7use AqwSocketClient\Interfaces\ClientInterface;
8use AqwSocketClient\Interfaces\CommandInterface;
9use AqwSocketClient\Interfaces\EventInterface;
10use AqwSocketClient\Interfaces\ExpirableScriptInterface;
11use AqwSocketClient\Interfaces\MessageInterface;
12use AqwSocketClient\Interfaces\ScriptInterface;
13use AqwSocketClient\Scripts\ClientContext;
14use Override;
15use Psl\DataStructure\Queue;
16
17abstract class AbstractClient implements ClientInterface
18{
19    private ?ClientContext $lastContext = null;
20
21    #[Override]
22    public function context(): ?ClientContext
23    {
24        return $this->lastContext;
25    }
26
27    #[Override]
28    public function run(ScriptInterface $script): void
29    {
30        /** @var Queue<CommandInterface> $queue */
31        $queue = new Queue();
32        $context = new ClientContext();
33        $this->lastContext = $context;
34
35        $initial = $script->start($context);
36
37        if ($initial !== null) {
38            $queue->enqueue($initial);
39        }
40
41        while ($this->isConnected() && !$script->isDone()) {
42            if ($script instanceof ExpirableScriptInterface && $script->isExpired()) {
43                $script->expired();
44                break;
45            }
46
47            if ($queue->count() > 0) {
48                $this->send($queue->dequeue()->pack());
49            }
50
51            foreach ($this->receive() as $message) {
52                $command = $this->processMessage($script, $message, $context);
53
54                if ($command !== null) {
55                    $queue->enqueue($command);
56                }
57            }
58        }
59
60        if (!$this->isConnected()) {
61            $script->disconnected();
62        }
63    }
64
65    private function processMessage(
66        ScriptInterface $script,
67        MessageInterface $message,
68        ClientContext $context,
69    ): ?CommandInterface {
70        foreach ($this->resolveEvents($script, $message) as $event) {
71            $command = $script->handle($event, $context);
72
73            if ($command !== null) {
74                return $command;
75            }
76        }
77
78        return null;
79    }
80
81    /**
82     * @return EventInterface[]
83     */
84    private function resolveEvents(ScriptInterface $script, MessageInterface $message): array
85    {
86        $events = [];
87
88        foreach ($script->handles() as $eventClass) {
89            // @mago-expect analyzer:possibly-static-access-on-interface
90            $event = $eventClass::from($message);
91            /** @var null|EventInterface */
92            if ($event !== null) {
93                $events[] = $event;
94            }
95        }
96
97        return $events;
98    }
99}