Completed
Push — master ( efbfdb...641f39 )
by Irfaq
03:41
created

CommandBus::removeCommands()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4286
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
3
namespace Telegram\Bot\Commands;
4
5
use Telegram\Bot\Api;
6
use Telegram\Bot\Exceptions\TelegramSDKException;
7
use Telegram\Bot\Objects\Update;
8
9
/**
10
 * Class CommandBus.
11
 */
12
class CommandBus
13
{
14
    /**
15
     * @var Command[] Holds all commands.
16
     */
17
    protected $commands = [];
18
19
    /**
20
     * @var Api
21
     */
22
    private $telegram;
23
24
    /**
25
     * Instantiate Command Bus.
26
     *
27
     * @param Api $telegram
28
     *
29
     * @throws TelegramSDKException
30
     */
31 18
    public function __construct(Api $telegram)
32
    {
33 18
        $this->telegram = $telegram;
34 18
    }
35
36
    /**
37
     * Returns the list of commands.
38
     *
39
     * @return array
40
     */
41 8
    public function getCommands()
42
    {
43 8
        return $this->commands;
44
    }
45
46
    /**
47
     * Add a list of commands.
48
     *
49
     * @param array $commands
50
     *
51
     * @return CommandBus
52
     */
53 6
    public function addCommands(array $commands)
54
    {
55 6
        foreach ($commands as $command) {
56 6
            $this->addCommand($command);
57 6
        }
58
59 6
        return $this;
60
    }
61
62
    /**
63
     * Add a command to the commands list.
64
     *
65
     * @param CommandInterface|string $command Either an object or full path to the command class.
66
     *
67
     * @throws TelegramSDKException
68
     *
69
     * @return CommandBus
70
     */
71 14
    public function addCommand($command)
72
    {
73 14
        if (!is_object($command)) {
74 10
            if (!class_exists($command)) {
75 2
                throw new TelegramSDKException(sprintf('Command class "%s" not found! Please make sure the class exists.',
76 2
                    $command));
77
            }
78
79 8
            if ($this->telegram->hasContainer()) {
80
                $command = $this->buildDependencyInjectedCommand($command);
81
            } else {
82 8
                $command = new $command();
83
            }
84 8
        }
85
86 12
        if ($command instanceof CommandInterface) {
87
88
            /*
89
             * At this stage we definitely have a proper command to use.
90
             *
91
             * @var Command $command
92
             */
93 10
            $this->commands[$command->getName()] = $command;
94
95 10
            return $this;
96
        }
97
98 2
        throw new TelegramSDKException(sprintf('Command class "%s" should be an instance of "Telegram\Bot\Commands\CommandInterface"',
99 2
            get_class($command)));
100
    }
101
102
    /**
103
     * Remove a command from the list.
104
     *
105
     * @param $name
106
     */
107 4
    public function removeCommand($name)
108
    {
109 4
        unset($this->commands[$name]);
110 4
    }
111
112
    /**
113
     * Removes a list of commands.
114
     *
115
     * @param array $names
116
     *
117
     * @return CommandBus
118
     */
119 2
    public function removeCommands(array $names)
120
    {
121 2
        foreach ($names as $name) {
122 2
            $this->removeCommand($name);
123 2
        }
124
125 2
        return $this;
126
    }
127
128
    /**
129
     * Handles Inbound Messages and Executes Appropriate Command.
130
     *
131
     * @param $message
132
     * @param $update
133
     *
134
     * @throws TelegramSDKException
135
     *
136
     * @return Update
137
     */
138 4
    public function handler($message, Update $update)
139
    {
140 4
        $match = $this->parseCommand($message);
141 4
        if (!empty($match)) {
142 4
            $command = $match[1];
143
//            $bot = (!empty($match[2])) ? $match[2] : '';
1 ignored issue
show
Unused Code Comprehensibility introduced by
71% 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...
144 4
            $arguments = $match[3];
145 4
            $this->execute($command, $arguments, $update);
146 4
        }
147
148 4
        return $update;
149
    }
150
151
    /**
152
     * Parse a Command for a Match.
153
     *
154
     * @param $text
155
     *
156
     * @throws \InvalidArgumentException
157
     *
158
     * @return array
159
     */
160 4
    public function parseCommand($text)
161
    {
162 4
        if (trim($text) === '') {
163
            throw new \InvalidArgumentException('Message is empty, Cannot parse for command');
164
        }
165
166 4
        preg_match('/^\/([^\s@]+)@?(\S+)?\s?(.*)$/', $text, $matches);
167
168 4
        return $matches;
169
    }
170
171
    /**
172
     * Execute the command.
173
     *
174
     * @param $name
175
     * @param $arguments
176
     * @param $message
177
     *
178
     * @return mixed
179
     */
180 4
    public function execute($name, $arguments, $message)
181
    {
182 4
        if (array_key_exists($name, $this->commands)) {
183 2
            return $this->commands[$name]->make($this->telegram, $arguments, $message);
184 2
        } elseif (array_key_exists('help', $this->commands)) {
185
            return $this->commands['help']->make($this->telegram, $arguments, $message);
186
        }
187
188 2
        return 'Ok';
189
    }
190
191
    /**
192
     * Use PHP Reflection and Laravel Container to instantiate the command with type hinted dependencies.
193
     *
194
     * @param $commandClass
195
     *
196
     * @return object
197
     */
198
    private function buildDependencyInjectedCommand($commandClass)
199
    {
200
201
        // check if the command has a constructor
202
        if (!method_exists($commandClass, '__construct')) {
203
            return new $commandClass();
204
        }
205
206
        // get constructor params
207
        $constructorReflector = new \ReflectionMethod($commandClass, '__construct');
208
        $params = $constructorReflector->getParameters();
209
210
        // if no params are needed proceed with normal instantiation
211
        if (empty($params)) {
212
            return new $commandClass();
213
        }
214
215
        // otherwise fetch each dependency out of the container
216
        $container = $this->telegram->getContainer();
217
        $dependencies = [];
218
        foreach ($params as $param) {
219
            $dependencies[] = $container->make($param->getClass()->name);
220
        }
221
222
        // and instantiate the object with dependencies through ReflectionClass
223
        $classReflector = new \ReflectionClass($commandClass);
224
225
        return $classReflector->newInstanceArgs($dependencies);
226
    }
227
}
228