ChatCommandsProcessor::addCommand()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 4
c 2
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
1
<?php
2
declare(strict_types=1);
3
4
namespace HeroesofAbenez\Chat;
5
6
/**
7
 * ChatCommandsProcessor
8
 *
9
 * @author Jakub Konečný
10
 */
11 1
final class ChatCommandsProcessor implements ChatMessageProcessor
12
{
13
    /** @var IChatCommand[] */
14
    private array $commands = [];
15
16
    /**
17
     * Add new command
18
     *
19
     * @throws CommandNameAlreadyUsedException
20
     */
21
    public function addCommand(IChatCommand $command): void
22
    {
23 1
        $name = $command->getName();
24 1
        if ($this->hasCommand($name)) {
25 1
            throw new CommandNameAlreadyUsedException("Command $name is already defined.");
26
        }
27 1
        $this->commands[] = $command;
28 1
    }
29
30
    /**
31
     * Add an alias for already defined command
32
     *
33
     * @throws CommandNotFoundException
34
     * @throws CommandNameAlreadyUsedException
35
     */
36
    public function addAlias(string $oldName, string $newName): void
37
    {
38 1
        $command = $this->getCommand($oldName);
39 1
        $new = clone $command;
40 1
        $new->setName($newName);
41 1
        $this->addCommand($new);
42 1
    }
43
44
    /**
45
     * Extract command from text
46
     */
47
    public function extractCommand(string $text): string
48
    {
49 1
        if (!str_starts_with($text, "/")) {
50 1
            return "";
51
        }
52 1
        if (!str_contains($text, " ")) {
53 1
            $command = substr($text, 1);
54
        } else {
55 1
            $parts = explode(" ", substr($text, 1));
56 1
            $command = $parts[0];
57
        }
58 1
        if ($this->hasCommand($command)) {
59 1
            return $command;
60
        }
61 1
        return "";
62
    }
63
64
65
    /**
66
     * Extract parameters from text
67
     */
68
    public function extractParameters(string $text): array
69
    {
70 1
        if (!str_starts_with($text, "/") || !str_contains($text, " ")) {
71 1
            return [];
72
        }
73 1
        $params = explode(" ", $text);
74 1
        unset($params[0]);
75 1
        return $params;
76
    }
77
78
    /**
79
     * Check whether a command is defined
80
     */
81
    public function hasCommand(string $name): bool
82
    {
83 1
        foreach ($this->commands as $command) {
84 1
            if ($command->getName() === $name) {
85 1
                return true;
86
            }
87
        }
88 1
        return false;
89
    }
90
91
    /**
92
     * Get command's definition
93
     *
94
     * @throws CommandNotFoundException
95
     */
96
    public function getCommand(string $name): IChatCommand
97
    {
98 1
        foreach ($this->commands as $command) {
99 1
            if ($command->getName() === $name) {
100 1
                return $command;
101
            }
102
        }
103 1
        throw new CommandNotFoundException("Command $name is not defined.");
104
    }
105
106
    public function parse(string $message): ?string
107
    {
108 1
        $commandName = $this->extractCommand($message);
109 1
        if ($commandName === "") {
110 1
            return null;
111
        }
112 1
        $command = $this->getCommand($commandName);
113 1
        $params = $this->extractParameters($message);
114 1
        return call_user_func_array([$command, "execute"], $params);
115
    }
116
}
117