Passed
Push — master ( e3547c...5fc327 )
by Gusev
01:17
created

Client::callbackQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
namespace TelegramBot\Api;
4
5
use Closure;
6
use ReflectionFunction;
7
use TelegramBot\Api\Events\EventCollection;
8
use TelegramBot\Api\Types\Update;
9
10
/**
11
 * Class Client
12
 *
13
 * @package TelegramBot\Api
14
 */
15
class Client
16
{
17
    /**
18
     * RegExp for bot commands
19
     */
20
    const REGEXP = '/^(?:@\w+\s)?\/([^\s@]+)(@\S+)?\s?(.*)$/';
21
22
    /**
23
     * @var \TelegramBot\Api\BotApi
24
     */
25
    protected $api;
26
27
    /**
28
     * @var \TelegramBot\Api\Events\EventCollection
29
     */
30
    protected $events;
31
32
    /**
33
     * Client constructor
34
     *
35
     * @param string $token Telegram Bot API token
36
     * @param string|null $trackerToken Yandex AppMetrica application api_key
37
     */
38 7
    public function __construct($token, $trackerToken = null)
39
    {
40 7
        $this->api = new BotApi($token);
41 7
        $this->events = new EventCollection($trackerToken);
42 7
    }
43
44
    /**
45
     * Use this method to add command. Parameters will be automatically parsed and passed to closure.
46
     *
47
     * @param string $name
48
     * @param \Closure $action
49
     *
50
     * @return \TelegramBot\Api\Client
51
     */
52
    public function command($name, Closure $action)
53
    {
54
        return $this->on(self::getEvent($action), self::getChecker($name));
55
    }
56
57
    public function editedMessage(Closure $action)
58
    {
59
        return $this->on(self::getEditedMessageEvent($action), self::getEditedMessageChecker());
60
    }
61
62
    public function callbackQuery(Closure $action)
63
    {
64
        return $this->on(self::getCallbackQueryEvent($action), self::getCallbackQueryChecker());
65
    }
66
67
    public function channelPost(Closure $action)
68
    {
69
        return $this->on(self::getChannelPostEvent($action), self::getChannelPostChecker());
70
    }
71
72
    public function editedChannelPost(Closure $action)
73
    {
74
        return $this->on(self::getEditedChannelPostEvent($action), self::getEditedChannelPostChecker());
75
    }
76
77
    public function inlineQuery(Closure $action)
78
    {
79
        return $this->on(self::getInlineQueryEvent($action), self::getInlineQueryChecker());
80
    }
81
82
    public function chosenInlineResult(Closure $action)
83
    {
84
        return $this->on(self::getChosenInlineResultEvent($action), self::getChosenInlineResultChecker());
85
    }
86
87
    public function shippingQuery(Closure $action)
88
    {
89
        return $this->on(self::getShippingQueryEvent($action), self::getShippingQueryChecker());
90
    }
91
92
    public function preCheckoutQuery(Closure $action)
93
    {
94
        return $this->on(self::getPreCheckoutQueryEvent($action), self::getPreCheckoutQueryChecker());
95
    }
96
97
    /**
98
     * Use this method to add an event.
99
     * If second closure will return true (or if you are passed null instead of closure), first one will be executed.
100
     *
101
     * @param \Closure $event
102
     * @param \Closure|null $checker
103
     *
104
     * @return \TelegramBot\Api\Client
105
     */
106 1
    public function on(Closure $event, Closure $checker = null)
107
    {
108 1
        $this->events->add($event, $checker);
109
110 1
        return $this;
111
    }
112
113
    /**
114
     * Handle updates
115
     *
116
     * @param Update[] $updates
117
     */
118 4
    public function handle(array $updates)
119
    {
120 4
        foreach ($updates as $update) {
121
            /* @var \TelegramBot\Api\Types\Update $update */
122 4
            $this->events->handle($update);
123 4
        }
124 4
    }
125
126
    /**
127
     * Webhook handler
128
     *
129
     * @return array
130
     * @throws \TelegramBot\Api\InvalidJsonException
131
     */
132
    public function run()
133
    {
134
        if ($data = BotApi::jsonValidate($this->getRawBody(), true)) {
135
            $this->handle([Update::fromResponse($data)]);
136
        }
137
    }
138
139
    public function getRawBody()
140
    {
141
        return file_get_contents('php://input');
142
    }
143
144
    /**
145
     * Returns event function to handling the command.
146
     *
147
     * @param \Closure $action
148
     *
149
     * @return \Closure
150
     */
151 4
    protected static function getEvent(Closure $action)
152
    {
153
        return function (Update $update) use ($action) {
154 4
            $message = $update->getMessage();
155 4
            if (!$message) {
156 1
                return true;
157
            }
158
159 3
            preg_match(self::REGEXP, $message->getText(), $matches);
160
161 3
            if (isset($matches[3]) && !empty($matches[3])) {
162 1
                $parameters = str_getcsv($matches[3], chr(32));
163 1
            } else {
164 2
                $parameters = [];
165
            }
166
167 3
            array_unshift($parameters, $message);
168
169 3
            $action = new ReflectionFunction($action);
170
171 3
            if (count($parameters) >= $action->getNumberOfRequiredParameters()) {
172 3
                $action->invokeArgs($parameters);
173 3
            }
174
175 3
            return false;
176 4
        };
177
    }
178
179 View Code Duplication
    protected static function getEditedMessageEvent(Closure $action)
180
    {
181
        return function (Update $update) use ($action) {
182
            if (!$update->getEditedMessage()) {
183
                return true;
184
            }
185
186
            $reflectionAction = new ReflectionFunction($action);
187
            $reflectionAction->invokeArgs([$update->getEditedMessage()]);
188
            return false;
189
        };
190
    }
191
192 View Code Duplication
    protected static function getChannelPostEvent(Closure $action)
193
    {
194
        return function (Update $update) use ($action) {
195
            if (!$update->getChannelPost()) {
196
                return true;
197
            }
198
199
            $reflectionAction = new ReflectionFunction($action);
200
            $reflectionAction->invokeArgs([$update->getChannelPost()]);
201
            return false;
202
        };
203
    }
204
205 View Code Duplication
    protected static function getCallbackQueryEvent(Closure $action)
206
    {
207
        return function (Update $update) use ($action) {
208
            if (!$update->getCallbackQuery()) {
209
                return true;
210
            }
211
212
            $reflectionAction = new ReflectionFunction($action);
213
            $reflectionAction->invokeArgs([$update->getCallbackQuery()]);
214
            return false;
215
        };
216
    }
217
218 View Code Duplication
    protected static function getEditedChannelPostEvent(Closure $action)
219
    {
220
        return function (Update $update) use ($action) {
221
            if (!$update->getEditedChannelPost()) {
222
                return true;
223
            }
224
225
            $reflectionAction = new ReflectionFunction($action);
226
            $reflectionAction->invokeArgs([$update->getEditedChannelPost()]);
227
            return false;
228
        };
229
    }
230
231 4 View Code Duplication
    protected static function getInlineQueryEvent(Closure $action)
232
    {
233
        return function (Update $update) use ($action) {
234 4
            if (!$update->getInlineQuery()) {
235 3
                return true;
236
            }
237
238 1
            $reflectionAction = new ReflectionFunction($action);
239 1
            $reflectionAction->invokeArgs([$update->getInlineQuery()]);
240 1
            return false;
241 4
        };
242
    }
243
244 View Code Duplication
    protected static function getChosenInlineResultEvent(Closure $action)
245
    {
246
        return function (Update $update) use ($action) {
247
            if (!$update->getChosenInlineResult()) {
248
                return true;
249
            }
250
251
            $reflectionAction = new ReflectionFunction($action);
252
            $reflectionAction->invokeArgs([$update->getChosenInlineResult()]);
253
            return false;
254
        };
255
    }
256
257 View Code Duplication
    protected static function getShippingQueryEvent(Closure $action)
258
    {
259
        return function (Update $update) use ($action) {
260
            if (!$update->getShippingQuery()) {
261
                return true;
262
            }
263
264
            $reflectionAction = new ReflectionFunction($action);
265
            $reflectionAction->invokeArgs([$update->getShippingQuery()]);
266
            return false;
267
        };
268
    }
269
270 View Code Duplication
    protected static function getPreCheckoutQueryEvent(Closure $action)
271
    {
272
        return function (Update $update) use ($action) {
273
            if (!$update->getPreCheckoutQuery()) {
274
                return true;
275
            }
276
277
            $reflectionAction = new ReflectionFunction($action);
278
            $reflectionAction->invokeArgs([$update->getPreCheckoutQuery()]);
279
            return false;
280
        };
281
    }
282
283
    /**
284
     * Returns check function to handling the command.
285
     *
286
     * @param string $name
287
     *
288
     * @return \Closure
289
     */
290 4
    protected static function getChecker($name)
291
    {
292
        return function (Update $update) use ($name) {
293 4
            $message = $update->getMessage();
294 4
            if (is_null($message) || !strlen($message->getText())) {
295 1
                return false;
296
            }
297
298 3
            preg_match(self::REGEXP, $message->getText(), $matches);
299
300 3
            return !empty($matches) && $matches[1] == $name;
301 4
        };
302
    }
303
304
    /**
305
     * Returns check function to handling the edited message.
306
     *
307
     * @return Closure
308
     */
309
    protected static function getEditedMessageChecker()
310
    {
311
        return function (Update $update) {
312
            return !is_null($update->getEditedMessage());
313
        };
314
    }
315
316
    /**
317
     * Returns check function to handling the channel post.
318
     *
319
     * @return Closure
320
     */
321
    protected static function getChannelPostChecker()
322
    {
323
        return function (Update $update) {
324
            return !is_null($update->getChannelPost());
325
        };
326
    }
327
328
    /**
329
     * Returns check function to handling the callbackQuery.
330
     *
331
     * @return Closure
332
     */
333
    protected static function getCallbackQueryChecker()
334
    {
335
        return function (Update $update) {
336
            return !is_null($update->getCallbackQuery());
337
        };
338
    }
339
340
    /**
341
     * Returns check function to handling the edited channel post.
342
     *
343
     * @return Closure
344
     */
345
    protected static function getEditedChannelPostChecker()
346
    {
347
        return function (Update $update) {
348
            return !is_null($update->getEditedChannelPost());
349
        };
350
    }
351
352
    /**
353
     * Returns check function to handling the chosen inline result.
354
     *
355
     * @return Closure
356
     */
357
    protected static function getChosenInlineResultChecker()
358
    {
359
        return function (Update $update) {
360
            return !is_null($update->getChosenInlineResult());
361
        };
362
    }
363
364
    /**
365
     * Returns check function to handling the inline queries.
366
     *
367
     * @return Closure
368
     */
369 4
    protected static function getInlineQueryChecker()
370
    {
371
        return function (Update $update) {
372 4
            return !is_null($update->getInlineQuery());
373 4
        };
374
    }
375
376
    /**
377
     * Returns check function to handling the shipping queries.
378
     *
379
     * @return Closure
380
     */
381
    protected static function getShippingQueryChecker()
382
    {
383
        return function (Update $update) {
384
            return !is_null($update->getShippingQuery());
385
        };
386
    }
387
388
    /**
389
     * Returns check function to handling the pre checkout queries.
390
     *
391
     * @return Closure
392
     */
393
    protected static function getPreCheckoutQueryChecker()
394
    {
395
        return function (Update $update) {
396
            return !is_null($update->getPreCheckoutQuery());
397
        };
398
    }
399
400 1
    public function __call($name, array $arguments)
401
    {
402 1
        if (method_exists($this, $name)) {
403
            return call_user_func_array([$this, $name], $arguments);
404 1
        } elseif (method_exists($this->api, $name)) {
405
            return call_user_func_array([$this->api, $name], $arguments);
406
        }
407 1
        throw new BadMethodCallException("Method {$name} not exists");
408
    }
409
}
410