Passed
Pull Request — master (#408)
by Alexander
02:08 queued 28s
created

Client::shippingQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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