Completed
Push — master ( 3a5ae7...d35303 )
by Irfaq
08:47 queued 06:10
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\Objects\Update;
8
use Telegram\Bot\Exceptions\TelegramSDKException;
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
        if (!is_object($command)) {
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
     * Remove a command from the list.
139
     *
140
     * @param $name
141
     *
142
     * @return CommandBus
143
     */
144 4
    public function removeCommand($name)
145
    {
146 4
        unset($this->commands[$name]);
147
148 4
        return $this;
149
    }
150
151
    /**
152
     * Removes a list of commands.
153
     *
154
     * @param array $names
155
     *
156
     * @return CommandBus
157
     */
158 2
    public function removeCommands(array $names)
159
    {
160 2
        foreach ($names as $name) {
161 2
            $this->removeCommand($name);
162 2
        }
163
164 2
        return $this;
165
    }
166
167
    /**
168
     * Parse a Command for a Match.
169
     *
170
     * @param $text
171
     *
172
     * @throws \InvalidArgumentException
173
     *
174
     * @return array
175
     */
176 16
    public function parseCommand($text)
177
    {
178 16
        if (trim($text) === '') {
179 2
            throw new \InvalidArgumentException('Message is empty, Cannot parse for command');
180
        }
181
182 14
        preg_match('/^\/([^\s@]+)@?(\S+)?\s?(.*)$/', $text, $matches);
183
184 14
        return $matches;
185
    }
186
187
    /**
188
     * Handles Inbound Messages and Executes Appropriate Command.
189
     *
190
     * @param $message
191
     * @param $update
192
     *
193
     * @throws TelegramSDKException
194
     *
195
     * @return Update
196
     */
197 8
    protected function handler($message, Update $update)
198
    {
199 8
        $match = $this->parseCommand($message);
200 8
        if (!empty($match)) {
201 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...
202
//            $bot = (!empty($match[2])) ? $match[2] : '';
203 8
            $arguments = $match[3];
204
205 8
            $this->execute($command, $arguments, $update);
206 8
        }
207
208 8
        return $update;
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