Lines 92.85% 13 / 14
Functions and Methods 66.66% 2 / 3
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
RoomJoinedEvent 92.85% 13 / 14 66.66% 2 / 3 8.02 0.00% 0 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 from 100.00% 12 / 12 100.00% 1 / 1 6
 summary 0.00% 0 / 1 0.00% 0 / 1 2
1<?php
2
3declare(strict_types=1);
4
5namespace Lorekeeper\Server\Event\Map;
6
7use DOMElement;
8use Lorekeeper\Core\Player\PlayerName;
9use Lorekeeper\Server\Event\Event;
10use Lorekeeper\Server\Event\NamedAfterClass;
11use Lorekeeper\Server\Exception\MalformedEventException;
12use Lorekeeper\Server\Message\Message;
13use Lorekeeper\Server\Message\XmlMessage;
14use Override;
15use Psl\Option;
16use Psl\Type;
17use Psl\Type\Exception\CoercionException;
18
19final readonly class RoomJoinedEvent implements Event
20{
21    use NamedAfterClass;
22
23    /** @param list<PlayerName> $players */
24    public function __construct(
25        public array $players,
26    ) {}
27
28    /** @return Option\Option<static> */
29    #[Override]
30    public static function from(Message $message): Option\Option
31    {
32        if (!$message instanceof XmlMessage) {
33            return Option\none();
34        }
35
36        $body = $message->dom->getElementsByTagName('body')->item(0);
37        if (!$body instanceof DOMElement || $body->getAttribute('action') !== 'joinOK') {
38            return Option\none();
39        }
40
41        $players = [];
42        foreach ($body->getElementsByTagName('u') as $user) {
43            try {
44                $name = Type\non_empty_string()->coerce($user->getElementsByTagName('n')->item(0)?->textContent);
45            } catch (CoercionException $exception) {
46                throw new MalformedEventException(static::class, 'a player name is missing or invalid', $exception);
47            }
48
49            $players[] = new PlayerName($name);
50        }
51
52        return Option\some(new static($players));
53    }
54
55    #[Override]
56    public function summary(): string
57    {
58        return 'Joined a room with ' . count($this->players) . ' players';
59    }
60}