Completed
Pull Request — master (#171)
by
unknown
02:33
created

CommandBus::__call()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 8
ccs 3
cts 4
cp 0.75
rs 9.4285
cc 2
eloc 4
nc 2
nop 2
crap 2.0625
1
<?php
2
3
namespace Telegram\Bot\Commands;
4
5
use Telegram\Bot\Answers\AnswerBus;
6
use Telegram\Bot\Api;
7
use Telegram\Bot\Exceptions\TelegramSDKException;
8
use Telegram\Bot\Objects\Update;
9
10
/**
11
 * Class CommandBus.
12
 */
13
class CommandBus extends AnswerBus
14
{
15
    /**
16
     * @var Command[] Holds all commands.
17
     */
18
    protected $commands = [];
19
20
    /**
21
     * @var Command[] Holds all commands' aliases.
22
     */
23
    protected $commandAliases = [];
24
25
    /**
26
     * Instantiate Command Bus.
27
     *
28
     * @param Api $telegram
29
     *
30
     * @throws TelegramSDKException
31
     */
32 94
    public function __construct(Api $telegram)
33
    {
34 94
        $this->telegram = $telegram;
35 94
    }
36
37
    /**
38
     * Returns the list of commands.
39
     *
40
     * @return array
41
     */
42 10
    public function getCommands()
43
    {
44 10
        return $this->commands;
45
    }
46
47
    /**
48
     * Add a list of commands.
49
     *
50
     * @param array $commands
51
     *
52
     * @return CommandBus
53
     */
54 8
    public function addCommands(array $commands)
55
    {
56 8
        foreach ($commands as $command) {
57 8
            $this->addCommand($command);
58 8
        }
59
60 8
        return $this;
61
    }
62
63
    /**
64
     * Add a command to the commands list.
65
     *
66
     * @param CommandInterface|string $command Either an object or full path to the command class.
67
     *
68
     * @throws TelegramSDKException
69
     *
70
     * @return CommandBus
71
     */
72 20
    public function addCommand($command)
73
    {
74 20 View Code Duplication
        if (!is_object($command)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
75 12
            if (!class_exists($command)) {
76 2
                throw new TelegramSDKException(
77 2
                    sprintf(
78 2
                        'Command class "%s" not found! Please make sure the class exists.',
79
                        $command
80 2
                    )
81 2
                );
82
            }
83
84 10
            if ($this->telegram->hasContainer()) {
85 2
                $command = $this->buildDependencyInjectedAnswer($command);
86 2
            } else {
87 8
                $command = new $command();
88
            }
89 10
        }
90
91 18
        if ($command instanceof CommandInterface) {
92
93
            /*
94
             * At this stage we definitely have a proper command to use.
95
             *
96
             * @var Command $command
97
      *       */
98 16
            $this->commands[$command->getName()] = $command;
99
100 16
            $aliases = $command->getAliases();
101
102 16
            if (empty($aliases)) {
103 16
                return $this;
104
            }
105
106
            foreach ($command->getAliases() as $alias) {
107 View Code Duplication
                if (isset($this->commands[$alias])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
108
                    throw new TelegramSDKException(sprintf(
109
                        '[Error] Alias [%s] conflicts with command name of "%s" try with another name or remove this alias from the list.',
110
                        $alias,
111
                        get_class($command)
112
                    ));
113
                }
114
115 View Code Duplication
                if (isset($this->commandAliases[$alias])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
116
                    throw new TelegramSDKException(sprintf(
117
                        '[Error] Alias [%s] conflicts with another command\'s alias list: "%s", try with another name or remove this alias from the list.',
118
                        $alias,
119
                        get_class($command)
120
                    ));
121
                }
122
123
                $this->commandAliases[$alias] = $command;
124
            }
125
126
            return $this;
127
        }
128
129 2
        throw new TelegramSDKException(
130 2
            sprintf(
131 2
                'Command class "%s" should be an instance of "Telegram\Bot\Commands\CommandInterface"',
132 2
                get_class($command)
133 2
            )
134 2
        );
135
    }
136
137
    /**
138
     * Removes a list of commands.
139
     *
140
     * @param array $names
141
     *
142
     * @return CommandBus
143
     */
144 2
    public function removeCommands(array $names)
145
    {
146 2
        foreach ($names as $name) {
147 2
            $this->removeCommand($name);
148 2
        }
149
150 2
        return $this;
151
    }
152
153
    /**
154
     * Remove a command from the list.
155
     *
156
     * @param $name
157
     *
158
     * @return CommandBus
159
     */
160 4
    public function removeCommand($name)
161
    {
162 4
        unset($this->commands[$name]);
163
164 4
        return $this;
165
    }
166
167
    /**
168
     * Handles Inbound Messages and Executes Appropriate Command.
169
     *
170
     * @param $message
171
     * @param $update
172
     *
173
     * @throws TelegramSDKException
174
     *
175
     * @return Update
176
     */
177 8
    protected function handler($message, Update $update)
178
    {
179 8
        $match = $this->parseCommand($message);
180 8
        if (!empty($match)) {
181 8
            $command = strtolower($match[1]); //All commands must be lowercase.
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
182
//            $bot = (!empty($match[2])) ? $match[2] : '';
183 8
            $arguments = $match[3];
184
185 8
            $this->execute($command, $arguments, $update);
186 8
        }
187
188 8
        return $update;
189
    }
190
191
    /**
192
     * Parse a Command for a Match.
193
     *
194
     * @param $text
195
     *
196
     * @throws \InvalidArgumentException
197
     *
198
     * @return array
199
     */
200 16
    public function parseCommand($text)
201
    {
202 16
        if (trim($text) === '') {
203 2
            throw new \InvalidArgumentException('Message is empty, Cannot parse for command');
204
        }
205
206 14
        preg_match('/^\/([^\s@]+)@?(\S+)?\s?(.*)$/', $text, $matches);
207
208 14
        return $matches;
209
    }
210
211
    /**
212
     * Execute the command.
213
     *
214
     * @param $name
215
     * @param $arguments
216
     * @param $message
217
     *
218
     * @return mixed
219
     */
220 10
    protected function execute($name, $arguments, $message)
221
    {
222 10
        if (array_key_exists($name, $this->commands)) {
223 6
            return $this->commands[$name]->make($this->telegram, $arguments, $message);
224 4
        } elseif (array_key_exists($name, $this->commandAliases)) {
225
            return $this->commandAliases[$name]->make($this->telegram, $arguments, $message);
226 4
        } elseif (array_key_exists('help', $this->commands)) {
227
            return $this->commands['help']->make($this->telegram, $arguments, $message);
228
        }
229
230 4
        return 'Ok';
231
    }
232
}
233