Completed
Pull Request — master (#627)
by
unknown
02:42
created

DB   D

Complexity

Total Complexity 118

Size/Duplication

Total Lines 1163
Duplicated Lines 10.83 %

Coupling/Cohesion

Components 1
Dependencies 9

Test Coverage

Coverage 30.19%

Importance

Changes 0
Metric Value
wmc 118
lcom 1
cbo 9
dl 126
loc 1163
ccs 160
cts 530
cp 0.3019
rs 4.4102
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
B initialize() 0 28 3
A externalInitialize() 0 18 2
A defineTables() 0 21 3
A isDbConnected() 0 4 1
A getPdo() 0 4 1
B selectTelegramUpdate() 0 33 6
A getTimestamp() 0 8 2
B selectMessages() 0 27 4
A entitiesArrayToJson() 0 13 2
C insertTelegramUpdate() 0 38 8
B insertUser() 0 64 5
B insertChat() 0 48 4
D insertRequest() 48 101 17
B insertInlineQueryRequest() 39 39 4
B insertChosenInlineResultRequest() 39 39 4
B insertCallbackQueryRequest() 0 61 6
F insertMessageRequest() 0 166 13
B insertEditedMessageRequest() 0 55 5
F selectChats() 0 104 20
B getTelegramRequestCount() 0 30 3
B insertTelegramRequest() 0 31 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DB often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DB, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * This file is part of the TelegramBot package.
4
 *
5
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 * Written by Marco Boretto <[email protected]>
10
 */
11
12
namespace Longman\TelegramBot;
13
14
use Longman\TelegramBot\Entities\CallbackQuery;
15
use Longman\TelegramBot\Entities\Chat;
16
use Longman\TelegramBot\Entities\ChosenInlineResult;
17
use Longman\TelegramBot\Entities\InlineQuery;
18
use Longman\TelegramBot\Entities\Message;
19
use Longman\TelegramBot\Entities\ReplyToMessage;
20
use Longman\TelegramBot\Entities\Update;
21
use Longman\TelegramBot\Entities\User;
22
use Longman\TelegramBot\Exception\TelegramException;
23
use PDO;
24
use PDOException;
25
26
class DB
27
{
28
    /**
29
     * MySQL credentials
30
     *
31
     * @var array
32
     */
33
    static protected $mysql_credentials = [];
34
35
    /**
36
     * PDO object
37
     *
38
     * @var PDO
39
     */
40
    static protected $pdo;
41
42
    /**
43
     * Table prefix
44
     *
45
     * @var string
46
     */
47
    static protected $table_prefix;
48
49
    /**
50
     * Telegram class object
51
     *
52
     * @var \Longman\TelegramBot\Telegram
53
     */
54
    static protected $telegram;
55
56
    /**
57
     * Initialize
58
     *
59
     * @param array                         $credentials  Database connection details
60
     * @param \Longman\TelegramBot\Telegram $telegram     Telegram object to connect with this object
61
     * @param string                        $table_prefix Table prefix
62
     * @param string                        $encoding     Database character encoding
63
     *
64
     * @return PDO PDO database object
65
     * @throws \Longman\TelegramBot\Exception\TelegramException
66
     */
67 9
    public static function initialize(
68
        array $credentials,
69
        Telegram $telegram,
70
        $table_prefix = null,
71
        $encoding = 'utf8mb4'
72
    ) {
73 9
        if (empty($credentials)) {
74
            throw new TelegramException('MySQL credentials not provided!');
75
        }
76
77 9
        $dsn     = 'mysql:host=' . $credentials['host'] . ';dbname=' . $credentials['database'];
78 9
        $options = [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $encoding];
79
        try {
80 9
            $pdo = new PDO($dsn, $credentials['user'], $credentials['password'], $options);
81 9
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
82
        } catch (PDOException $e) {
83
            throw new TelegramException($e->getMessage());
84
        }
85
86 9
        self::$pdo               = $pdo;
87 9
        self::$telegram          = $telegram;
88 9
        self::$mysql_credentials = $credentials;
89 9
        self::$table_prefix      = $table_prefix;
90
91 9
        self::defineTables();
92
93 9
        return self::$pdo;
94
    }
95
96
    /**
97
     * External Initialize
98
     *
99
     * Let you use the class with an external already existing Pdo Mysql connection.
100
     *
101
     * @param PDO                           $external_pdo_connection PDO database object
102
     * @param \Longman\TelegramBot\Telegram $telegram                Telegram object to connect with this object
103
     * @param string                        $table_prefix            Table prefix
104
     *
105
     * @return PDO PDO database object
106
     * @throws \Longman\TelegramBot\Exception\TelegramException
107
     */
108
    public static function externalInitialize(
109
        $external_pdo_connection,
110
        Telegram $telegram,
111
        $table_prefix = null
112
    ) {
113
        if ($external_pdo_connection === null) {
114
            throw new TelegramException('MySQL external connection not provided!');
115
        }
116
117
        self::$pdo               = $external_pdo_connection;
118
        self::$telegram          = $telegram;
119
        self::$mysql_credentials = [];
120
        self::$table_prefix      = $table_prefix;
121
122
        self::defineTables();
123
124
        return self::$pdo;
125
    }
126
127
    /**
128
     * Define all the tables with the proper prefix
129
     */
130 9
    protected static function defineTables()
131
    {
132
        $tables = [
133 9
            'callback_query',
134
            'chat',
135
            'chosen_inline_result',
136
            'edited_message',
137
            'inline_query',
138
            'message',
139
            'request_limiter',
140
            'telegram_update',
141
            'user',
142
            'user_chat',
143
        ];
144 9
        foreach ($tables as $table) {
145 9
            $table_name = 'TB_' . strtoupper($table);
146 9
            if (!defined($table_name)) {
147 9
                define($table_name, self::$table_prefix . $table);
148
            }
149
        }
150 9
    }
151
152
    /**
153
     * Check if database connection has been created
154
     *
155
     * @return bool
156
     */
157 9
    public static function isDbConnected()
158
    {
159 9
        return self::$pdo !== null;
160
    }
161
162
    /**
163
     * Get the PDO object of the connected database
164
     *
165
     * @return \PDO
166
     */
167
    public static function getPdo()
168
    {
169
        return self::$pdo;
170
    }
171
172
    /**
173
     * Fetch update(s) from DB
174
     *
175
     * @param int $limit Limit the number of updates to fetch
176
     * @param int $id    Check for unique update id
177
     *
178
     * @return array|bool Fetched data or false if not connected
179
     * @throws \Longman\TelegramBot\Exception\TelegramException
180
     */
181
    public static function selectTelegramUpdate($limit = null, $id = null)
182
    {
183
        if (!self::isDbConnected()) {
184
            return false;
185
        }
186
187
        try {
188
            $sql = 'SELECT `id` FROM `' . TB_TELEGRAM_UPDATE . '`';
189
190
            if ($id !== null) {
191
                $sql .= ' WHERE `id` = :id';
192
            }
193
194
            $sql .= ' ORDER BY `id` DESC';
195
196
            if ($limit !== null) {
197
                $sql .= ' LIMIT :limit';
198
            }
199
200
            $sth = self::$pdo->prepare($sql);
201
            $sth->bindParam(':limit', $limit, PDO::PARAM_INT);
202
203
            if ($id !== null) {
204
                $sth->bindParam(':id', $id, PDO::PARAM_STR);
205
            }
206
207
            $sth->execute();
208
209
            return $sth->fetchAll(PDO::FETCH_ASSOC);
210
        } catch (PDOException $e) {
211
            throw new TelegramException($e->getMessage());
212
        }
213
    }
214
215
    /**
216
     * Fetch message(s) from DB
217
     *
218
     * @param int $limit Limit the number of messages to fetch
219
     *
220
     * @return array|bool Fetched data or false if not connected
221
     * @throws \Longman\TelegramBot\Exception\TelegramException
222
     */
223
    public static function selectMessages($limit = null)
224
    {
225
        if (!self::isDbConnected()) {
226
            return false;
227
        }
228
229
        try {
230
            $sql = '
231
                SELECT *
232
                FROM `' . TB_MESSAGE . '`
233
                WHERE `update_id` != 0
234
                ORDER BY `message_id` DESC
235
            ';
236
237
            if ($limit !== null) {
238
                $sql .= 'LIMIT :limit';
239
            }
240
241
            $sth = self::$pdo->prepare($sql);
242
            $sth->bindParam(':limit', $limit, PDO::PARAM_INT);
243
            $sth->execute();
244
245
            return $sth->fetchAll(PDO::FETCH_ASSOC);
246
        } catch (PDOException $e) {
247
            throw new TelegramException($e->getMessage());
248
        }
249
    }
250
251
    /**
252
     * Convert from unix timestamp to timestamp
253
     *
254
     * @param int $time Unix timestamp (if null, current timestamp is used)
255
     *
256
     * @return string
257
     */
258 7
    protected static function getTimestamp($time = null)
259
    {
260 7
        if ($time === null) {
261 6
            $time = time();
262
        }
263
264 7
        return date('Y-m-d H:i:s', $time);
265
    }
266
267
    /**
268
     * Convert array of Entity items to a JSON array
269
     *
270
     * @todo Find a better way, as json_* functions are very heavy
271
     *
272
     * @param array|null $entities
273
     * @param mixed      $default
274
     *
275
     * @return mixed
276
     */
277 6
    public static function entitiesArrayToJson($entities, $default = null)
278
    {
279 6
        if (!is_array($entities)) {
280 6
            return $default;
281
        }
282
283
        //Convert each Entity item into an object based on its JSON reflection
284
        $json_entities = array_map(function ($entity) {
285
            return json_decode($entity, true);
286
        }, $entities);
287
288
        return json_encode($json_entities);
289
    }
290
291
    /**
292
     * Insert entry to telegram_update table
293
     *
294
     * @param int $id
295
     * @param int $chat_id
296
     * @param int $message_id
297
     * @param int $inline_query_id
298
     * @param int $chosen_inline_result_id
299
     * @param int $callback_query_id
300
     * @param int $edited_message_id
301
     *
302
     * @return bool If the insert was successful
303
     * @throws \Longman\TelegramBot\Exception\TelegramException
304
     */
305
    public static function insertTelegramUpdate(
306
        $id,
307
        $chat_id,
308
        $message_id,
309
        $inline_query_id,
310
        $chosen_inline_result_id,
311
        $callback_query_id,
312
        $edited_message_id
313
    ) {
314
        if ($message_id === null && $inline_query_id === null && $chosen_inline_result_id === null && $callback_query_id === null && $edited_message_id === null) {
315
            throw new TelegramException('message_id, inline_query_id, chosen_inline_result_id, callback_query_id, edited_message_id are all null');
316
        }
317
318
        if (!self::isDbConnected()) {
319
            return false;
320
        }
321
322
        try {
323
            $sth = self::$pdo->prepare('
324
                INSERT IGNORE INTO `' . TB_TELEGRAM_UPDATE . '`
325
                (`id`, `chat_id`, `message_id`, `inline_query_id`, `chosen_inline_result_id`, `callback_query_id`, `edited_message_id`)
326
                VALUES
327
                (:id, :chat_id, :message_id, :inline_query_id, :chosen_inline_result_id, :callback_query_id, :edited_message_id)
328
            ');
329
330
            $sth->bindParam(':id', $id, PDO::PARAM_STR);
331
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_STR);
332
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_STR);
333
            $sth->bindParam(':inline_query_id', $inline_query_id, PDO::PARAM_STR);
334
            $sth->bindParam(':chosen_inline_result_id', $chosen_inline_result_id, PDO::PARAM_STR);
335
            $sth->bindParam(':callback_query_id', $callback_query_id, PDO::PARAM_STR);
336
            $sth->bindParam(':edited_message_id', $edited_message_id, PDO::PARAM_STR);
337
338
            return $sth->execute();
339
        } catch (PDOException $e) {
340
            throw new TelegramException($e->getMessage());
341
        }
342
    }
343
344
    /**
345
     * Insert users and save their connection to chats
346
     *
347
     * @param  \Longman\TelegramBot\Entities\User $user
348
     * @param  string                             $date
349
     * @param  \Longman\TelegramBot\Entities\Chat $chat
350
     *
351
     * @return bool If the insert was successful
352
     * @throws \Longman\TelegramBot\Exception\TelegramException
353
     */
354 6
    public static function insertUser(User $user, $date, Chat $chat = null)
355
    {
356 6
        if (!self::isDbConnected()) {
357
            return false;
358
        }
359
360 6
        $user_id        = $user->getId();
361 6
        $is_bot         = $user->getIsBot();
362 6
        $username       = $user->getUsername();
363 6
        $first_name     = $user->getFirstName();
364 6
        $last_name      = $user->getLastName();
365 6
        $language_code  = $user->getLanguageCode();
366
367
        try {
368 6
            $sth = self::$pdo->prepare('
369 6
                INSERT INTO `' . TB_USER . '`
370
                (`id`, `is_bot`, `username`, `first_name`, `last_name`, `language_code`, `created_at`, `updated_at`)
371
                VALUES
372
                (:id, :is_bot,:username, :first_name, :last_name, :language_code, :created_at, :updated_at)
373
                ON DUPLICATE KEY UPDATE
374
                    `is_bot`         = VALUES(`is_bot`),
375
                    `username`       = VALUES(`username`),
376
                    `first_name`     = VALUES(`first_name`),
377
                    `last_name`      = VALUES(`last_name`),
378
                    `language_code`  = VALUES(`language_code`),
379
                    `updated_at`     = VALUES(`updated_at`)
380
            ');
381
382 6
            $sth->bindParam(':id', $user_id, PDO::PARAM_STR);
383 6
            $sth->bindParam(':is_bot', $is_bot, PDO::PARAM_INT);
384 6
            $sth->bindParam(':username', $username, PDO::PARAM_STR, 255);
385 6
            $sth->bindParam(':first_name', $first_name, PDO::PARAM_STR, 255);
386 6
            $sth->bindParam(':last_name', $last_name, PDO::PARAM_STR, 255);
387 6
            $sth->bindParam(':language_code', $language_code, PDO::PARAM_STR, 10);
388 6
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
389 6
            $sth->bindParam(':updated_at', $date, PDO::PARAM_STR);
390
391 6
            $status = $sth->execute();
392
        } catch (PDOException $e) {
393
            throw new TelegramException($e->getMessage());
394
        }
395
396
        //insert also the relationship to the chat into user_chat table
397 6
        if ($chat instanceof Chat) {
398 6
            $chat_id = $chat->getId();
399
            try {
400 6
                $sth = self::$pdo->prepare('
401 6
                    INSERT IGNORE INTO `' . TB_USER_CHAT . '`
402
                    (`user_id`, `chat_id`)
403
                    VALUES
404
                    (:user_id, :chat_id)
405
                ');
406
407 6
                $sth->bindParam(':user_id', $user_id, PDO::PARAM_STR);
408 6
                $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_STR);
409
410 6
                $status = $sth->execute();
411
            } catch (PDOException $e) {
412
                throw new TelegramException($e->getMessage());
413
            }
414
        }
415
416 6
        return $status;
417
    }
418
419
    /**
420
     * Insert chat
421
     *
422
     * @param  \Longman\TelegramBot\Entities\Chat $chat
423
     * @param  string                             $date
424
     * @param  int                                $migrate_to_chat_id
425
     *
426
     * @return bool If the insert was successful
427
     * @throws \Longman\TelegramBot\Exception\TelegramException
428
     */
429 6
    public static function insertChat(Chat $chat, $date, $migrate_to_chat_id = null)
430
    {
431 6
        if (!self::isDbConnected()) {
432
            return false;
433
        }
434
435 6
        $chat_id                             = $chat->getId();
436 6
        $chat_title                          = $chat->getTitle();
437 6
        $chat_username                       = $chat->getUsername();
438 6
        $chat_type                           = $chat->getType();
439 6
        $chat_all_members_are_administrators = $chat->getAllMembersAreAdministrators();
440
441
        try {
442 6
            $sth = self::$pdo->prepare('
443 6
                INSERT IGNORE INTO `' . TB_CHAT . '`
444
                (`id`, `type`, `title`, `username`, `all_members_are_administrators`, `created_at` ,`updated_at`, `old_id`)
445
                VALUES
446
                (:id, :type, :title, :username, :all_members_are_administrators, :created_at, :updated_at, :oldid)
447
                ON DUPLICATE KEY UPDATE
448
                    `type`                           = VALUES(`type`),
449
                    `title`                          = VALUES(`title`),
450
                    `username`                       = VALUES(`username`),
451
                    `all_members_are_administrators` = VALUES(`all_members_are_administrators`),
452
                    `updated_at`                     = VALUES(`updated_at`)
453
            ');
454
455 6
            if ($migrate_to_chat_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $migrate_to_chat_id of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
456
                $chat_type = 'supergroup';
457
458
                $sth->bindParam(':id', $migrate_to_chat_id, PDO::PARAM_STR);
459
                $sth->bindParam(':oldid', $chat_id, PDO::PARAM_STR);
460
            } else {
461 6
                $sth->bindParam(':id', $chat_id, PDO::PARAM_STR);
462 6
                $sth->bindParam(':oldid', $migrate_to_chat_id, PDO::PARAM_STR);
463
            }
464
465 6
            $sth->bindParam(':type', $chat_type, PDO::PARAM_STR);
466 6
            $sth->bindParam(':title', $chat_title, PDO::PARAM_STR, 255);
467 6
            $sth->bindParam(':username', $chat_username, PDO::PARAM_STR, 255);
468 6
            $sth->bindParam(':all_members_are_administrators', $chat_all_members_are_administrators, PDO::PARAM_INT);
469 6
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
470 6
            $sth->bindParam(':updated_at', $date, PDO::PARAM_STR);
471
472 6
            return $sth->execute();
473
        } catch (PDOException $e) {
474
            throw new TelegramException($e->getMessage());
475
        }
476
    }
477
478
    /**
479
     * Insert request into database
480
     *
481
     * @todo self::$pdo->lastInsertId() - unsafe usage if expected previous insert fails?
482
     *
483
     * @param \Longman\TelegramBot\Entities\Update $update
484
     *
485
     * @return bool
486
     * @throws \Longman\TelegramBot\Exception\TelegramException
487
     */
488
    public static function insertRequest(Update $update)
489
    {
490
        if (!self::isDbConnected()) {
491
            return false;
492
        }
493
494
        $update_id   = $update->getUpdateId();
495
        $update_type = $update->getUpdateType();
496
497
        if (count(self::selectTelegramUpdate(1, $update_id)) === 1) {
498
            throw new TelegramException('Duplicate update received!');
499
        }
500
501
        if ($update_type === 'message') {
502
            $message = $update->getMessage();
503
504 View Code Duplication
            if (self::insertMessageRequest($message)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
505
                $message_id = $message->getMessageId();
506
                $chat_id    = $message->getChat()->getId();
507
508
                return self::insertTelegramUpdate($update_id, $chat_id, $message_id, null, null, null, null);
509
            }
510 View Code Duplication
        } elseif ($update_type === 'edited_message') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
511
            $edited_message = $update->getEditedMessage();
512
513
            if (self::insertEditedMessageRequest($edited_message)) {
514
                $chat_id                 = $edited_message->getChat()->getId();
515
                $edited_message_local_id = self::$pdo->lastInsertId();
516
517
                return self::insertTelegramUpdate(
518
                    $update_id,
519
                    $chat_id,
520
                    null,
521
                    null,
522
                    null,
523
                    null,
524
                    $edited_message_local_id
525
                );
526
            }
527
        } elseif ($update_type === 'channel_post') {
528
            $channel_post = $update->getChannelPost();
529
530 View Code Duplication
            if (self::insertMessageRequest($channel_post)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
531
                $message_id = $channel_post->getMessageId();
532
                $chat_id    = $channel_post->getChat()->getId();
533
534
                return self::insertTelegramUpdate($update_id, $chat_id, $message_id, null, null, null, null);
535
            }
536 View Code Duplication
        } elseif ($update_type === 'edited_channel_post') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
537
            $edited_channel_post = $update->getEditedChannelPost();
538
539
            if (self::insertEditedMessageRequest($edited_channel_post)) {
540
                $chat_id                      = $edited_channel_post->getChat()->getId();
541
                $edited_channel_post_local_id = self::$pdo->lastInsertId();
542
543
                return self::insertTelegramUpdate(
544
                    $update_id,
545
                    $chat_id,
546
                    null,
547
                    null,
548
                    null,
549
                    null,
550
                    $edited_channel_post_local_id
551
                );
552
            }
553
        } elseif ($update_type === 'inline_query') {
554
            $inline_query = $update->getInlineQuery();
555
556
            if (self::insertInlineQueryRequest($inline_query)) {
557
                $inline_query_id = $inline_query->getId();
558
559
                return self::insertTelegramUpdate($update_id, null, null, $inline_query_id, null, null, null);
560
            }
561
        } elseif ($update_type === 'chosen_inline_result') {
562
            $chosen_inline_result = $update->getChosenInlineResult();
563
564
            if (self::insertChosenInlineResultRequest($chosen_inline_result)) {
565
                $chosen_inline_result_local_id = self::$pdo->lastInsertId();
566
567
                return self::insertTelegramUpdate(
568
                    $update_id,
569
                    null,
570
                    null,
571
                    null,
572
                    $chosen_inline_result_local_id,
573
                    null,
574
                    null
575
                );
576
            }
577
        } elseif ($update_type === 'callback_query') {
578
            $callback_query = $update->getCallbackQuery();
579
580
            if (self::insertCallbackQueryRequest($callback_query)) {
581
                $callback_query_id = $callback_query->getId();
582
583
                return self::insertTelegramUpdate($update_id, null, null, null, null, $callback_query_id, null);
584
            }
585
        }
586
587
        return false;
588
    }
589
590
    /**
591
     * Insert inline query request into database
592
     *
593
     * @param \Longman\TelegramBot\Entities\InlineQuery $inline_query
594
     *
595
     * @return bool If the insert was successful
596
     * @throws \Longman\TelegramBot\Exception\TelegramException
597
     */
598 View Code Duplication
    public static function insertInlineQueryRequest(InlineQuery $inline_query)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
599
    {
600
        if (!self::isDbConnected()) {
601
            return false;
602
        }
603
604
        try {
605
            $sth = self::$pdo->prepare('
606
                INSERT IGNORE INTO `' . TB_INLINE_QUERY . '`
607
                (`id`, `user_id`, `location`, `query`, `offset`, `created_at`)
608
                VALUES
609
                (:inline_query_id, :user_id, :location, :query, :param_offset, :created_at)
610
            ');
611
612
            $date            = self::getTimestamp();
613
            $inline_query_id = $inline_query->getId();
614
            $from            = $inline_query->getFrom();
615
            $user_id         = null;
616
            if ($from instanceof User) {
617
                $user_id = $from->getId();
618
                self::insertUser($from, $date);
619
            }
620
621
            $location = $inline_query->getLocation();
622
            $query    = $inline_query->getQuery();
623
            $offset   = $inline_query->getOffset();
624
625
            $sth->bindParam(':inline_query_id', $inline_query_id, PDO::PARAM_STR);
626
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_STR);
627
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
628
            $sth->bindParam(':query', $query, PDO::PARAM_STR);
629
            $sth->bindParam(':param_offset', $offset, PDO::PARAM_STR);
630
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
631
632
            return $sth->execute();
633
        } catch (PDOException $e) {
634
            throw new TelegramException($e->getMessage());
635
        }
636
    }
637
638
    /**
639
     * Insert chosen inline result request into database
640
     *
641
     * @param \Longman\TelegramBot\Entities\ChosenInlineResult $chosen_inline_result
642
     *
643
     * @return bool If the insert was successful
644
     * @throws \Longman\TelegramBot\Exception\TelegramException
645
     */
646 View Code Duplication
    public static function insertChosenInlineResultRequest(ChosenInlineResult $chosen_inline_result)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
647
    {
648
        if (!self::isDbConnected()) {
649
            return false;
650
        }
651
652
        try {
653
            $sth = self::$pdo->prepare('
654
                INSERT INTO `' . TB_CHOSEN_INLINE_RESULT . '`
655
                (`result_id`, `user_id`, `location`, `inline_message_id`, `query`, `created_at`)
656
                VALUES
657
                (:result_id, :user_id, :location, :inline_message_id, :query, :created_at)
658
            ');
659
660
            $date      = self::getTimestamp();
661
            $result_id = $chosen_inline_result->getResultId();
662
            $from      = $chosen_inline_result->getFrom();
663
            $user_id   = null;
664
            if ($from instanceof User) {
665
                $user_id = $from->getId();
666
                self::insertUser($from, $date);
667
            }
668
669
            $location          = $chosen_inline_result->getLocation();
670
            $inline_message_id = $chosen_inline_result->getInlineMessageId();
671
            $query             = $chosen_inline_result->getQuery();
672
673
            $sth->bindParam(':result_id', $result_id, PDO::PARAM_STR);
674
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_STR);
675
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
676
            $sth->bindParam(':inline_message_id', $inline_message_id, PDO::PARAM_STR);
677
            $sth->bindParam(':query', $query, PDO::PARAM_STR);
678
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
679
680
            return $sth->execute();
681
        } catch (PDOException $e) {
682
            throw new TelegramException($e->getMessage());
683
        }
684
    }
685
686
    /**
687
     * Insert callback query request into database
688
     *
689
     * @param \Longman\TelegramBot\Entities\CallbackQuery $callback_query
690
     *
691
     * @return bool If the insert was successful
692
     * @throws \Longman\TelegramBot\Exception\TelegramException
693
     */
694
    public static function insertCallbackQueryRequest(CallbackQuery $callback_query)
695
    {
696
        if (!self::isDbConnected()) {
697
            return false;
698
        }
699
700
        try {
701
            $sth = self::$pdo->prepare('
702
                INSERT IGNORE INTO `' . TB_CALLBACK_QUERY . '`
703
                (`id`, `user_id`, `chat_id`, `message_id`, `inline_message_id`, `data`, `created_at`)
704
                VALUES
705
                (:callback_query_id, :user_id, :chat_id, :message_id, :inline_message_id, :data, :created_at)
706
            ');
707
708
            $date              = self::getTimestamp();
709
            $callback_query_id = $callback_query->getId();
710
            $from              = $callback_query->getFrom();
711
            $user_id           = null;
712
            if ($from instanceof User) {
713
                $user_id = $from->getId();
714
                self::insertUser($from, $date);
715
            }
716
717
            $message    = $callback_query->getMessage();
718
            $chat_id    = null;
719
            $message_id = null;
720
            if ($message instanceof Message) {
721
                $chat_id    = $message->getChat()->getId();
722
                $message_id = $message->getMessageId();
723
724
                $is_message = self::$pdo->query('
725
                    SELECT *
726
                    FROM `' . TB_MESSAGE . '`
727
                    WHERE `id` = ' . $message_id . '
728
                      AND `chat_id` = ' . $chat_id . '
729
                    LIMIT 1
730
                ')->rowCount();
731
732
                if ($is_message) {
733
                    self::insertEditedMessageRequest($message);
734
                } else {
735
                    self::insertMessageRequest($message);
736
                }
737
            }
738
739
            $inline_message_id = $callback_query->getInlineMessageId();
740
            $data              = $callback_query->getData();
741
742
            $sth->bindParam(':callback_query_id', $callback_query_id, PDO::PARAM_STR);
743
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_STR);
744
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_STR);
745
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_STR);
746
            $sth->bindParam(':inline_message_id', $inline_message_id, PDO::PARAM_STR);
747
            $sth->bindParam(':data', $data, PDO::PARAM_STR);
748
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
749
750
            return $sth->execute();
751
        } catch (PDOException $e) {
752
            throw new TelegramException($e->getMessage());
753
        }
754
    }
755
756
    /**
757
     * Insert Message request in db
758
     *
759
     * @param \Longman\TelegramBot\Entities\Message $message
760
     *
761
     * @return bool If the insert was successful
762
     * @throws \Longman\TelegramBot\Exception\TelegramException
763
     */
764 6
    public static function insertMessageRequest(Message $message)
765
    {
766 6
        if (!self::isDbConnected()) {
767
            return false;
768
        }
769
770 6
        $from = $message->getFrom();
771 6
        $chat = $message->getChat();
772
773 6
        $chat_id = $chat->getId();
774
775 6
        $date = self::getTimestamp($message->getDate());
776
777 6
        $forward_from            = $message->getForwardFrom();
778 6
        $forward_from_chat       = $message->getForwardFromChat();
779 6
        $forward_from_message_id = $message->getForwardFromMessageId();
780 6
        $photo                   = self::entitiesArrayToJson($message->getPhoto(), '');
781 6
        $entities                = self::entitiesArrayToJson($message->getEntities(), null);
782 6
        $new_chat_members        = $message->getNewChatMembers();
783 6
        $left_chat_member        = $message->getLeftChatMember();
784 6
        $new_chat_photo          = self::entitiesArrayToJson($message->getNewChatPhoto(), '');
785 6
        $migrate_to_chat_id      = $message->getMigrateToChatId();
786
787
        //Insert chat, update chat id in case it migrated
788 6
        self::insertChat($chat, $date, $migrate_to_chat_id);
789
790
        //Insert user and the relation with the chat
791 6
        if (is_object($from)) {
792 6
            self::insertUser($from, $date, $chat);
793
        }
794
795
        //Insert the forwarded message user in users table
796 6
        if ($forward_from instanceof User) {
797
            $forward_date = self::getTimestamp($message->getForwardDate());
798
            self::insertUser($forward_from, $forward_date);
799
            $forward_from = $forward_from->getId();
800
        }
801
802 6
        if ($forward_from_chat instanceof Chat) {
803
            $forward_date = self::getTimestamp($message->getForwardDate());
804
            self::insertChat($forward_from_chat, $forward_date);
805
            $forward_from_chat = $forward_from_chat->getId();
806
        }
807
808
        //New and left chat member
809 6
        if (!empty($new_chat_members)) {
810
            $new_chat_members_ids = [];
811
            foreach ($new_chat_members as $new_chat_member) {
812
                if ($new_chat_member instanceof User) {
813
                    //Insert the new chat user
814
                    self::insertUser($new_chat_member, $date, $chat);
815
                    $new_chat_members_ids[] = $new_chat_member->getId();
816
                }
817
            }
818
            $new_chat_members_ids = implode(',', $new_chat_members_ids);
819 6
        } elseif ($left_chat_member instanceof User) {
820
            //Insert the left chat user
821
            self::insertUser($left_chat_member, $date, $chat);
822
            $left_chat_member = $left_chat_member->getId();
823
        }
824
825
        try {
826 6
            $sth = self::$pdo->prepare('
827 6
                INSERT IGNORE INTO `' . TB_MESSAGE . '`
828
                (
829
                    `id`, `user_id`, `chat_id`, `date`, `forward_from`, `forward_from_chat`, `forward_from_message_id`,
830
                    `forward_date`, `reply_to_chat`, `reply_to_message`, `text`, `entities`, `audio`, `document`,
831
                    `photo`, `sticker`, `video`, `voice`, `video_note`, `caption`, `contact`,
832
                    `location`, `venue`, `new_chat_members`, `left_chat_member`,
833
                    `new_chat_title`,`new_chat_photo`, `delete_chat_photo`, `group_chat_created`,
834
                    `supergroup_chat_created`, `channel_chat_created`,
835
                    `migrate_from_chat_id`, `migrate_to_chat_id`, `pinned_message`
836
                ) VALUES (
837
                    :message_id, :user_id, :chat_id, :date, :forward_from, :forward_from_chat, :forward_from_message_id,
838
                    :forward_date, :reply_to_chat, :reply_to_message, :text, :entities, :audio, :document,
839
                    :photo, :sticker, :video, :voice, :video_note, :caption, :contact,
840
                    :location, :venue, :new_chat_members, :left_chat_member,
841
                    :new_chat_title, :new_chat_photo, :delete_chat_photo, :group_chat_created,
842
                    :supergroup_chat_created, :channel_chat_created,
843
                    :migrate_from_chat_id, :migrate_to_chat_id, :pinned_message
844
                )
845
            ');
846
847 6
            $message_id = $message->getMessageId();
848
849 6
            if (is_object($from)) {
850 6
                $from_id = $from->getId();
851
            } else {
852
                $from_id = null;
853
            }
854
855 6
            $reply_to_message    = $message->getReplyToMessage();
856 6
            $reply_to_message_id = null;
857 6
            if ($reply_to_message instanceof ReplyToMessage) {
858
                $reply_to_message_id = $reply_to_message->getMessageId();
859
                // please notice that, as explained in the documentation, reply_to_message don't contain other
860
                // reply_to_message field so recursion deep is 1
861
                self::insertMessageRequest($reply_to_message);
862
            }
863
864 6
            $text                    = $message->getText();
865 6
            $audio                   = $message->getAudio();
866 6
            $document                = $message->getDocument();
867 6
            $sticker                 = $message->getSticker();
868 6
            $video                   = $message->getVideo();
869 6
            $voice                   = $message->getVoice();
870 6
            $video_note              = $message->getVideoNote();
871 6
            $caption                 = $message->getCaption();
872 6
            $contact                 = $message->getContact();
873 6
            $location                = $message->getLocation();
874 6
            $venue                   = $message->getVenue();
875 6
            $new_chat_title          = $message->getNewChatTitle();
876 6
            $delete_chat_photo       = $message->getDeleteChatPhoto();
877 6
            $group_chat_created      = $message->getGroupChatCreated();
878 6
            $supergroup_chat_created = $message->getSupergroupChatCreated();
879 6
            $channel_chat_created    = $message->getChannelChatCreated();
880 6
            $migrate_from_chat_id    = $message->getMigrateFromChatId();
881 6
            $migrate_to_chat_id      = $message->getMigrateToChatId();
882 6
            $pinned_message          = $message->getPinnedMessage();
883
884 6
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_STR);
885 6
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_STR);
886 6
            $sth->bindParam(':user_id', $from_id, PDO::PARAM_STR);
887 6
            $sth->bindParam(':date', $date, PDO::PARAM_STR);
888 6
            $sth->bindParam(':forward_from', $forward_from, PDO::PARAM_STR);
889 6
            $sth->bindParam(':forward_from_chat', $forward_from_chat, PDO::PARAM_STR);
890 6
            $sth->bindParam(':forward_from_message_id', $forward_from_message_id, PDO::PARAM_STR);
891 6
            $sth->bindParam(':forward_date', $forward_date, PDO::PARAM_STR);
892
893 6
            $reply_to_chat_id = null;
894 6
            if ($reply_to_message_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $reply_to_message_id of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
895
                $reply_to_chat_id = $chat_id;
896
            }
897
898 6
            $sth->bindParam(':reply_to_chat', $reply_to_chat_id, PDO::PARAM_STR);
899 6
            $sth->bindParam(':reply_to_message', $reply_to_message_id, PDO::PARAM_STR);
900 6
            $sth->bindParam(':text', $text, PDO::PARAM_STR);
901 6
            $sth->bindParam(':entities', $entities, PDO::PARAM_STR);
902 6
            $sth->bindParam(':audio', $audio, PDO::PARAM_STR);
903 6
            $sth->bindParam(':document', $document, PDO::PARAM_STR);
904 6
            $sth->bindParam(':photo', $photo, PDO::PARAM_STR);
905 6
            $sth->bindParam(':sticker', $sticker, PDO::PARAM_STR);
906 6
            $sth->bindParam(':video', $video, PDO::PARAM_STR);
907 6
            $sth->bindParam(':voice', $voice, PDO::PARAM_STR);
908 6
            $sth->bindParam(':video_note', $video_note, PDO::PARAM_STR);
909 6
            $sth->bindParam(':caption', $caption, PDO::PARAM_STR);
910 6
            $sth->bindParam(':contact', $contact, PDO::PARAM_STR);
911 6
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
912 6
            $sth->bindParam(':venue', $venue, PDO::PARAM_STR);
913 6
            $sth->bindParam(':new_chat_members', $new_chat_members_ids, PDO::PARAM_STR);
914 6
            $sth->bindParam(':left_chat_member', $left_chat_member, PDO::PARAM_STR);
915 6
            $sth->bindParam(':new_chat_title', $new_chat_title, PDO::PARAM_STR);
916 6
            $sth->bindParam(':new_chat_photo', $new_chat_photo, PDO::PARAM_STR);
917 6
            $sth->bindParam(':delete_chat_photo', $delete_chat_photo, PDO::PARAM_INT);
918 6
            $sth->bindParam(':group_chat_created', $group_chat_created, PDO::PARAM_INT);
919 6
            $sth->bindParam(':supergroup_chat_created', $supergroup_chat_created, PDO::PARAM_INT);
920 6
            $sth->bindParam(':channel_chat_created', $channel_chat_created, PDO::PARAM_INT);
921 6
            $sth->bindParam(':migrate_from_chat_id', $migrate_from_chat_id, PDO::PARAM_STR);
922 6
            $sth->bindParam(':migrate_to_chat_id', $migrate_to_chat_id, PDO::PARAM_STR);
923 6
            $sth->bindParam(':pinned_message', $pinned_message, PDO::PARAM_STR);
924
925 6
            return $sth->execute();
926
        } catch (PDOException $e) {
927
            throw new TelegramException($e->getMessage());
928
        }
929
    }
930
931
    /**
932
     * Insert Edited Message request in db
933
     *
934
     * @param \Longman\TelegramBot\Entities\Message $edited_message
935
     *
936
     * @return bool If the insert was successful
937
     * @throws \Longman\TelegramBot\Exception\TelegramException
938
     */
939
    public static function insertEditedMessageRequest(Message $edited_message)
940
    {
941
        if (!self::isDbConnected()) {
942
            return false;
943
        }
944
945
        $from = $edited_message->getFrom();
946
        $chat = $edited_message->getChat();
947
948
        $chat_id = $chat->getId();
949
950
        $edit_date = self::getTimestamp($edited_message->getEditDate());
951
952
        $entities = self::entitiesArrayToJson($edited_message->getEntities(), null);
953
954
        //Insert chat
955
        self::insertChat($chat, $edit_date);
956
957
        //Insert user and the relation with the chat
958
        if (is_object($from)) {
959
            self::insertUser($from, $edit_date, $chat);
960
        }
961
962
        try {
963
            $sth = self::$pdo->prepare('
964
                INSERT IGNORE INTO `' . TB_EDITED_MESSAGE . '`
965
                (`chat_id`, `message_id`, `user_id`, `edit_date`, `text`, `entities`, `caption`)
966
                VALUES
967
                (:chat_id, :message_id, :user_id, :edit_date, :text, :entities, :caption)
968
            ');
969
970
            $message_id = $edited_message->getMessageId();
971
972
            if (is_object($from)) {
973
                $from_id = $from->getId();
974
            } else {
975
                $from_id = null;
976
            }
977
978
            $text    = $edited_message->getText();
979
            $caption = $edited_message->getCaption();
980
981
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_STR);
982
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_STR);
983
            $sth->bindParam(':user_id', $from_id, PDO::PARAM_STR);
984
            $sth->bindParam(':edit_date', $edit_date, PDO::PARAM_STR);
985
            $sth->bindParam(':text', $text, PDO::PARAM_STR);
986
            $sth->bindParam(':entities', $entities, PDO::PARAM_STR);
987
            $sth->bindParam(':caption', $caption, PDO::PARAM_STR);
988
989
            return $sth->execute();
990
        } catch (PDOException $e) {
991
            throw new TelegramException($e->getMessage());
992
        }
993
    }
994
995
    /**
996
     * Select Groups, Supergroups, Channels and/or single user Chats (also by ID or text)
997
     *
998
     * @param $select_chats_params
999
     *
1000
     * @return array|bool
1001
     * @throws TelegramException
1002
     */
1003
    public static function selectChats($select_chats_params)
1004
    {
1005
        if (!self::isDbConnected()) {
1006
            return false;
1007
        }
1008
1009
        // Set defaults for omitted values.
1010
        $select = array_merge([
1011
            'groups'      => true,
1012
            'supergroups' => true,
1013
            'channels'    => true,
1014
            'users'       => true,
1015
            'date_from'   => null,
1016
            'date_to'     => null,
1017
            'chat_id'     => null,
1018
            'text'        => null,
1019
        ], $select_chats_params);
1020
1021
        if (!$select['groups'] && !$select['users'] && !$select['supergroups']) {
1022
            return false;
1023
        }
1024
1025
        try {
1026
            $query = '
1027
                SELECT * ,
1028
                ' . TB_CHAT . '.`id` AS `chat_id`,
1029
                ' . TB_CHAT . '.`username` AS `chat_username`,
1030
                ' . TB_CHAT . '.`created_at` AS `chat_created_at`,
1031
                ' . TB_CHAT . '.`updated_at` AS `chat_updated_at`
1032
            ';
1033
            if ($select['users']) {
1034
                $query .= '
1035
                    , ' . TB_USER . '.`id` AS `user_id`
1036
                    FROM `' . TB_CHAT . '`
1037
                    LEFT JOIN `' . TB_USER . '`
1038
                    ON ' . TB_CHAT . '.`id`=' . TB_USER . '.`id`
1039
                ';
1040
            } else {
1041
                $query .= 'FROM `' . TB_CHAT . '`';
1042
            }
1043
1044
            //Building parts of query
1045
            $where  = [];
1046
            $tokens = [];
1047
1048
            if (!$select['groups'] || !$select['users'] || !$select['supergroups']) {
1049
                $chat_or_user = [];
1050
1051
                $select['groups'] && $chat_or_user[] = TB_CHAT . '.`type` = "group"';
1052
                $select['supergroups'] && $chat_or_user[] = TB_CHAT . '.`type` = "supergroup"';
1053
                $select['channels'] && $chat_or_user[] = TB_CHAT . '.`type` = "channel"';
1054
                $select['users'] && $chat_or_user[] = TB_CHAT . '.`type` = "private"';
1055
1056
                $where[] = '(' . implode(' OR ', $chat_or_user) . ')';
1057
            }
1058
1059
            if (null !== $select['date_from']) {
1060
                $where[]              = TB_CHAT . '.`updated_at` >= :date_from';
1061
                $tokens[':date_from'] = $select['date_from'];
1062
            }
1063
1064
            if (null !== $select['date_to']) {
1065
                $where[]            = TB_CHAT . '.`updated_at` <= :date_to';
1066
                $tokens[':date_to'] = $select['date_to'];
1067
            }
1068
1069
            if (null !== $select['chat_id']) {
1070
                $where[]            = TB_CHAT . '.`id` = :chat_id';
1071
                $tokens[':chat_id'] = $select['chat_id'];
1072
            }
1073
1074
            if (null !== $select['text']) {
1075
                $text_like = '%' . strtolower($select['text']) . '%';
1076
                if ($select['users']) {
1077
                    $where[] = '(
1078
                        LOWER(' . TB_CHAT . '.`title`) LIKE :text1
1079
                        OR LOWER(' . TB_USER . '.`first_name`) LIKE :text2
1080
                        OR LOWER(' . TB_USER . '.`last_name`) LIKE :text3
1081
                        OR LOWER(' . TB_USER . '.`username`) LIKE :text4
1082
                    )';
1083
                    $tokens[':text1'] = $text_like;
1084
                    $tokens[':text2'] = $text_like;
1085
                    $tokens[':text3'] = $text_like;
1086
                    $tokens[':text4'] = $text_like;
1087
                } else {
1088
                    $where[] = 'LOWER(' . TB_CHAT . '.`title`) LIKE :text';
1089
                    $tokens[':text'] = $text_like;
1090
                }
1091
            }
1092
1093
            if (!empty($where)) {
1094
                $query .= ' WHERE ' . implode(' AND ', $where);
1095
            }
1096
1097
            $query .= ' ORDER BY ' . TB_CHAT . '.`updated_at` ASC';
1098
1099
            $sth = self::$pdo->prepare($query);
1100
            $sth->execute($tokens);
1101
1102
            return $sth->fetchAll(PDO::FETCH_ASSOC);
1103
        } catch (PDOException $e) {
1104
            throw new TelegramException($e->getMessage());
1105
        }
1106
    }
1107
1108
    /**
1109
     * Get Telegram API request count for current chat / message
1110
     *
1111
     * @param integer $chat_id
1112
     * @param string  $inline_message_id
1113
     *
1114
     * @return array|bool (Array containing TOTAL and CURRENT fields or false on invalid arguments)
1115
     * @throws \Longman\TelegramBot\Exception\TelegramException
1116
     */
1117
    public static function getTelegramRequestCount($chat_id = null, $inline_message_id = null)
1118
    {
1119
        if (!self::isDbConnected()) {
1120
            return false;
1121
        }
1122
1123
        try {
1124
            $sth = self::$pdo->prepare('SELECT 
1125
                (SELECT COUNT(DISTINCT `chat_id`) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_1) as LIMIT_PER_SEC_ALL,
1126
                (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_2 AND ((`chat_id` = :chat_id_1 AND `inline_message_id` IS NULL) OR (`inline_message_id` = :inline_message_id AND `chat_id` IS NULL))) as LIMIT_PER_SEC,
1127
                (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_minute AND `chat_id` = :chat_id_2) as LIMIT_PER_MINUTE
1128
            ');
1129
1130
            $date = self::getTimestamp();
1131
            $date_minute = self::getTimestamp(strtotime('-1 minute'));
1132
1133
            $sth->bindParam(':chat_id_1', $chat_id, \PDO::PARAM_STR);
1134
            $sth->bindParam(':chat_id_2', $chat_id, \PDO::PARAM_STR);
1135
            $sth->bindParam(':inline_message_id', $inline_message_id, \PDO::PARAM_STR);
1136
            $sth->bindParam(':created_at_1', $date, \PDO::PARAM_STR);
1137
            $sth->bindParam(':created_at_2', $date, \PDO::PARAM_STR);
1138
            $sth->bindParam(':created_at_minute', $date_minute, \PDO::PARAM_STR);
1139
1140
            $sth->execute();
1141
1142
            return $sth->fetch();
1143
        } catch (\Exception $e) {
1144
            throw new TelegramException($e->getMessage());
1145
        }
1146
    }
1147
1148
    /**
1149
     * Insert Telegram API request in db
1150
     *
1151
     * @param string $method
1152
     * @param array  $data
1153
     *
1154
     * @return bool If the insert was successful
1155
     * @throws \Longman\TelegramBot\Exception\TelegramException
1156
     */
1157
    public static function insertTelegramRequest($method, $data)
1158
    {
1159
        if (!self::isDbConnected()) {
1160
            return false;
1161
        }
1162
1163
        $chat_id = ((isset($data['chat_id'])) ? $data['chat_id'] : null);
1164
        $inline_message_id = (isset($data['inline_message_id']) ? $data['inline_message_id'] : null);
1165
1166
        try {
1167
            $sth = self::$pdo->prepare('INSERT INTO `' . TB_REQUEST_LIMITER . '`
1168
                (
1169
                `method`, `chat_id`, `inline_message_id`, `created_at`
1170
                )
1171
                VALUES (
1172
                :method, :chat_id, :inline_message_id, :created_at
1173
                );
1174
            ');
1175
1176
            $created_at = self::getTimestamp();
1177
1178
            $sth->bindParam(':chat_id', $chat_id, \PDO::PARAM_STR);
1179
            $sth->bindParam(':inline_message_id', $inline_message_id, \PDO::PARAM_STR);
1180
            $sth->bindParam(':method', $method, \PDO::PARAM_STR);
1181
            $sth->bindParam(':created_at', $created_at, \PDO::PARAM_STR);
1182
1183
            return $sth->execute();
1184
        } catch (\Exception $e) {
1185
            throw new TelegramException($e->getMessage());
1186
        }
1187
    }
1188
}
1189