Completed
Pull Request — master (#100)
by
unknown
08:03
created

Client::getInlineQueryEvent()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 12
Ratio 100 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
dl 12
loc 12
ccs 7
cts 7
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
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
     * @return int Max Update Id
119
     */
120 4
    public function handle(array $updates)
121
    {
122 4
        $maxId = 0;
123
        
124 4
        foreach ($updates as $update) {
125
            /* @var \TelegramBot\Api\Types\Update $update */
126 4
            $this->events->handle($update);
127
            
128 4
            $id = $update->getUpdateId();
129 4
            $maxId = ($id > $maxId)? $id : $maxId;
130 4
        }
131
        
132 4
        return $maxId;
133
    }
134
135
    /**
136
     * Webhook handler
137
     *
138
     * @return array
139
     * @throws \TelegramBot\Api\InvalidJsonException
140
     */
141
    public function run()
142
    {
143
        if ($data = BotApi::jsonValidate($this->getRawBody(), true)) {
144
            $this->handle([Update::fromResponse($data)]);
145
        }
146
    }
147
148
    public function getRawBody()
149
    {
150
        return file_get_contents('php://input');
151
    }
152
153
    /**
154
     * Returns event function to handling the command.
155
     *
156
     * @param \Closure $action
157
     *
158
     * @return \Closure
159
     */
160 4
    protected static function getEvent(Closure $action)
161
    {
162
        return function (Update $update) use ($action) {
163 4
            $message = $update->getMessage();
164 4
            if (!$message) {
165 1
                return true;
166
            }
167
168 3
            preg_match(self::REGEXP, $message->getText(), $matches);
169
170 3
            if (isset($matches[3]) && !empty($matches[3])) {
171 1
                $parameters = str_getcsv($matches[3], chr(32));
172 1
            } else {
173 2
                $parameters = [];
174
            }
175
176 3
            array_unshift($parameters, $message);
177
178 3
            $action = new ReflectionFunction($action);
179
180 3
            if (count($parameters) >= $action->getNumberOfRequiredParameters()) {
181 3
                $action->invokeArgs($parameters);
182 3
            }
183
184 3
            return false;
185 4
        };
186
    }
187
188 View Code Duplication
    protected static function getEditedMessageEvent(Closure $action)
189
    {
190
        return function (Update $update) use ($action) {
191
            if (!$update->getEditedMessage()) {
192
                return true;
193
            }
194
195
            $reflectionAction = new ReflectionFunction($action);
196
            $reflectionAction->invokeArgs([$update->getEditedMessage()]);
197
            return false;
198
        };
199
    }
200
201 View Code Duplication
    protected static function getChannelPostEvent(Closure $action)
202
    {
203
        return function (Update $update) use ($action) {
204
            if (!$update->getChannelPost()) {
205
                return true;
206
            }
207
208
            $reflectionAction = new ReflectionFunction($action);
209
            $reflectionAction->invokeArgs([$update->getChannelPost()]);
210
            return false;
211
        };
212
    }
213
214 View Code Duplication
    protected static function getCallbackQueryEvent(Closure $action)
215
    {
216
        return function (Update $update) use ($action) {
217
            if (!$update->getCallbackQuery()) {
218
                return true;
219
            }
220
221
            $reflectionAction = new ReflectionFunction($action);
222
            $reflectionAction->invokeArgs([$update->getCallbackQuery()]);
223
            return false;
224
        };
225
    }
226
227 View Code Duplication
    protected static function getEditedChannelPostEvent(Closure $action)
228
    {
229
        return function (Update $update) use ($action) {
230
            if (!$update->getEditedChannelPost()) {
231
                return true;
232
            }
233
234
            $reflectionAction = new ReflectionFunction($action);
235
            $reflectionAction->invokeArgs([$update->getEditedChannelPost()]);
236
            return false;
237
        };
238
    }
239
240 4 View Code Duplication
    protected static function getInlineQueryEvent(Closure $action)
241
    {
242
        return function (Update $update) use ($action) {
243 4
            if (!$update->getInlineQuery()) {
244 3
                return true;
245
            }
246
247 1
            $reflectionAction = new ReflectionFunction($action);
248 1
            $reflectionAction->invokeArgs([$update->getInlineQuery()]);
249 1
            return false;
250 4
        };
251
    }
252
253 View Code Duplication
    protected static function getChosenInlineResultEvent(Closure $action)
254
    {
255
        return function (Update $update) use ($action) {
256
            if (!$update->getChosenInlineResult()) {
257
                return true;
258
            }
259
260
            $reflectionAction = new ReflectionFunction($action);
261
            $reflectionAction->invokeArgs([$update->getChosenInlineResult()]);
262
            return false;
263
        };
264
    }
265
266 View Code Duplication
    protected static function getShippingQueryEvent(Closure $action)
267
    {
268
        return function (Update $update) use ($action) {
269
            if (!$update->getShippingQuery()) {
270
                return true;
271
            }
272
273
            $reflectionAction = new ReflectionFunction($action);
274
            $reflectionAction->invokeArgs([$update->getShippingQuery()]);
275
            return false;
276
        };
277
    }
278
279 View Code Duplication
    protected static function getPreCheckoutQueryEvent(Closure $action)
280
    {
281
        return function (Update $update) use ($action) {
282
            if (!$update->getPreCheckoutQuery()) {
283
                return true;
284
            }
285
286
            $reflectionAction = new ReflectionFunction($action);
287
            $reflectionAction->invokeArgs([$update->getPreCheckoutQuery()]);
288
            return false;
289
        };
290
    }
291
292
    /**
293
     * Returns check function to handling the command.
294
     *
295
     * @param string $name
296
     *
297
     * @return \Closure
298
     */
299 4
    protected static function getChecker($name)
300
    {
301
        return function (Update $update) use ($name) {
302 4
            $message = $update->getMessage();
303 4
            if (is_null($message) || !strlen($message->getText())) {
304 1
                return false;
305
            }
306
307 3
            preg_match(self::REGEXP, $message->getText(), $matches);
308
309 3
            return !empty($matches) && $matches[1] == $name;
310 4
        };
311
    }
312
313
    /**
314
     * Returns check function to handling the edited message.
315
     *
316
     * @return Closure
317
     */
318
    protected static function getEditedMessageChecker()
319
    {
320
        return function (Update $update) {
321
            return !is_null($update->getEditedMessage());
322
        };
323
    }
324
325
    /**
326
     * Returns check function to handling the channel post.
327
     *
328
     * @return Closure
329
     */
330
    protected static function getChannelPostChecker()
331
    {
332
        return function (Update $update) {
333
            return !is_null($update->getChannelPost());
334
        };
335
    }
336
337
    /**
338
     * Returns check function to handling the callbackQuery.
339
     *
340
     * @return Closure
341
     */
342
    protected static function getCallbackQueryChecker()
343
    {
344
        return function (Update $update) {
345
            return !is_null($update->getCallbackQuery());
346
        };
347
    }
348
349
    /**
350
     * Returns check function to handling the edited channel post.
351
     *
352
     * @return Closure
353
     */
354
    protected static function getEditedChannelPostChecker()
355
    {
356
        return function (Update $update) {
357
            return !is_null($update->getEditedChannelPost());
358
        };
359
    }
360
361
    /**
362
     * Returns check function to handling the chosen inline result.
363
     *
364
     * @return Closure
365
     */
366
    protected static function getChosenInlineResultChecker()
367
    {
368
        return function (Update $update) {
369
            return !is_null($update->getChosenInlineResult());
370
        };
371
    }
372
373
    /**
374
     * Returns check function to handling the inline queries.
375
     *
376
     * @return Closure
377
     */
378 4
    protected static function getInlineQueryChecker()
379
    {
380
        return function (Update $update) {
381 4
            return !is_null($update->getInlineQuery());
382 4
        };
383
    }
384
385
    /**
386
     * Returns check function to handling the shipping queries.
387
     *
388
     * @return Closure
389
     */
390
    protected static function getShippingQueryChecker()
391
    {
392
        return function (Update $update) {
393
            return !is_null($update->getShippingQuery());
394
        };
395
    }
396
397
    /**
398
     * Returns check function to handling the pre checkout queries.
399
     *
400
     * @return Closure
401
     */
402
    protected static function getPreCheckoutQueryChecker()
403
    {
404
        return function (Update $update) {
405
            return !is_null($update->getPreCheckoutQuery());
406
        };
407
    }
408
409 1
    public function __call($name, array $arguments)
410
    {
411 1
        if (method_exists($this, $name)) {
412
            return call_user_func_array([$this, $name], $arguments);
413 1
        } elseif (method_exists($this->api, $name)) {
414
            return call_user_func_array([$this->api, $name], $arguments);
415
        }
416 1
        throw new BadMethodCallException("Method {$name} not exists");
417
    }
418
}
419