Lines 93.33% 14 / 15
Functions and Methods 66.66% 2 / 3
Classes and Traits 0.00% 0 / 1
Name Lines Functions and Methods CRAP Classes and Traits
PlayerEnteredEvent 93.33% 14 / 15 66.66% 2 / 3 8.02 0.00% 0 / 1
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 from 100.00% 13 / 13 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\Player;
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 Lorekeeper\Server\SocketId;
15use Override;
16use Psl\Option;
17use Psl\Type;
18use Psl\Type\Exception\CoercionException;
19
20final readonly class PlayerEnteredEvent implements Event
21{
22    use NamedAfterClass;
23
24    public function __construct(
25        public SocketId $socketId,
26        public PlayerName $name,
27    ) {}
28
29    /** @return Option\Option<static> */
30    #[Override]
31    public static function from(Message $message): Option\Option
32    {
33        if (!$message instanceof XmlMessage) {
34            return Option\none();
35        }
36
37        $body = $message->dom->getElementsByTagName('body')->item(0);
38        if (!$body instanceof DOMElement || $body->getAttribute('action') !== 'uER') {
39            return Option\none();
40        }
41
42        $user = $body->getElementsByTagName('u')->item(0);
43        if (!$user instanceof DOMElement) {
44            throw new MalformedEventException(static::class, 'the player is missing');
45        }
46
47        try {
48            $socketId = Type\positive_int()->coerce($user->getAttribute('i'));
49            $name = Type\non_empty_string()->coerce($user->getElementsByTagName('n')->item(0)?->textContent);
50        } catch (CoercionException $exception) {
51            throw new MalformedEventException(static::class, 'player socket or name is missing or invalid', $exception);
52        }
53
54        return Option\some(new static(new SocketId($socketId), new PlayerName($name)));
55    }
56
57    #[Override]
58    public function summary(): string
59    {
60        return "{$this->name->value} (socket {$this->socketId->value}) entered";
61    }
62}