GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

DB::selectChats()   F
last analyzed

Complexity

Conditions 24
Paths > 20000

Size

Total Lines 108
Code Lines 73

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 600

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 24
eloc 73
nc 21755
nop 1
dl 0
loc 108
ccs 0
cts 0
cp 0
crap 600
rs 0
c 1
b 0
f 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

523
            $sth->bindValue(':all_members_are_administrators', /** @scrutinizer ignore-deprecated */ $chat->getAllMembersAreAdministrators(), PDO::PARAM_INT);
Loading history...
524
            $date = $date ?: self::getTimestamp();
525
            $sth->bindValue(':created_at', $date);
526
            $sth->bindValue(':updated_at', $date);
527
528
            return $sth->execute();
529
        } catch (PDOException $e) {
530
            throw new TelegramException($e->getMessage());
531
        }
532
    }
533
534
    /**
535
     * Insert request into database
536
     *
537
     * @todo self::$pdo->lastInsertId() - unsafe usage if expected previous insert fails?
538
     *
539
     * @param Update $update
540
     *
541
     * @return bool
542
     * @throws TelegramException
543
     */
544
    public static function insertRequest(Update $update): bool
545
    {
546
        if (!self::isDbConnected()) {
547
            return false;
548
        }
549
550
        $chat_id                   = null;
551
        $message_id                = null;
552
        $edited_message_id         = null;
553
        $channel_post_id           = null;
554
        $edited_channel_post_id    = null;
555
        $inline_query_id           = null;
556
        $chosen_inline_result_id   = null;
557
        $callback_query_id         = null;
558
        $shipping_query_id         = null;
559
        $pre_checkout_query_id     = null;
560
        $poll_id                   = null;
561
        $poll_answer_poll_id       = null;
562
        $my_chat_member_updated_id = null;
563
        $chat_member_updated_id    = null;
564
        $chat_join_request_id      = null;
565
566
        if (($message = $update->getMessage()) && self::insertMessageRequest($message)) {
567
            $chat_id    = $message->getChat()->getId();
568
            $message_id = $message->getMessageId();
569
        } elseif (($edited_message = $update->getEditedMessage()) && self::insertEditedMessageRequest($edited_message)) {
570
            $chat_id           = $edited_message->getChat()->getId();
571
            $edited_message_id = (int) self::$pdo->lastInsertId();
572
        } elseif (($channel_post = $update->getChannelPost()) && self::insertMessageRequest($channel_post)) {
573
            $chat_id         = $channel_post->getChat()->getId();
574
            $channel_post_id = $channel_post->getMessageId();
575
        } elseif (($edited_channel_post = $update->getEditedChannelPost()) && self::insertEditedMessageRequest($edited_channel_post)) {
576
            $chat_id                = $edited_channel_post->getChat()->getId();
577
            $edited_channel_post_id = (int) self::$pdo->lastInsertId();
578
        } elseif (($inline_query = $update->getInlineQuery()) && self::insertInlineQueryRequest($inline_query)) {
579
            $inline_query_id = $inline_query->getId();
580
        } elseif (($chosen_inline_result = $update->getChosenInlineResult()) && self::insertChosenInlineResultRequest($chosen_inline_result)) {
581
            $chosen_inline_result_id = self::$pdo->lastInsertId();
582
        } elseif (($callback_query = $update->getCallbackQuery()) && self::insertCallbackQueryRequest($callback_query)) {
583
            $callback_query_id = $callback_query->getId();
584
        } elseif (($shipping_query = $update->getShippingQuery()) && self::insertShippingQueryRequest($shipping_query)) {
585
            $shipping_query_id = $shipping_query->getId();
586
        } elseif (($pre_checkout_query = $update->getPreCheckoutQuery()) && self::insertPreCheckoutQueryRequest($pre_checkout_query)) {
587
            $pre_checkout_query_id = $pre_checkout_query->getId();
588
        } elseif (($poll = $update->getPoll()) && self::insertPollRequest($poll)) {
589
            $poll_id = $poll->getId();
590
        } elseif (($poll_answer = $update->getPollAnswer()) && self::insertPollAnswerRequest($poll_answer)) {
591
            $poll_answer_poll_id = $poll_answer->getPollId();
592
        } elseif (($my_chat_member = $update->getMyChatMember()) && self::insertChatMemberUpdatedRequest($my_chat_member)) {
593
            $my_chat_member_updated_id = self::$pdo->lastInsertId();
594
        } elseif (($chat_member = $update->getChatMember()) && self::insertChatMemberUpdatedRequest($chat_member)) {
595
            $chat_member_updated_id = self::$pdo->lastInsertId();
596
        } elseif (($chat_join_request = $update->getChatJoinRequest()) && self::insertChatJoinRequestRequest($chat_join_request)) {
597
            $chat_join_request_id = self::$pdo->lastInsertId();
598
        } else {
599
            return false;
600
        }
601
602
        return self::insertTelegramUpdate(
603
            $update->getUpdateId(),
604
            $chat_id,
605
            $message_id,
606
            $edited_message_id,
607
            $channel_post_id,
608
            $edited_channel_post_id,
609
            $inline_query_id,
610
            $chosen_inline_result_id,
611
            $callback_query_id,
612
            $shipping_query_id,
613
            $pre_checkout_query_id,
614
            $poll_id,
615
            $poll_answer_poll_id,
616
            $my_chat_member_updated_id,
617
            $chat_member_updated_id,
618
            $chat_join_request_id
619
        );
620
    }
621
622
    /**
623
     * Insert inline query request into database
624
     *
625
     * @param InlineQuery $inline_query
626
     *
627
     * @return bool If the insert was successful
628
     * @throws TelegramException
629
     */
630
    public static function insertInlineQueryRequest(InlineQuery $inline_query): bool
631
    {
632
        if (!self::isDbConnected()) {
633
            return false;
634
        }
635
636
        try {
637
            $sth = self::$pdo->prepare('
638
                INSERT IGNORE INTO `' . TB_INLINE_QUERY . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_INLINE_QUERY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
639
                (`id`, `user_id`, `location`, `query`, `offset`, `chat_type`, `created_at`)
640
                VALUES
641
                (:id, :user_id, :location, :query, :offset, :chat_type, :created_at)
642
            ');
643
644
            $date    = self::getTimestamp();
645
            $user_id = null;
646
647
            if ($user = $inline_query->getFrom()) {
648
                $user_id = $user->getId();
649
                self::insertUser($user, $date);
650
            }
651
652
            $sth->bindValue(':id', $inline_query->getId());
653
            $sth->bindValue(':user_id', $user_id);
654
            $sth->bindValue(':location', $inline_query->getLocation());
655
            $sth->bindValue(':query', $inline_query->getQuery());
656
            $sth->bindValue(':offset', $inline_query->getOffset());
657
            $sth->bindValue(':chat_type', $inline_query->getChatType());
658
            $sth->bindValue(':created_at', $date);
659
660
            return $sth->execute();
661
        } catch (PDOException $e) {
662
            throw new TelegramException($e->getMessage());
663
        }
664
    }
665
666
    /**
667
     * Insert chosen inline result request into database
668
     *
669
     * @param ChosenInlineResult $chosen_inline_result
670
     *
671
     * @return bool If the insert was successful
672
     * @throws TelegramException
673
     */
674
    public static function insertChosenInlineResultRequest(ChosenInlineResult $chosen_inline_result): bool
675
    {
676
        if (!self::isDbConnected()) {
677
            return false;
678
        }
679
680
        try {
681
            $sth = self::$pdo->prepare('
682
                INSERT INTO `' . TB_CHOSEN_INLINE_RESULT . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_CHOSEN_INLINE_RESULT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
683
                (`result_id`, `user_id`, `location`, `inline_message_id`, `query`, `created_at`)
684
                VALUES
685
                (:result_id, :user_id, :location, :inline_message_id, :query, :created_at)
686
            ');
687
688
            $date    = self::getTimestamp();
689
            $user_id = null;
690
691
            if ($user = $chosen_inline_result->getFrom()) {
692
                $user_id = $user->getId();
693
                self::insertUser($user, $date);
694
            }
695
696
            $sth->bindValue(':result_id', $chosen_inline_result->getResultId());
697
            $sth->bindValue(':user_id', $user_id);
698
            $sth->bindValue(':location', $chosen_inline_result->getLocation());
699
            $sth->bindValue(':inline_message_id', $chosen_inline_result->getInlineMessageId());
700
            $sth->bindValue(':query', $chosen_inline_result->getQuery());
701
            $sth->bindValue(':created_at', $date);
702
703
            return $sth->execute();
704
        } catch (PDOException $e) {
705
            throw new TelegramException($e->getMessage());
706
        }
707
    }
708
709
    /**
710
     * Insert callback query request into database
711
     *
712
     * @param CallbackQuery $callback_query
713
     *
714
     * @return bool If the insert was successful
715
     * @throws TelegramException
716
     */
717
    public static function insertCallbackQueryRequest(CallbackQuery $callback_query): bool
718
    {
719
        if (!self::isDbConnected()) {
720
            return false;
721
        }
722
723
        try {
724
            $sth = self::$pdo->prepare('
725
                INSERT IGNORE INTO `' . TB_CALLBACK_QUERY . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_CALLBACK_QUERY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
726
                (`id`, `user_id`, `chat_id`, `message_id`, `inline_message_id`, `chat_instance`, `data`, `game_short_name`, `created_at`)
727
                VALUES
728
                (:id, :user_id, :chat_id, :message_id, :inline_message_id, :chat_instance, :data, :game_short_name, :created_at)
729
            ');
730
731
            $date    = self::getTimestamp();
732
            $user_id = null;
733
734
            if ($user = $callback_query->getFrom()) {
735
                $user_id = $user->getId();
736
                self::insertUser($user, $date);
737
            }
738
739
            $chat_id    = null;
740
            $message_id = null;
741
            if ($message = $callback_query->getMessage()) {
742
                $chat_id    = $message->getChat()->getId();
743
                $message_id = $message->getMessageId();
744
745
                $is_message = self::$pdo->query('
746
                    SELECT *
747
                    FROM `' . TB_MESSAGE . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_MESSAGE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
748
                    WHERE `id` = ' . $message_id . '
749
                      AND `chat_id` = ' . $chat_id . '
750
                    LIMIT 1
751
                ')->rowCount();
752
753
                if ($is_message) {
754
                    self::insertEditedMessageRequest($message);
755
                } else {
756
                    self::insertMessageRequest($message);
757
                }
758
            }
759
760
            $sth->bindValue(':id', $callback_query->getId());
761
            $sth->bindValue(':user_id', $user_id);
762
            $sth->bindValue(':chat_id', $chat_id);
763
            $sth->bindValue(':message_id', $message_id);
764
            $sth->bindValue(':inline_message_id', $callback_query->getInlineMessageId());
765
            $sth->bindValue(':chat_instance', $callback_query->getChatInstance());
766
            $sth->bindValue(':data', $callback_query->getData());
767
            $sth->bindValue(':game_short_name', $callback_query->getGameShortName());
768 6
            $sth->bindValue(':created_at', $date);
769
770 6
            return $sth->execute();
771
        } catch (PDOException $e) {
772
            throw new TelegramException($e->getMessage());
773
        }
774 6
    }
775
776
    /**
777 6
     * Insert shipping query request into database
778 6
     *
779
     * @param ShippingQuery $shipping_query
780
     *
781 6
     * @return bool If the insert was successful
782 6
     * @throws TelegramException
783 6
     */
784
    public static function insertShippingQueryRequest(ShippingQuery $shipping_query): bool
785
    {
786
        if (!self::isDbConnected()) {
787 6
            return false;
788 6
        }
789 6
790
        try {
791
            $sth = self::$pdo->prepare('
792
                INSERT IGNORE INTO `' . TB_SHIPPING_QUERY . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_SHIPPING_QUERY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
793
                (`id`, `user_id`, `invoice_payload`, `shipping_address`, `created_at`)
794 6
                VALUES
795 6
                (:id, :user_id, :invoice_payload, :shipping_address, :created_at)
796
            ');
797
798
            $date    = self::getTimestamp();
799
            $user_id = null;
800
801
            if ($user = $shipping_query->getFrom()) {
802 6
                $user_id = $user->getId();
803 6
                self::insertUser($user, $date);
804
            }
805 6
806 6
            $sth->bindValue(':id', $shipping_query->getId());
807 6
            $sth->bindValue(':user_id', $user_id);
808
            $sth->bindValue(':invoice_payload', $shipping_query->getInvoicePayload());
809
            $sth->bindValue(':shipping_address', $shipping_query->getShippingAddress());
810
            $sth->bindValue(':created_at', $date);
811
812
            return $sth->execute();
813
        } catch (PDOException $e) {
814
            throw new TelegramException($e->getMessage());
815
        }
816 6
    }
817
818
    /**
819
     * Insert pre checkout query request into database
820
     *
821
     * @param PreCheckoutQuery $pre_checkout_query
822
     *
823 6
     * @return bool If the insert was successful
824 6
     * @throws TelegramException
825
     */
826
    public static function insertPreCheckoutQueryRequest(PreCheckoutQuery $pre_checkout_query): bool
827
    {
828
        if (!self::isDbConnected()) {
829
            return false;
830
        }
831
832
        try {
833
            $sth = self::$pdo->prepare('
834
                INSERT IGNORE INTO `' . TB_PRE_CHECKOUT_QUERY . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_PRE_CHECKOUT_QUERY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
835
                (`id`, `user_id`, `currency`, `total_amount`, `invoice_payload`, `shipping_option_id`, `order_info`, `created_at`)
836
                VALUES
837
                (:id, :user_id, :currency, :total_amount, :invoice_payload, :shipping_option_id, :order_info, :created_at)
838
            ');
839
840
            $date    = self::getTimestamp();
841
            $user_id = null;
842
843
            if ($user = $pre_checkout_query->getFrom()) {
844 6
                $user_id = $user->getId();
845 6
                self::insertUser($user, $date);
846 6
            }
847
848 6
            $sth->bindValue(':id', $pre_checkout_query->getId());
849
            $sth->bindValue(':user_id', $user_id);
850 6
            $sth->bindValue(':currency', $pre_checkout_query->getCurrency());
851 6
            $sth->bindValue(':total_amount', $pre_checkout_query->getTotalAmount());
852 6
            $sth->bindValue(':invoice_payload', $pre_checkout_query->getInvoicePayload());
853
            $sth->bindValue(':shipping_option_id', $pre_checkout_query->getShippingOptionId());
854
            $sth->bindValue(':order_info', $pre_checkout_query->getOrderInfo());
855
            $sth->bindValue(':created_at', $date);
856
857
            return $sth->execute();
858
        } catch (PDOException $e) {
859 6
            throw new TelegramException($e->getMessage());
860 6
        }
861 6
    }
862 6
863 6
    /**
864 6
     * Insert poll request into database
865 6
     *
866 6
     * @param Poll $poll
867
     *
868 6
     * @return bool If the insert was successful
869 6
     * @throws TelegramException
870
     */
871
    public static function insertPollRequest(Poll $poll): bool
872 6
    {
873 6
        if (!self::isDbConnected()) {
874
            return false;
875 6
        }
876 6
877 6
        try {
878 6
            $sth = self::$pdo->prepare('
879 6
                INSERT INTO `' . TB_POLL . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_POLL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
880 6
                (`id`, `question`, `options`, `total_voter_count`, `is_closed`, `is_anonymous`, `type`, `allows_multiple_answers`, `correct_option_id`, `explanation`, `explanation_entities`, `open_period`, `close_date`, `created_at`)
881 6
                VALUES
882 6
                (:id, :question, :options, :total_voter_count, :is_closed, :is_anonymous, :type, :allows_multiple_answers, :correct_option_id, :explanation, :explanation_entities, :open_period, :close_date, :created_at)
883 6
                ON DUPLICATE KEY UPDATE
884 6
                    `options`                 = VALUES(`options`),
885 6
                    `total_voter_count`       = VALUES(`total_voter_count`),
886 6
                    `is_closed`               = VALUES(`is_closed`),
887 6
                    `is_anonymous`            = VALUES(`is_anonymous`),
888 6
                    `type`                    = VALUES(`type`),
889 6
                    `allows_multiple_answers` = VALUES(`allows_multiple_answers`),
890 6
                    `correct_option_id`       = VALUES(`correct_option_id`),
891 6
                    `explanation`             = VALUES(`explanation`),
892 6
                    `explanation_entities`    = VALUES(`explanation_entities`),
893 6
                    `open_period`             = VALUES(`open_period`),
894 6
                    `close_date`              = VALUES(`close_date`)
895 6
            ');
896 6
897 6
            $sth->bindValue(':id', $poll->getId());
898 6
            $sth->bindValue(':question', $poll->getQuestion());
899 6
            $sth->bindValue(':options', self::entitiesArrayToJson($poll->getOptions() ?: []));
900 6
            $sth->bindValue(':total_voter_count', $poll->getTotalVoterCount());
901
            $sth->bindValue(':is_closed', $poll->getIsClosed(), PDO::PARAM_INT);
902 6
            $sth->bindValue(':is_anonymous', $poll->getIsAnonymous(), PDO::PARAM_INT);
903
            $sth->bindValue(':type', $poll->getType());
904
            $sth->bindValue(':allows_multiple_answers', $poll->getAllowsMultipleAnswers(), PDO::PARAM_INT);
905
            $sth->bindValue(':correct_option_id', $poll->getCorrectOptionId());
906
            $sth->bindValue(':explanation', $poll->getExplanation());
907
            $sth->bindValue(':explanation_entities', self::entitiesArrayToJson($poll->getExplanationEntities() ?: []));
908
            $sth->bindValue(':open_period', $poll->getOpenPeriod());
909
            $sth->bindValue(':close_date', self::getTimestamp($poll->getCloseDate()));
910
            $sth->bindValue(':created_at', self::getTimestamp());
911
912
            return $sth->execute();
913
        } catch (PDOException $e) {
914
            throw new TelegramException($e->getMessage());
915
        }
916
    }
917
918
    /**
919
     * Insert poll answer request into database
920
     *
921
     * @param PollAnswer $poll_answer
922
     *
923
     * @return bool If the insert was successful
924
     * @throws TelegramException
925
     */
926
    public static function insertPollAnswerRequest(PollAnswer $poll_answer): bool
927
    {
928
        if (!self::isDbConnected()) {
929
            return false;
930
        }
931
932
        try {
933
            $sth = self::$pdo->prepare('
934
                INSERT INTO `' . TB_POLL_ANSWER . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_POLL_ANSWER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
935
                (`poll_id`, `user_id`, `option_ids`, `created_at`)
936
                VALUES
937
                (:poll_id, :user_id, :option_ids, :created_at)
938
                ON DUPLICATE KEY UPDATE
939
                    `option_ids` = VALUES(`option_ids`)
940
            ');
941
942
            $date    = self::getTimestamp();
943
            $user_id = null;
944
945
            if ($user = $poll_answer->getUser()) {
946
                $user_id = $user->getId();
947
                self::insertUser($user, $date);
948
            }
949
950
            $sth->bindValue(':poll_id', $poll_answer->getPollId());
951
            $sth->bindValue(':user_id', $user_id);
952
            $sth->bindValue(':option_ids', json_encode($poll_answer->getOptionIds()));
953
            $sth->bindValue(':created_at', $date);
954
955
            return $sth->execute();
956
        } catch (PDOException $e) {
957
            throw new TelegramException($e->getMessage());
958
        }
959
    }
960
961
    /**
962
     * Insert chat member updated request into database
963
     *
964
     * @param ChatMemberUpdated $chat_member_updated
965
     *
966
     * @return bool If the insert was successful
967
     * @throws TelegramException
968
     */
969
    public static function insertChatMemberUpdatedRequest(ChatMemberUpdated $chat_member_updated): bool
970
    {
971
        if (!self::isDbConnected()) {
972
            return false;
973
        }
974
975
        try {
976
            $sth = self::$pdo->prepare('
977
                INSERT INTO `' . TB_CHAT_MEMBER_UPDATED . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_CHAT_MEMBER_UPDATED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
978
                (`chat_id`, `user_id`, `date`, `old_chat_member`, `new_chat_member`, `invite_link`, `created_at`)
979
                VALUES
980
                (:chat_id, :user_id, :date, :old_chat_member, :new_chat_member, :invite_link, :created_at)
981
            ');
982
983
            $date    = self::getTimestamp();
984
            $chat_id = null;
985
            $user_id = null;
986
987
            if ($chat = $chat_member_updated->getChat()) {
988
                $chat_id = $chat->getId();
989
                self::insertChat($chat, $date);
990
            }
991
            if ($user = $chat_member_updated->getFrom()) {
992
                $user_id = $user->getId();
993
                self::insertUser($user, $date);
994
            }
995
996
            $sth->bindValue(':chat_id', $chat_id);
997
            $sth->bindValue(':user_id', $user_id);
998
            $sth->bindValue(':date', self::getTimestamp($chat_member_updated->getDate()));
999
            $sth->bindValue(':old_chat_member', $chat_member_updated->getOldChatMember());
1000
            $sth->bindValue(':new_chat_member', $chat_member_updated->getNewChatMember());
1001
            $sth->bindValue(':invite_link', $chat_member_updated->getInviteLink());
1002
            $sth->bindValue(':created_at', $date);
1003
1004
            return $sth->execute();
1005
        } catch (PDOException $e) {
1006
            throw new TelegramException($e->getMessage());
1007
        }
1008
    }
1009
1010
    /**
1011
     * Insert chat join request into database
1012
     *
1013
     * @param ChatJoinRequest $chat_join_request
1014
     *
1015
     * @return bool If the insert was successful
1016
     * @throws TelegramException
1017
     */
1018
    public static function insertChatJoinRequestRequest(ChatJoinRequest $chat_join_request): bool
1019
    {
1020
        if (!self::isDbConnected()) {
1021
            return false;
1022
        }
1023
1024
        try {
1025
            $sth = self::$pdo->prepare('
1026
                INSERT INTO `' . TB_CHAT_JOIN_REQUEST . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_CHAT_JOIN_REQUEST was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1027
                (`chat_id`, `user_id`, `date`, `bio`, `invite_link`, `created_at`)
1028
                VALUES
1029
                (:chat_id, :user_id, :date, :bio, :invite_link, :created_at)
1030
            ');
1031
1032
            $date    = self::getTimestamp();
1033
            $chat_id = null;
1034
            $user_id = null;
1035
1036
            if ($chat = $chat_join_request->getChat()) {
1037
                $chat_id = $chat->getId();
1038
                self::insertChat($chat, $date);
1039
            }
1040
            if ($user = $chat_join_request->getFrom()) {
1041
                $user_id = $user->getId();
1042
                self::insertUser($user, $date);
1043
            }
1044
1045
            $sth->bindValue(':chat_id', $chat_id);
1046
            $sth->bindValue(':user_id', $user_id);
1047
            $sth->bindValue(':date', self::getTimestamp($chat_join_request->getDate()));
1048
            $sth->bindValue(':bio', $chat_join_request->getBio());
1049
            $sth->bindValue(':invite_link', $chat_join_request->getInviteLink());
1050
            $sth->bindValue(':created_at', $date);
1051
1052
            return $sth->execute();
1053
        } catch (PDOException $e) {
1054
            throw new TelegramException($e->getMessage());
1055
        }
1056
    }
1057
1058
    /**
1059
     * Insert Message request in db
1060
     *
1061
     * @param Message $message
1062
     *
1063
     * @return bool If the insert was successful
1064
     * @throws TelegramException
1065
     */
1066
    public static function insertMessageRequest(Message $message): bool
1067
    {
1068
        if (!self::isDbConnected()) {
1069
            return false;
1070
        }
1071
1072
        $date = self::getTimestamp($message->getDate());
1073
1074
        // Insert chat, update chat id in case it migrated
1075
        $chat = $message->getChat();
1076
        self::insertChat($chat, $date, $message->getMigrateToChatId());
1077
1078
        $sender_chat_id = null;
1079
        if ($sender_chat = $message->getSenderChat()) {
1080
            self::insertChat($sender_chat);
1081
            $sender_chat_id = $sender_chat->getId();
1082
        }
1083
1084
        // Insert user and the relation with the chat
1085
        if ($user = $message->getFrom()) {
1086
            self::insertUser($user, $date, $chat);
1087
        }
1088
1089
        // Insert the forwarded message user in users table
1090
        $forward_date = $message->getForwardDate() ? self::getTimestamp($message->getForwardDate()) : null;
1091
1092
        if ($forward_from = $message->getForwardFrom()) {
1093
            self::insertUser($forward_from);
1094
            $forward_from = $forward_from->getId();
1095
        }
1096
        if ($forward_from_chat = $message->getForwardFromChat()) {
1097
            self::insertChat($forward_from_chat);
1098
            $forward_from_chat = $forward_from_chat->getId();
1099
        }
1100
1101
        $via_bot_id = null;
1102
        if ($via_bot = $message->getViaBot()) {
1103
            self::insertUser($via_bot);
1104
            $via_bot_id = $via_bot->getId();
1105
        }
1106
1107
        // New and left chat member
1108
        $new_chat_members_ids = null;
1109
        $left_chat_member_id  = null;
1110
1111
        $new_chat_members = $message->getNewChatMembers();
0 ignored issues
show
Bug introduced by
The method getNewChatMembers() does not exist on Longman\TelegramBot\Entities\Message. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1111
        /** @scrutinizer ignore-call */ 
1112
        $new_chat_members = $message->getNewChatMembers();
Loading history...
1112
        $left_chat_member = $message->getLeftChatMember();
1113
        if (!empty($new_chat_members)) {
1114
            foreach ($new_chat_members as $new_chat_member) {
1115
                if ($new_chat_member instanceof User) {
1116
                    // Insert the new chat user
1117
                    self::insertUser($new_chat_member, $date, $chat);
1118
                    $new_chat_members_ids[] = $new_chat_member->getId();
1119
                }
1120
            }
1121
            $new_chat_members_ids = implode(',', $new_chat_members_ids);
1122
        } elseif ($left_chat_member) {
0 ignored issues
show
introduced by
$left_chat_member is of type Longman\TelegramBot\Entities\User, thus it always evaluated to true.
Loading history...
1123
            // Insert the left chat user
1124
            self::insertUser($left_chat_member, $date, $chat);
1125
            $left_chat_member_id = $left_chat_member->getId();
1126
        }
1127
1128
        try {
1129
            $sth = self::$pdo->prepare('
1130
                INSERT IGNORE INTO `' . TB_MESSAGE . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_MESSAGE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1131
                (
1132
                    `id`, `user_id`, `chat_id`, `sender_chat_id`, `date`, `forward_from`, `forward_from_chat`, `forward_from_message_id`,
1133
                    `forward_signature`, `forward_sender_name`, `forward_date`,
1134
                    `reply_to_chat`, `reply_to_message`, `via_bot`, `edit_date`, `media_group_id`, `author_signature`, `text`, `entities`, `caption_entities`,
1135
                    `audio`, `document`, `animation`, `game`, `photo`, `sticker`, `video`, `voice`, `video_note`, `caption`, `contact`,
1136
                    `location`, `venue`, `poll`, `dice`, `new_chat_members`, `left_chat_member`,
1137
                    `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`,
1138
                    `supergroup_chat_created`, `channel_chat_created`, `message_auto_delete_timer_changed`, `migrate_to_chat_id`, `migrate_from_chat_id`,
1139
                    `pinned_message`, `invoice`, `successful_payment`, `connected_website`, `passport_data`, `proximity_alert_triggered`,
1140
                    `voice_chat_scheduled`, `voice_chat_started`, `voice_chat_ended`, `voice_chat_participants_invited`, `reply_markup`
1141
                ) VALUES (
1142
                    :message_id, :user_id, :chat_id, :sender_chat_id, :date, :forward_from, :forward_from_chat, :forward_from_message_id,
1143
                    :forward_signature, :forward_sender_name, :forward_date,
1144
                    :reply_to_chat, :reply_to_message, :via_bot, :edit_date, :media_group_id, :author_signature, :text, :entities, :caption_entities,
1145
                    :audio, :document, :animation, :game, :photo, :sticker, :video, :voice, :video_note, :caption, :contact,
1146
                    :location, :venue, :poll, :dice, :new_chat_members, :left_chat_member,
1147
                    :new_chat_title, :new_chat_photo, :delete_chat_photo, :group_chat_created,
1148
                    :supergroup_chat_created, :channel_chat_created, :message_auto_delete_timer_changed, :migrate_to_chat_id, :migrate_from_chat_id,
1149
                    :pinned_message, :invoice, :successful_payment, :connected_website, :passport_data, :proximity_alert_triggered,
1150
                    :voice_chat_scheduled, :voice_chat_started, :voice_chat_ended, :voice_chat_participants_invited, :reply_markup
1151
                )
1152
            ');
1153
1154
            $user_id = $user ? $user->getId() : null;
0 ignored issues
show
introduced by
$user is of type Longman\TelegramBot\Entities\User, thus it always evaluated to true.
Loading history...
1155
            $chat_id = $chat->getId();
1156
1157
            $reply_to_message_id = null;
1158
            if ($reply_to_message = $message->getReplyToMessage()) {
1159
                $reply_to_message_id = $reply_to_message->getMessageId();
1160 3
                // please notice that, as explained in the documentation, reply_to_message don't contain other
1161
                // reply_to_message field so recursion deep is 1
1162 3
                self::insertMessageRequest($reply_to_message);
1163
            }
1164
1165
            $sth->bindValue(':message_id', $message->getMessageId());
1166
            $sth->bindValue(':chat_id', $chat_id);
1167
            $sth->bindValue(':sender_chat_id', $sender_chat_id);
1168 3
            $sth->bindValue(':user_id', $user_id);
1169
            $sth->bindValue(':date', $date);
1170
            $sth->bindValue(':forward_from', $forward_from);
1171 3
            $sth->bindValue(':forward_from_chat', $forward_from_chat);
1172 3
            $sth->bindValue(':forward_from_message_id', $message->getForwardFromMessageId());
1173 3
            $sth->bindValue(':forward_signature', $message->getForwardSignature());
1174 3
            $sth->bindValue(':forward_sender_name', $message->getForwardSenderName());
1175
            $sth->bindValue(':forward_date', $forward_date);
1176
1177
            $reply_to_chat_id = null;
1178 3
            if ($reply_to_message_id !== null) {
1179 3
                $reply_to_chat_id = $chat_id;
1180 3
            }
1181 3
            $sth->bindValue(':reply_to_chat', $reply_to_chat_id);
1182
            $sth->bindValue(':reply_to_message', $reply_to_message_id);
1183
1184 3
            $sth->bindValue(':via_bot', $via_bot_id);
1185 3
            $sth->bindValue(':edit_date', self::getTimestamp($message->getEditDate()));
1186
            $sth->bindValue(':media_group_id', $message->getMediaGroupId());
1187 3
            $sth->bindValue(':author_signature', $message->getAuthorSignature());
1188
            $sth->bindValue(':text', $message->getText());
1189
            $sth->bindValue(':entities', self::entitiesArrayToJson($message->getEntities() ?: []));
1190
            $sth->bindValue(':caption_entities', self::entitiesArrayToJson($message->getCaptionEntities() ?: []));
1191
            $sth->bindValue(':audio', $message->getAudio());
1192
            $sth->bindValue(':document', $message->getDocument());
1193
            $sth->bindValue(':animation', $message->getAnimation());
1194
            $sth->bindValue(':game', $message->getGame());
1195
            $sth->bindValue(':photo', self::entitiesArrayToJson($message->getPhoto() ?: []));
1196
            $sth->bindValue(':sticker', $message->getSticker());
1197
            $sth->bindValue(':video', $message->getVideo());
1198
            $sth->bindValue(':voice', $message->getVoice());
1199
            $sth->bindValue(':video_note', $message->getVideoNote());
1200
            $sth->bindValue(':caption', $message->getCaption());
1201
            $sth->bindValue(':contact', $message->getContact());
1202
            $sth->bindValue(':location', $message->getLocation());
1203
            $sth->bindValue(':venue', $message->getVenue());
1204
            $sth->bindValue(':poll', $message->getPoll());
1205
            $sth->bindValue(':dice', $message->getDice());
1206
            $sth->bindValue(':new_chat_members', $new_chat_members_ids);
1207
            $sth->bindValue(':left_chat_member', $left_chat_member_id);
1208
            $sth->bindValue(':new_chat_title', $message->getNewChatTitle());
1209
            $sth->bindValue(':new_chat_photo', self::entitiesArrayToJson($message->getNewChatPhoto() ?: []));
1210
            $sth->bindValue(':delete_chat_photo', $message->getDeleteChatPhoto());
1211
            $sth->bindValue(':group_chat_created', $message->getGroupChatCreated());
1212
            $sth->bindValue(':supergroup_chat_created', $message->getSupergroupChatCreated());
1213
            $sth->bindValue(':channel_chat_created', $message->getChannelChatCreated());
1214
            $sth->bindValue(':message_auto_delete_timer_changed', $message->getMessageAutoDeleteTimerChanged());
1215
            $sth->bindValue(':migrate_to_chat_id', $message->getMigrateToChatId());
1216
            $sth->bindValue(':migrate_from_chat_id', $message->getMigrateFromChatId());
1217
            $sth->bindValue(':pinned_message', $message->getPinnedMessage());
1218
            $sth->bindValue(':invoice', $message->getInvoice());
1219
            $sth->bindValue(':successful_payment', $message->getSuccessfulPayment());
1220
            $sth->bindValue(':connected_website', $message->getConnectedWebsite());
1221
            $sth->bindValue(':passport_data', $message->getPassportData());
1222
            $sth->bindValue(':proximity_alert_triggered', $message->getProximityAlertTriggered());
1223
            $sth->bindValue(':voice_chat_scheduled', $message->getVoiceChatScheduled());
1224
            $sth->bindValue(':voice_chat_started', $message->getVoiceChatStarted());
1225
            $sth->bindValue(':voice_chat_ended', $message->getVoiceChatEnded());
1226
            $sth->bindValue(':voice_chat_participants_invited', $message->getVoiceChatParticipantsInvited());
1227
            $sth->bindValue(':reply_markup', $message->getReplyMarkup());
1228
1229
            return $sth->execute();
1230
        } catch (PDOException $e) {
1231
            throw new TelegramException($e->getMessage());
1232
        }
1233
    }
1234
1235
    /**
1236
     * Insert Edited Message request in db
1237
     *
1238
     * @param Message $edited_message
1239
     *
1240
     * @return bool If the insert was successful
1241
     * @throws TelegramException
1242
     */
1243
    public static function insertEditedMessageRequest(Message $edited_message): bool
1244
    {
1245
        if (!self::isDbConnected()) {
1246
            return false;
1247
        }
1248
1249
        try {
1250
            $edit_date = self::getTimestamp($edited_message->getEditDate());
1251
1252
            // Insert chat
1253
            $chat = $edited_message->getChat();
1254
            self::insertChat($chat, $edit_date);
1255
1256
            // Insert user and the relation with the chat
1257
            if ($user = $edited_message->getFrom()) {
1258
                self::insertUser($user, $edit_date, $chat);
1259
            }
1260
1261
            $sth = self::$pdo->prepare('
1262
                INSERT IGNORE INTO `' . TB_EDITED_MESSAGE . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_EDITED_MESSAGE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1263
                (`chat_id`, `message_id`, `user_id`, `edit_date`, `text`, `entities`, `caption`)
1264
                VALUES
1265
                (:chat_id, :message_id, :user_id, :edit_date, :text, :entities, :caption)
1266
            ');
1267
1268
            $user_id = $user ? $user->getId() : null;
0 ignored issues
show
introduced by
$user is of type Longman\TelegramBot\Entities\User, thus it always evaluated to true.
Loading history...
1269
1270
            $sth->bindValue(':chat_id', $chat->getId());
1271
            $sth->bindValue(':message_id', $edited_message->getMessageId());
1272
            $sth->bindValue(':user_id', $user_id);
1273
            $sth->bindValue(':edit_date', $edit_date);
1274
            $sth->bindValue(':text', $edited_message->getText());
1275
            $sth->bindValue(':entities', self::entitiesArrayToJson($edited_message->getEntities() ?: []));
1276
            $sth->bindValue(':caption', $edited_message->getCaption());
1277
1278
            return $sth->execute();
1279
        } catch (PDOException $e) {
1280
            throw new TelegramException($e->getMessage());
1281
        }
1282
    }
1283
1284
    /**
1285
     * Select Groups, Supergroups, Channels and/or single user Chats (also by ID or text)
1286
     *
1287
     * @param $select_chats_params
1288
     *
1289
     * @return array|bool
1290
     * @throws TelegramException
1291
     */
1292
    public static function selectChats($select_chats_params)
1293
    {
1294
        if (!self::isDbConnected()) {
1295
            return false;
1296
        }
1297
1298
        // Set defaults for omitted values.
1299
        $select = array_merge([
1300
            'groups'      => true,
1301
            'supergroups' => true,
1302
            'channels'    => true,
1303
            'users'       => true,
1304
            'date_from'   => null,
1305
            'date_to'     => null,
1306
            'chat_id'     => null,
1307
            'text'        => null,
1308
            'language'    => null,
1309
        ], $select_chats_params);
1310
1311
        if (!$select['groups'] && !$select['users'] && !$select['supergroups'] && !$select['channels']) {
1312
            return false;
1313
        }
1314
1315
        try {
1316
            $query = '
1317
                SELECT * ,
1318
                ' . TB_CHAT . '.`id` AS `chat_id`,
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_CHAT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1319
                ' . TB_CHAT . '.`username` AS `chat_username`,
1320
                ' . TB_CHAT . '.`created_at` AS `chat_created_at`,
1321
                ' . TB_CHAT . '.`updated_at` AS `chat_updated_at`
1322
            ';
1323
            if ($select['users']) {
1324
                $query .= '
1325
                    , ' . TB_USER . '.`id` AS `user_id`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_USER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1326
                    FROM `' . TB_CHAT . '`
1327
                    LEFT JOIN `' . TB_USER . '`
1328
                    ON ' . TB_CHAT . '.`id`=' . TB_USER . '.`id`
1329
                ';
1330
            } else {
1331
                $query .= 'FROM `' . TB_CHAT . '`';
1332
            }
1333
1334
            // Building parts of query
1335
            $where  = [];
1336
            $tokens = [];
1337
1338
            if (!$select['groups'] || !$select['users'] || !$select['supergroups'] || !$select['channels']) {
1339
                $chat_or_user = [];
1340
1341
                $select['groups'] && $chat_or_user[] = TB_CHAT . '.`type` = "group"';
1342
                $select['supergroups'] && $chat_or_user[] = TB_CHAT . '.`type` = "supergroup"';
1343
                $select['channels'] && $chat_or_user[] = TB_CHAT . '.`type` = "channel"';
1344
                $select['users'] && $chat_or_user[] = TB_CHAT . '.`type` = "private"';
1345
1346
                $where[] = '(' . implode(' OR ', $chat_or_user) . ')';
1347
            }
1348
1349
            if (null !== $select['date_from']) {
1350
                $where[]              = TB_CHAT . '.`updated_at` >= :date_from';
1351
                $tokens[':date_from'] = $select['date_from'];
1352
            }
1353
1354
            if (null !== $select['date_to']) {
1355
                $where[]            = TB_CHAT . '.`updated_at` <= :date_to';
1356
                $tokens[':date_to'] = $select['date_to'];
1357
            }
1358
1359
            if (null !== $select['chat_id']) {
1360
                $where[]            = TB_CHAT . '.`id` = :chat_id';
1361
                $tokens[':chat_id'] = $select['chat_id'];
1362
            }
1363
1364
            if ($select['users'] && null !== $select['language']) {
1365
                $where[]             = TB_USER . '.`language_code` = :language';
1366
                $tokens[':language'] = $select['language'];
1367
            }
1368
1369
            if (null !== $select['text']) {
1370
                $text_like = '%' . strtolower($select['text']) . '%';
1371
                if ($select['users']) {
1372
                    $where[]          = '(
1373
                        LOWER(' . TB_CHAT . '.`title`) LIKE :text1
1374
                        OR LOWER(' . TB_USER . '.`first_name`) LIKE :text2
1375
                        OR LOWER(' . TB_USER . '.`last_name`) LIKE :text3
1376
                        OR LOWER(' . TB_USER . '.`username`) LIKE :text4
1377
                    )';
1378
                    $tokens[':text1'] = $text_like;
1379
                    $tokens[':text2'] = $text_like;
1380
                    $tokens[':text3'] = $text_like;
1381
                    $tokens[':text4'] = $text_like;
1382
                } else {
1383
                    $where[]         = 'LOWER(' . TB_CHAT . '.`title`) LIKE :text';
1384
                    $tokens[':text'] = $text_like;
1385
                }
1386
            }
1387
1388
            if (!empty($where)) {
1389
                $query .= ' WHERE ' . implode(' AND ', $where);
1390
            }
1391
1392
            $query .= ' ORDER BY ' . TB_CHAT . '.`updated_at` ASC';
1393
1394
            $sth = self::$pdo->prepare($query);
1395
            $sth->execute($tokens);
1396
1397
            return $sth->fetchAll(PDO::FETCH_ASSOC);
1398
        } catch (PDOException $e) {
1399
            throw new TelegramException($e->getMessage());
1400
        }
1401
    }
1402
1403
    /**
1404
     * Get Telegram API request count for current chat / message
1405
     *
1406
     * @param int|string|null $chat_id
1407
     * @param string|null     $inline_message_id
1408
     *
1409
     * @return array|bool Array containing TOTAL and CURRENT fields or false on invalid arguments
1410
     * @throws TelegramException
1411
     */
1412
    public static function getTelegramRequestCount($chat_id = null, string $inline_message_id = null)
1413
    {
1414
        if (!self::isDbConnected()) {
1415
            return false;
1416
        }
1417
1418
        try {
1419
            $sth = self::$pdo->prepare('SELECT
1420
                (SELECT COUNT(DISTINCT `chat_id`) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_1) AS LIMIT_PER_SEC_ALL,
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_REQUEST_LIMITER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1421
                (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,
1422
                (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_minute AND `chat_id` = :chat_id_2) AS LIMIT_PER_MINUTE
1423
            ');
1424
1425
            $date        = self::getTimestamp();
1426
            $date_minute = self::getTimestamp(strtotime('-1 minute'));
1427
1428
            $sth->bindValue(':chat_id_1', $chat_id);
1429
            $sth->bindValue(':chat_id_2', $chat_id);
1430
            $sth->bindValue(':inline_message_id', $inline_message_id);
1431
            $sth->bindValue(':created_at_1', $date);
1432
            $sth->bindValue(':created_at_2', $date);
1433
            $sth->bindValue(':created_at_minute', $date_minute);
1434
1435
            $sth->execute();
1436
1437
            return $sth->fetch();
1438
        } catch (PDOException $e) {
1439
            throw new TelegramException($e->getMessage());
1440
        }
1441
    }
1442
1443
    /**
1444
     * Insert Telegram API request in db
1445
     *
1446
     * @param string $method
1447
     * @param array  $data
1448
     *
1449
     * @return bool If the insert was successful
1450
     * @throws TelegramException
1451
     */
1452
    public static function insertTelegramRequest(string $method, array $data): bool
1453
    {
1454
        if (!self::isDbConnected()) {
1455
            return false;
1456
        }
1457
1458
        try {
1459
            $sth = self::$pdo->prepare('INSERT INTO `' . TB_REQUEST_LIMITER . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_REQUEST_LIMITER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1460
                (`method`, `chat_id`, `inline_message_id`, `created_at`)
1461
                VALUES
1462
                (:method, :chat_id, :inline_message_id, :created_at);
1463
            ');
1464
1465
            $chat_id           = $data['chat_id'] ?? null;
1466
            $inline_message_id = $data['inline_message_id'] ?? null;
1467
1468
            $sth->bindValue(':chat_id', $chat_id);
1469
            $sth->bindValue(':inline_message_id', $inline_message_id);
1470
            $sth->bindValue(':method', $method);
1471
            $sth->bindValue(':created_at', self::getTimestamp());
1472
1473
            return $sth->execute();
1474
        } catch (PDOException $e) {
1475
            throw new TelegramException($e->getMessage());
1476
        }
1477
    }
1478
1479
    /**
1480
     * Bulk update the entries of any table
1481
     *
1482
     * @param string $table
1483
     * @param array  $fields_values
1484
     * @param array  $where_fields_values
1485
     *
1486
     * @return bool
1487
     * @throws TelegramException
1488
     */
1489
    public static function update(string $table, array $fields_values, array $where_fields_values): bool
1490
    {
1491
        if (empty($fields_values) || !self::isDbConnected()) {
1492
            return false;
1493
        }
1494
1495
        try {
1496
            // Building parts of query
1497
            $tokens = $fields = $where = [];
1498
1499
            // Fields with values to update
1500
            foreach ($fields_values as $field => $value) {
1501
                $token          = ':' . count($tokens);
1502
                $fields[]       = "`{$field}` = {$token}";
1503
                $tokens[$token] = $value;
1504
            }
1505
1506
            // Where conditions
1507
            foreach ($where_fields_values as $field => $value) {
1508
                $token          = ':' . count($tokens);
1509
                $where[]        = "`{$field}` = {$token}";
1510
                $tokens[$token] = $value;
1511
            }
1512
1513
            $sql = 'UPDATE `' . $table . '` SET ' . implode(', ', $fields);
1514
            $sql .= count($where) > 0 ? ' WHERE ' . implode(' AND ', $where) : '';
1515
1516
            return self::$pdo->prepare($sql)->execute($tokens);
1517
        } catch (PDOException $e) {
1518
            throw new TelegramException($e->getMessage());
1519
        }
1520
    }
1521
}
1522