Completed
Push — master ( e02d88...60454e )
by Irfaq
02:29
created

BotsManager   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 279
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 0%

Importance

Changes 4
Bugs 1 Features 0
Metric Value
wmc 29
c 4
b 1
f 0
lcom 1
cbo 1
dl 0
loc 279
ccs 0
cts 77
cp 0
rs 10

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setContainer() 0 6 1
A getBotConfig() 0 13 4
A bot() 0 10 3
A reconnect() 0 7 2
A disconnect() 0 5 2
A getConfig() 0 4 1
A getDefaultBot() 0 4 1
A setDefaultBot() 0 6 1
A getBots() 0 4 1
A deduplicateArray() 0 4 1
B makeBot() 0 25 3
A parseBotCommands() 0 7 1
B parseCommands() 0 35 6
A __call() 0 4 1
1
<?php
2
3
namespace Telegram\Bot;
4
5
use Illuminate\Contracts\Container\Container;
6
use InvalidArgumentException;
7
8
/**
9
 * Class BotsManager
10
 *
11
 * @TODO Add methods in docblock for autocompletion from Api file.
12
 */
13
class BotsManager
14
{
15
    /**
16
     * The config instance.
17
     *
18
     * @var array
19
     */
20
    protected $config;
21
22
    /**
23
     * The container instance.
24
     *
25
     * @var \Illuminate\Contracts\Container\Container
26
     */
27
    protected $container;
28
29
    /**
30
     * The active bot instances.
31
     *
32
     * @var Api[]
33
     */
34
    protected $bots = [];
35
36
    /**
37
     * TelegramManager constructor.
38
     *
39
     * @param array $config
40
     */
41
    public function __construct($config)
42
    {
43
        $this->config = $config;
44
    }
45
46
    /**
47
     * Set the IoC Container.
48
     *
49
     * @param $container Container instance
50
     *
51
     * @return $this
52
     */
53
    public function setContainer(Container $container)
54
    {
55
        $this->container = $container;
56
57
        return $this;
58
    }
59
60
    /**
61
     * Get the configuration for a bot.
62
     *
63
     * @param string|null $name
64
     *
65
     * @throws \InvalidArgumentException
66
     *
67
     * @return array
68
     */
69
    public function getBotConfig($name = null)
70
    {
71
        $name = $name ?: $this->getDefaultBot();
72
73
        $bots = $this->getConfig('bots');
74
        if (!is_array($config = array_get($bots, $name)) && !$config) {
75
            throw new InvalidArgumentException("Bot [$name] not configured.");
76
        }
77
78
        $config['bot'] = $name;
79
80
        return $config;
81
    }
82
83
    /**
84
     * Get a bot instance.
85
     *
86
     * @param string $name
87
     *
88
     * @return Api
89
     */
90
    public function bot($name = null)
91
    {
92
        $name = $name ?: $this->getDefaultBot();
93
94
        if (!isset($this->bots[$name])) {
95
            $this->bots[$name] = $this->makeBot($name);
96
        }
97
98
        return $this->bots[$name];
99
    }
100
101
    /**
102
     * Reconnect to the given bot.
103
     *
104
     * @param string $name
105
     *
106
     * @return Api
107
     */
108
    public function reconnect($name = null)
109
    {
110
        $name = $name ?: $this->getDefaultBot();
111
        $this->disconnect($name);
112
113
        return $this->bot($name);
114
    }
115
116
    /**
117
     * Disconnect from the given bot.
118
     *
119
     * @param string $name
120
     *
121
     * @return void
122
     */
123
    public function disconnect($name = null)
124
    {
125
        $name = $name ?: $this->getDefaultBot();
126
        unset($this->bots[$name]);
127
    }
128
129
    /**
130
     * Get the specified configuration value for Telegram.
131
     *
132
     * @param  string $key
133
     * @param  mixed  $default
134
     *
135
     * @return mixed
136
     */
137
    public function getConfig($key, $default = null)
138
    {
139
        return array_get($this->config, $key, $default);
140
    }
141
142
    /**
143
     * Get the default bot name.
144
     *
145
     * @return string
146
     */
147
    public function getDefaultBot()
148
    {
149
        return $this->getConfig('default');
150
    }
151
152
    /**
153
     * Set the default bot name.
154
     *
155
     * @param string $name
156
     *
157
     * @return $this
158
     */
159
    public function setDefaultBot($name)
160
    {
161
        array_set($this->config, 'default', $name);
162
163
        return $this;
164
    }
165
166
    /**
167
     * Return all of the created bots.
168
     *
169
     * @return Api[]
170
     */
171
    public function getBots()
172
    {
173
        return $this->bots;
174
    }
175
176
    /**
177
     * De-duplicate an array.
178
     *
179
     * @param array $array
180
     *
181
     * @return array
182
     */
183
    protected function deduplicateArray(array $array)
184
    {
185
        return array_values(array_unique($array));
186
    }
187
188
    /**
189
     * Make the bot instance.
190
     *
191
     * @param string $name
192
     *
193
     * @return Api
194
     */
195
    protected function makeBot($name)
196
    {
197
        $config = $this->getBotConfig($name);
198
199
        $token = array_get($config, 'token');
200
        $commands = array_get($config, 'commands', []);
201
202
        $telegram = new Api(
203
            $token,
204
            $this->getConfig('async_requests', false),
205
            $this->getConfig('http_client_handler', null)
206
        );
207
208
        // Check if DI needs to be enabled for Commands
209
        if ($this->getConfig('resolve_command_dependencies', false) && isset($this->container)) {
210
            $telegram->setContainer($this->container);
211
        }
212
213
        $commands = $this->parseBotCommands($commands);
214
215
        // Register Commands
216
        $telegram->addCommands($commands);
0 ignored issues
show
Documentation Bug introduced by
The method addCommands does not exist on object<Telegram\Bot\Api>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
217
218
        return $telegram;
219
    }
220
221
    /**
222
     * Builds the list of commands for the given commands array.
223
     *
224
     * @param array $commands
225
     *
226
     * @return array An array of commands which includes global and bot specific commands.
227
     */
228
    protected function parseBotCommands(array $commands)
229
    {
230
        $globalCommands = $this->getConfig('commands', []);
231
        $parsedCommands = $this->parseCommands($commands);
232
233
        return $this->deduplicateArray(array_merge($globalCommands, $parsedCommands));
234
    }
235
236
    /**
237
     * Parse an array of commands and build a list.
238
     *
239
     * @param array $commands
240
     *
241
     * @return array
242
     */
243
    protected function parseCommands(array $commands)
244
    {
245
        if (!is_array($commands)) {
246
            return $commands;
247
        }
248
249
        $commandGroups = $this->getConfig('command_groups');
250
        $sharedCommands = $this->getConfig('shared_commands');
251
252
        $results = [];
253
        foreach ($commands as $command) {
254
            // If the command is a group, we'll parse through the group of commands
255
            // and resolve the full class name.
256
            if (isset($commandGroups[$command])) {
257
                $results = array_merge(
258
                    $results, $this->parseCommands($commandGroups[$command])
259
                );
260
261
                continue;
262
263
            }
264
265
            // If this command is actually a shared command, we'll extract the full
266
            // class name out of the command list now.
267
            if (isset($sharedCommands[$command])) {
268
                $command = $sharedCommands[$command];
269
            }
270
271
            if (!in_array($command, $results)) {
272
                $results[] = $command;
273
            }
274
        }
275
276
        return $results;
277
    }
278
279
    /**
280
     * Magically pass methods to the default bot.
281
     *
282
     * @param string $method
283
     * @param array  $parameters
284
     *
285
     * @return mixed
286
     */
287
    public function __call($method, $parameters)
288
    {
289
        return call_user_func_array([$this->bot(), $method], $parameters);
290
    }
291
}
292