DB::insertTelegramUpdate()   D
last analyzed

Complexity

Conditions 21
Paths 25

Size

Total Lines 74
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 462

Importance

Changes 0
Metric Value
cc 21
eloc 30
c 0
b 0
f 0
nc 25
nop 20
dl 0
loc 74
ccs 0
cts 27
cp 0
crap 462
rs 4.1666

How to fix   Long Method    Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\ChatBoostRemoved;
18
use Longman\TelegramBot\Entities\ChatBoostUpdated;
19
use Longman\TelegramBot\Entities\ChatJoinRequest;
20
use Longman\TelegramBot\Entities\ChatMemberUpdated;
21
use Longman\TelegramBot\Entities\ChosenInlineResult;
22
use Longman\TelegramBot\Entities\InlineQuery;
23
use Longman\TelegramBot\Entities\Message;
24
use Longman\TelegramBot\Entities\MessageReactionCountUpdated;
25
use Longman\TelegramBot\Entities\MessageReactionUpdated;
26
use Longman\TelegramBot\Entities\Payments\PreCheckoutQuery;
27
use Longman\TelegramBot\Entities\Payments\ShippingQuery;
28
use Longman\TelegramBot\Entities\Poll;
29
use Longman\TelegramBot\Entities\PollAnswer;
30
use Longman\TelegramBot\Entities\Update;
31
use Longman\TelegramBot\Entities\User;
32
use Longman\TelegramBot\Exception\TelegramException;
33
use PDO;
34
use PDOException;
35
36
class DB
37
{
38
    /**
39
     * MySQL credentials
40
     *
41
     * @var array
42
     */
43
    protected static $mysql_credentials = [];
44
45
    /**
46
     * PDO object
47
     *
48
     * @var PDO
49
     */
50
    protected static $pdo;
51
52
    /**
53
     * Table prefix
54
     *
55
     * @var string
56
     */
57
    protected static $table_prefix;
58
59
    /**
60
     * Telegram class object
61
     *
62
     * @var Telegram
63
     */
64
    protected static $telegram;
65
66
    /**
67
     * Initialize
68
     *
69
     * @param array    $credentials  Database connection details
70
     * @param Telegram $telegram     Telegram object to connect with this object
71
     * @param string   $table_prefix Table prefix
72
     * @param string   $encoding     Database character encoding
73 9
     *
74
     * @return PDO PDO database object
75
     * @throws TelegramException
76
     */
77
    public static function initialize(
78
        array $credentials,
79 9
        Telegram $telegram,
80
        $table_prefix = '',
81
        $encoding = 'utf8mb4',
82 9
    ): PDO {
83
        if (empty($credentials)) {
84
            throw new TelegramException('MySQL credentials not provided!');
85 9
        }
86
        if (isset($credentials['unix_socket'])) {
87 9
            $dsn = 'mysql:unix_socket=' . $credentials['unix_socket'];
88
        } else {
89 9
            $dsn = 'mysql:host=' . $credentials['host'];
90 9
        }
91
        $dsn .= ';dbname=' . $credentials['database'];
92
93 9
        if (!empty($credentials['port'])) {
94
            $dsn .= ';port=' . $credentials['port'];
95 9
        }
96 9
97
        $options = [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $encoding];
98
        try {
99
            $pdo = new PDO($dsn, $credentials['user'], $credentials['password'], $options);
100
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
101 9
        } catch (PDOException $e) {
102 9
            throw new TelegramException($e->getMessage());
103 9
        }
104 9
105
        self::$pdo               = $pdo;
106 9
        self::$telegram          = $telegram;
107
        self::$mysql_credentials = $credentials;
108 9
        self::$table_prefix      = $table_prefix;
109
110
        self::defineTables();
111
112
        return self::$pdo;
113
    }
114
115
    /**
116
     * External Initialize
117
     *
118
     * Let you use the class with an external already existing Pdo Mysql connection.
119
     *
120
     * @param PDO      $external_pdo_connection PDO database object
121
     * @param Telegram $telegram                Telegram object to connect with this object
122
     * @param string   $table_prefix            Table prefix
123
     *
124
     * @return PDO PDO database object
125
     * @throws TelegramException
126
     */
127
    public static function externalInitialize(
128
        PDO $external_pdo_connection,
129
        Telegram $telegram,
130
        string $table_prefix = '',
131
    ): PDO {
132
        if ($external_pdo_connection === null) {
133
            throw new TelegramException('MySQL external connection not provided!');
134
        }
135
136
        self::$pdo               = $external_pdo_connection;
137
        self::$telegram          = $telegram;
138
        self::$mysql_credentials = [];
139
        self::$table_prefix      = $table_prefix;
140
141
        self::defineTables();
142
143
        return self::$pdo;
144
    }
145 9
146
    /**
147 9
     * Define all the tables with the proper prefix
148 9
     */
149 9
    protected static function defineTables(): void
150 9
    {
151 9
        $tables = [
152 9
            'callback_query',
153 9
            'chat',
154 9
            'chat_boost_updated',
155 9
            'chat_boost_removed',
156 9
            'chat_join_request',
157 9
            'chat_member_updated',
158 9
            'chosen_inline_result',
159 9
            'edited_message',
160 9
            'inline_query',
161 9
            'message',
162 9
            'message_reaction',
163 9
            'message_reaction_count',
164 9
            'poll',
165 9
            'poll_answer',
166 9
            'pre_checkout_query',
167 9
            'request_limiter',
168 1
            'shipping_query',
169
            'telegram_update',
170
            'user',
171
            'user_chat',
172
        ];
173
        foreach ($tables as $table) {
174
            $table_name = 'TB_' . strtoupper($table);
175
            if (!defined($table_name)) {
176
                define($table_name, self::$table_prefix . $table);
177
            }
178 9
        }
179
    }
180 9
181
    /**
182
     * Check if database connection has been created
183
     *
184
     * @return bool
185
     */
186
    public static function isDbConnected(): bool
187
    {
188
        return self::$pdo !== null;
189
    }
190
191
    /**
192
     * Get the PDO object of the connected database
193
     *
194
     * @return PDO|null
195
     */
196
    public static function getPdo(): ?PDO
197
    {
198
        return self::$pdo;
199
    }
200
201
    /**
202
     * Fetch update(s) from DB
203
     *
204
     * @param int    $limit Limit the number of updates to fetch
205
     * @param string $id    Check for unique update id
206
     *
207
     * @return array|bool Fetched data or false if not connected
208
     * @throws TelegramException
209
     */
210
    public static function selectTelegramUpdate(int $limit = 0, string $id = '')
211
    {
212
        if (!self::isDbConnected()) {
213
            return false;
214
        }
215
216
        try {
217
            $sql = '
218
                SELECT `id`
219
                FROM `' . TB_TELEGRAM_UPDATE . '`
220
            ';
221
222
            if ($id !== '') {
223
                $sql .= ' WHERE `id` = :id';
224
            } else {
225
                $sql .= ' ORDER BY `id` DESC';
226
            }
227
228
            if ($limit > 0) {
229
                $sql .= ' LIMIT :limit';
230
            }
231
232
            $sth = self::$pdo->prepare($sql);
233
234
            if ($limit > 0) {
235
                $sth->bindValue(':limit', $limit, PDO::PARAM_INT);
236
            }
237
            if ($id !== '') {
238
                $sth->bindValue(':id', $id);
239
            }
240
241
            $sth->execute();
242
243
            return $sth->fetchAll(PDO::FETCH_ASSOC);
244
        } catch (PDOException $e) {
245
            throw new TelegramException($e->getMessage());
246
        }
247
    }
248
249
    /**
250
     * Fetch message(s) from DB
251
     *
252
     * @param int $limit Limit the number of messages to fetch
253
     *
254
     * @return array|bool Fetched data or false if not connected
255
     * @throws TelegramException
256
     */
257
    public static function selectMessages(int $limit = 0)
258
    {
259
        if (!self::isDbConnected()) {
260
            return false;
261
        }
262
263
        try {
264
            $sql = '
265
                SELECT *
266
                FROM `' . TB_MESSAGE . '`
267
                ORDER BY `id` DESC
268
            ';
269
270
            if ($limit > 0) {
271
                $sql .= ' LIMIT :limit';
272
            }
273
274
            $sth = self::$pdo->prepare($sql);
275
276
            if ($limit > 0) {
277
                $sth->bindValue(':limit', $limit, PDO::PARAM_INT);
278
            }
279
280
            $sth->execute();
281
282
            return $sth->fetchAll(PDO::FETCH_ASSOC);
283
        } catch (PDOException $e) {
284
            throw new TelegramException($e->getMessage());
285
        }
286
    }
287 7
288
    /**
289 7
     * Convert from unix timestamp to timestamp
290
     *
291
     * @param ?int $unixtime Unix timestamp (if empty, current timestamp is used)
292
     *
293
     * @return string
294
     */
295
    protected static function getTimestamp(?int $unixtime = null): string
296
    {
297
        return date('Y-m-d H:i:s', $unixtime ?? time());
298
    }
299
300
    /**
301
     * Convert array of Entity items to a JSON array
302 6
     *
303
     * @param array $entities
304 6
     * @param mixed $default
305 6
     *
306
     * @return mixed
307
     * @todo Find a better way, as json_* functions are very heavy
308
     *
309
     */
310
    public static function entitiesArrayToJson(array $entities, $default = null)
311
    {
312
        if (empty($entities)) {
313
            return $default;
314
        }
315
316
        // Convert each Entity item into an object based on its JSON reflection
317
        $json_entities = array_map(function ($entity) {
318
            return json_decode($entity, true);
319
        }, $entities);
320
321
        return json_encode($json_entities);
322
    }
323
324
    /**
325
     * Insert entry to telegram_update table
326
     *
327
     * @throws TelegramException
328
     */
329
    protected static function insertTelegramUpdate(
330
        int $update_id,
331
        ?int $chat_id = null,
332
        ?int $message_id = null,
333
        ?int $edited_message_id = null,
334
        ?int $channel_post_id = null,
335
        ?int $edited_channel_post_id = null,
336
        ?string $message_reaction_id = null,
337
        ?string $message_reaction_count_id = null,
338
        ?string $inline_query_id = null,
339
        ?string $chosen_inline_result_id = null,
340
        ?string $callback_query_id = null,
341
        ?string $shipping_query_id = null,
342
        ?string $pre_checkout_query_id = null,
343
        ?string $poll_id = null,
344
        ?string $poll_answer_poll_id = null,
345
        ?string $my_chat_member_updated_id = null,
346
        ?string $chat_member_updated_id = null,
347
        ?string $chat_join_request_id = null,
348
        ?string $chat_boost_updated_id = null,
349
        ?string $chat_boost_removed_id = null,
350
    ): ?bool {
351
        if ($message_id === null && $edited_message_id === null && $channel_post_id === null && $edited_channel_post_id === null && $message_reaction_id === null && $message_reaction_count_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 && $chat_boost_updated_id === null && $chat_boost_removed_id === null) {
352
            throw new TelegramException('message_id, edited_message_id, channel_post_id, edited_channel_post_id, message_reaction_id, message_reaction_count_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, chat_join_request_id, chat_boost_updated_id, chat_boost_removed_id are all null');
353
        }
354
355
        if (!self::isDbConnected()) {
356
            return false;
357
        }
358
359
        try {
360
            $sth = self::$pdo->prepare('
361
                INSERT IGNORE INTO `' . TB_TELEGRAM_UPDATE . '`
362
                (
363
                    `id`, `chat_id`, `message_id`, `edited_message_id`,
364
                    `channel_post_id`, `edited_channel_post_id`, `message_reaction_id`, `message_reaction_count_id`,
365
                    `inline_query_id`, `chosen_inline_result_id`,
366
                    `callback_query_id`, `shipping_query_id`, `pre_checkout_query_id`,
367
                    `poll_id`, `poll_answer_poll_id`, `my_chat_member_updated_id`, `chat_member_updated_id`,
368
                    `chat_join_request_id`, `chat_boost_updated_id`, `chat_boost_removed_id`
369
                ) VALUES (
370
                    :id, :chat_id, :message_id, :edited_message_id,
371
                    :channel_post_id, :edited_channel_post_id, :message_reaction_id, :message_reaction_count_id,
372
                    :inline_query_id, :chosen_inline_result_id,
373
                    :callback_query_id, :shipping_query_id, :pre_checkout_query_id,
374
                    :poll_id, :poll_answer_poll_id, :my_chat_member_updated_id, :chat_member_updated_id,
375
                    :chat_join_request_id, :chat_boost_updated_id, :chat_boost_removed_id
376
                )
377
            ');
378
379
            $sth->bindValue(':id', $update_id);
380
            $sth->bindValue(':chat_id', $chat_id);
381
            $sth->bindValue(':message_id', $message_id);
382
            $sth->bindValue(':edited_message_id', $edited_message_id);
383
            $sth->bindValue(':channel_post_id', $channel_post_id);
384
            $sth->bindValue(':edited_channel_post_id', $edited_channel_post_id);
385
            $sth->bindValue(':message_reaction_id', $message_reaction_id);
386
            $sth->bindValue(':message_reaction_count_id', $message_reaction_count_id);
387
            $sth->bindValue(':inline_query_id', $inline_query_id);
388
            $sth->bindValue(':chosen_inline_result_id', $chosen_inline_result_id);
389
            $sth->bindValue(':callback_query_id', $callback_query_id);
390
            $sth->bindValue(':shipping_query_id', $shipping_query_id);
391
            $sth->bindValue(':pre_checkout_query_id', $pre_checkout_query_id);
392
            $sth->bindValue(':poll_id', $poll_id);
393
            $sth->bindValue(':poll_answer_poll_id', $poll_answer_poll_id);
394
            $sth->bindValue(':my_chat_member_updated_id', $my_chat_member_updated_id);
395
            $sth->bindValue(':chat_member_updated_id', $chat_member_updated_id);
396
            $sth->bindValue(':chat_join_request_id', $chat_join_request_id);
397
            $sth->bindValue(':chat_boost_updated_id', $chat_boost_updated_id);
398
            $sth->bindValue(':chat_boost_removed_id', $chat_boost_removed_id);
399
400
            return $sth->execute();
401
        } catch (PDOException $e) {
402
            throw new TelegramException($e->getMessage());
403
        }
404
    }
405
406
    /**
407
     * Insert users and save their connection to chats
408
     *
409
     * @param User        $user
410
     * @param string|null $date
411
     * @param Chat|null   $chat
412
     *
413
     * @return bool If the insert was successful
414
     * @throws TelegramException
415 6
     */
416
    public static function insertUser(User $user, ?string $date = null, ?Chat $chat = null): bool
417 6
    {
418
        if (!self::isDbConnected()) {
419
            return false;
420
        }
421
422 6
        try {
423 6
            $sth = self::$pdo->prepare('
424
                INSERT INTO `' . TB_USER . '`
425
                (`id`, `is_bot`, `username`, `first_name`, `last_name`, `language_code`, `is_premium`, `added_to_attachment_menu`, `created_at`, `updated_at`)
426
                VALUES
427
                (:id, :is_bot, :username, :first_name, :last_name, :language_code, :is_premium, :added_to_attachment_menu, :created_at, :updated_at)
428
                ON DUPLICATE KEY UPDATE
429
                    `is_bot`                   = VALUES(`is_bot`),
430
                    `username`                 = VALUES(`username`),
431
                    `first_name`               = VALUES(`first_name`),
432
                    `last_name`                = VALUES(`last_name`),
433
                    `language_code`            = VALUES(`language_code`),
434
                    `is_premium`               = VALUES(`is_premium`),
435
                    `added_to_attachment_menu` = VALUES(`added_to_attachment_menu`),
436 6
                    `updated_at`               = VALUES(`updated_at`)
437
            ');
438 6
439 6
            $sth->bindValue(':id', $user->getId());
440 6
            $sth->bindValue(':is_bot', $user->getIsBot(), PDO::PARAM_INT);
441 6
            $sth->bindValue(':username', $user->getUsername());
442 6
            $sth->bindValue(':first_name', $user->getFirstName());
443 6
            $sth->bindValue(':last_name', $user->getLastName());
444 6
            $sth->bindValue(':language_code', $user->getLanguageCode());
445 6
            $sth->bindValue(':is_premium', $user->getIsPremium(), PDO::PARAM_INT);
446 6
            $sth->bindValue(':added_to_attachment_menu', $user->getAddedToAttachmentMenu(), PDO::PARAM_INT);
447 6
            $date = $date ?: self::getTimestamp();
448 6
            $sth->bindValue(':created_at', $date);
449
            $sth->bindValue(':updated_at', $date);
450 6
451
            $status = $sth->execute();
452
        } catch (PDOException $e) {
453
            throw new TelegramException($e->getMessage());
454
        }
455
456 6
        // Also insert the relationship to the chat into the user_chat table
457
        if ($chat) {
458 6
            try {
459 6
                $sth = self::$pdo->prepare('
460
                    INSERT IGNORE INTO `' . TB_USER_CHAT . '`
461
                    (`user_id`, `chat_id`)
462
                    VALUES
463 6
                    (:user_id, :chat_id)
464
                ');
465 6
466 6
                $sth->bindValue(':user_id', $user->getId());
467
                $sth->bindValue(':chat_id', $chat->getId());
468 6
469
                $status = $sth->execute();
470
            } catch (PDOException $e) {
471
                throw new TelegramException($e->getMessage());
472
            }
473
        }
474 6
475
        return $status;
476
    }
477
478
    /**
479
     * Insert chat
480
     *
481
     * @param Chat        $chat
482
     * @param string|null $date
483
     * @param int|null    $migrate_to_chat_id
484
     *
485
     * @return bool If the insert was successful
486
     * @throws TelegramException
487 6
     */
488
    public static function insertChat(Chat $chat, ?string $date = null, ?int $migrate_to_chat_id = null): ?bool
489 6
    {
490
        if (!self::isDbConnected()) {
491
            return false;
492
        }
493
494 6
        try {
495 6
            $sth = self::$pdo->prepare('
496
                INSERT IGNORE INTO `' . TB_CHAT . '`
497
                (`id`, `type`, `title`, `username`, `first_name`, `last_name`, `is_forum`, `created_at` ,`updated_at`, `old_id`)
498
                VALUES
499
                (:id, :type, :title, :username, :first_name, :last_name, :is_forum, :created_at, :updated_at, :old_id)
500
                ON DUPLICATE KEY UPDATE
501
                    `type`                           = VALUES(`type`),
502
                    `title`                          = VALUES(`title`),
503
                    `username`                       = VALUES(`username`),
504
                    `first_name`                     = VALUES(`first_name`),
505
                    `last_name`                      = VALUES(`last_name`),
506
                    `is_forum`                       = VALUES(`is_forum`),
507 6
                    `updated_at`                     = VALUES(`updated_at`)
508
            ');
509 6
510 6
            $chat_id   = $chat->getId();
511
            $chat_type = $chat->getType();
512 6
513
            if ($migrate_to_chat_id !== null) {
514
                $chat_type = 'supergroup';
515
516
                $sth->bindValue(':id', $migrate_to_chat_id);
517
                $sth->bindValue(':old_id', $chat_id);
518 6
            } else {
519 6
                $sth->bindValue(':id', $chat_id);
520
                $sth->bindValue(':old_id', $migrate_to_chat_id);
521
            }
522 6
523 6
            $sth->bindValue(':type', $chat_type);
524 6
            $sth->bindValue(':title', $chat->getTitle());
525 6
            $sth->bindValue(':username', $chat->getUsername());
526 6
            $sth->bindValue(':first_name', $chat->getFirstName());
527 6
            $sth->bindValue(':last_name', $chat->getLastName());
528 6
            $sth->bindValue(':is_forum', $chat->getIsForum());
529 6
            $date = $date ?: self::getTimestamp();
530 6
            $sth->bindValue(':created_at', $date);
531
            $sth->bindValue(':updated_at', $date);
532 6
533
            return $sth->execute();
534
        } catch (PDOException $e) {
535
            throw new TelegramException($e->getMessage());
536
        }
537
    }
538
539
    /**
540
     * Insert request into database
541
     *
542
     * @param Update $update
543
     *
544
     * @return bool
545
     * @throws TelegramException
546
     * @todo self::$pdo->lastInsertId() - unsafe usage if expected previous insert fails?
547
     *
548
     */
549
    public static function insertRequest(Update $update): bool
550
    {
551
        if (!self::isDbConnected()) {
552
            return false;
553
        }
554
555
        $chat_id                   = null;
556
        $message_id                = null;
557
        $edited_message_id         = null;
558
        $channel_post_id           = null;
559
        $edited_channel_post_id    = null;
560
        $message_reaction_id       = null;
561
        $message_reaction_count_id = null;
562
        $inline_query_id           = null;
563
        $chosen_inline_result_id   = null;
564
        $callback_query_id         = null;
565
        $shipping_query_id         = null;
566
        $pre_checkout_query_id     = null;
567
        $poll_id                   = null;
568
        $poll_answer_poll_id       = null;
569
        $my_chat_member_updated_id = null;
570
        $chat_member_updated_id    = null;
571
        $chat_join_request_id      = null;
572
        $chat_boost_updated_id     = null;
573
        $chat_boost_removed_id     = null;
574
575
        if (($message = $update->getMessage()) && self::insertMessageRequest($message)) {
576
            $chat_id    = $message->getChat()->getId();
577
            $message_id = $message->getMessageId();
578
        } elseif (($edited_message = $update->getEditedMessage()) && self::insertEditedMessageRequest($edited_message)) {
579
            $chat_id           = $edited_message->getChat()->getId();
580
            $edited_message_id = (int) self::$pdo->lastInsertId();
581
        } elseif (($channel_post = $update->getChannelPost()) && self::insertMessageRequest($channel_post)) {
582
            $chat_id         = $channel_post->getChat()->getId();
583
            $channel_post_id = $channel_post->getMessageId();
584
        } elseif (($edited_channel_post = $update->getEditedChannelPost()) && self::insertEditedMessageRequest($edited_channel_post)) {
585
            $chat_id                = $edited_channel_post->getChat()->getId();
586
            $edited_channel_post_id = (int) self::$pdo->lastInsertId();
587
        } elseif (($message_reaction = $update->getMessageReaction()) && self::insertMessageReaction($message_reaction)) {
588
            $chat_id             = $message_reaction->getChat()->getId();
589
            $message_id          = $message_reaction->getMessageId();
590
            $message_reaction_id = self::$pdo->lastInsertId();
591
        } elseif (($message_reaction_count = $update->getMessageReactionCount()) && self::insertMessageReactionCount($message_reaction_count)) {
592
            $chat_id                   = $message_reaction_count->getChat()->getId();
593
            $message_id                = $message_reaction_count->getMessageId();
594
            $message_reaction_count_id = self::$pdo->lastInsertId();
595
        } elseif (($inline_query = $update->getInlineQuery()) && self::insertInlineQueryRequest($inline_query)) {
596
            $inline_query_id = $inline_query->getId();
597
        } elseif (($chosen_inline_result = $update->getChosenInlineResult()) && self::insertChosenInlineResultRequest($chosen_inline_result)) {
598
            $chosen_inline_result_id = self::$pdo->lastInsertId();
599
        } elseif (($callback_query = $update->getCallbackQuery()) && self::insertCallbackQueryRequest($callback_query)) {
600
            $callback_query_id = $callback_query->getId();
601
        } elseif (($shipping_query = $update->getShippingQuery()) && self::insertShippingQueryRequest($shipping_query)) {
602
            $shipping_query_id = $shipping_query->getId();
603
        } elseif (($pre_checkout_query = $update->getPreCheckoutQuery()) && self::insertPreCheckoutQueryRequest($pre_checkout_query)) {
604
            $pre_checkout_query_id = $pre_checkout_query->getId();
605
        } elseif (($poll = $update->getPoll()) && self::insertPollRequest($poll)) {
606
            $poll_id = $poll->getId();
607
        } elseif (($poll_answer = $update->getPollAnswer()) && self::insertPollAnswerRequest($poll_answer)) {
608
            $poll_answer_poll_id = $poll_answer->getPollId();
609
        } elseif (($my_chat_member = $update->getMyChatMember()) && self::insertChatMemberUpdatedRequest($my_chat_member)) {
610
            $my_chat_member_updated_id = self::$pdo->lastInsertId();
611
        } elseif (($chat_member = $update->getChatMember()) && self::insertChatMemberUpdatedRequest($chat_member)) {
612
            $chat_member_updated_id = self::$pdo->lastInsertId();
613
        } elseif (($chat_join_request = $update->getChatJoinRequest()) && self::insertChatJoinRequestRequest($chat_join_request)) {
614
            $chat_join_request_id = self::$pdo->lastInsertId();
615
        } elseif (($chat_boost_updated = $update->getChatBoost()) && self::insertChatBoostUpdatedRequest($chat_boost_updated)) {
616
            $chat_boost_updated_id = self::$pdo->lastInsertId();
617
        } elseif (($chat_boost_removed = $update->getRemovedChatBoost()) && self::insertChatBoostRemovedRequest($chat_boost_removed)) {
618
            $chat_boost_removed_id = self::$pdo->lastInsertId();
619
        } else {
620
            return false;
621
        }
622
623
        return self::insertTelegramUpdate(
624
            $update->getUpdateId(),
625
            $chat_id,
626
            $message_id,
627
            $edited_message_id,
628
            $channel_post_id,
629
            $edited_channel_post_id,
630
            $message_reaction_id,
631
            $message_reaction_count_id,
632
            $inline_query_id,
633
            $chosen_inline_result_id,
634
            $callback_query_id,
635
            $shipping_query_id,
636
            $pre_checkout_query_id,
637
            $poll_id,
638
            $poll_answer_poll_id,
639
            $my_chat_member_updated_id,
640
            $chat_member_updated_id,
641
            $chat_join_request_id,
642
            $chat_boost_updated_id,
643
            $chat_boost_removed_id,
644
        );
645
    }
646
647
    public static function insertMessageReaction(MessageReactionUpdated $message_reaction): bool
648
    {
649
        if (!self::isDbConnected()) {
650
            return false;
651
        }
652
653
        try {
654
            $sth = self::$pdo->prepare('
655
                INSERT IGNORE INTO `' . TB_MESSAGE_REACTION . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_MESSAGE_REACTION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
656
                (`chat_id`, `message_id`, `user_id`, `actor_chat_id`, `old_reaction`, `new_reaction`, `created_at`)
657
                VALUES
658
                (:chat_id, :message_id, :user_id, :actor_chat_id, :old_reaction, :new_reaction, :created_at)
659
            ');
660
661
            $date          = self::getTimestamp($message_reaction->getDate());
662
            $chat_id       = null;
663
            $user_id       = null;
664
            $actor_chat_id = null;
665
666
            if ($chat = $message_reaction->getChat()) {
667
                $chat_id = $chat->getId();
668
                self::insertChat($chat, $date);
669
            }
670
            if ($user = $message_reaction->getUser()) {
671
                $user_id = $user->getId();
672
                self::insertUser($user, $date);
673
            }
674
            if ($actor_chat = $message_reaction->getActorChat()) {
675
                $actor_chat_id = $actor_chat->getId();
676
                self::insertChat($actor_chat, $date);
677
            }
678
679
            $sth->bindValue(':chat_id', $chat_id);
680
            $sth->bindValue(':message_id', $message_reaction->getMessageId());
681
            $sth->bindValue(':user_id', $user_id);
682
            $sth->bindValue(':actor_chat_id', $actor_chat_id);
683
            $sth->bindValue(':old_reaction', self::entitiesArrayToJson($message_reaction->getOldReaction() ?: []));
684
            $sth->bindValue(':new_reaction', self::entitiesArrayToJson($message_reaction->getNewReaction() ?: []));
685
            $sth->bindValue(':created_at', $date);
686
687
            return $sth->execute();
688
        } catch (PDOException $e) {
689
            throw new TelegramException($e->getMessage());
690
        }
691
    }
692
693
    public static function insertMessageReactionCount(MessageReactionCountUpdated $message_reaction_count): bool
694
    {
695
        if (!self::isDbConnected()) {
696
            return false;
697
        }
698
699
        try {
700
            $sth = self::$pdo->prepare('
701
                INSERT IGNORE INTO `' . TB_MESSAGE_REACTION_COUNT . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_MESSAGE_REACTION_COUNT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
702
                (`chat_id`, `message_id`, `reactions`, `created_at`)
703
                VALUES
704
                (:chat_id, :message_id, :reactions, :created_at)
705
            ');
706
707
            $date    = self::getTimestamp($message_reaction_count->getDate());
708
            $chat_id = null;
709
710
            if ($chat = $message_reaction->getChat()) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $message_reaction does not exist. Did you maybe mean $message_reaction_count?
Loading history...
711
                $chat_id = $chat->getId();
712
                self::insertChat($chat, $date);
713
            }
714
715
            $sth->bindValue(':chat_id', $chat_id);
716
            $sth->bindValue(':message_id', $message_reaction_count->getMessageId());
717
            $sth->bindValue(':reactions', $message_reaction_count->getReactions());
718
            $sth->bindValue(':created_at', $date);
719
720
            return $sth->execute();
721
        } catch (PDOException $e) {
722
            throw new TelegramException($e->getMessage());
723
        }
724
    }
725
726
    /**
727
     * Insert inline query request into database
728
     *
729
     * @param InlineQuery $inline_query
730
     *
731
     * @return bool If the insert was successful
732
     * @throws TelegramException
733
     */
734
    public static function insertInlineQueryRequest(InlineQuery $inline_query): bool
735
    {
736
        if (!self::isDbConnected()) {
737
            return false;
738
        }
739
740
        try {
741
            $sth = self::$pdo->prepare('
742
                INSERT IGNORE INTO `' . TB_INLINE_QUERY . '`
743
                (`id`, `user_id`, `location`, `query`, `offset`, `chat_type`, `created_at`)
744
                VALUES
745
                (:id, :user_id, :location, :query, :offset, :chat_type, :created_at)
746
            ');
747
748
            $date    = self::getTimestamp();
749
            $user_id = null;
750
751
            if ($user = $inline_query->getFrom()) {
752
                $user_id = $user->getId();
753
                self::insertUser($user, $date);
754
            }
755
756
            $sth->bindValue(':id', $inline_query->getId());
757
            $sth->bindValue(':user_id', $user_id);
758
            $sth->bindValue(':location', $inline_query->getLocation());
759
            $sth->bindValue(':query', $inline_query->getQuery());
760
            $sth->bindValue(':offset', $inline_query->getOffset());
761
            $sth->bindValue(':chat_type', $inline_query->getChatType());
762
            $sth->bindValue(':created_at', $date);
763
764
            return $sth->execute();
765
        } catch (PDOException $e) {
766
            throw new TelegramException($e->getMessage());
767
        }
768
    }
769
770
    /**
771
     * Insert chosen inline result request into database
772
     *
773
     * @param ChosenInlineResult $chosen_inline_result
774
     *
775
     * @return bool If the insert was successful
776
     * @throws TelegramException
777
     */
778
    public static function insertChosenInlineResultRequest(ChosenInlineResult $chosen_inline_result): bool
779
    {
780
        if (!self::isDbConnected()) {
781
            return false;
782
        }
783
784
        try {
785
            $sth = self::$pdo->prepare('
786
                INSERT INTO `' . TB_CHOSEN_INLINE_RESULT . '`
787
                (`result_id`, `user_id`, `location`, `inline_message_id`, `query`, `created_at`)
788
                VALUES
789
                (:result_id, :user_id, :location, :inline_message_id, :query, :created_at)
790
            ');
791
792
            $date    = self::getTimestamp();
793
            $user_id = null;
794
795
            if ($user = $chosen_inline_result->getFrom()) {
796
                $user_id = $user->getId();
797
                self::insertUser($user, $date);
798
            }
799
800
            $sth->bindValue(':result_id', $chosen_inline_result->getResultId());
801
            $sth->bindValue(':user_id', $user_id);
802
            $sth->bindValue(':location', $chosen_inline_result->getLocation());
803
            $sth->bindValue(':inline_message_id', $chosen_inline_result->getInlineMessageId());
804
            $sth->bindValue(':query', $chosen_inline_result->getQuery());
805
            $sth->bindValue(':created_at', $date);
806
807
            return $sth->execute();
808
        } catch (PDOException $e) {
809
            throw new TelegramException($e->getMessage());
810
        }
811
    }
812
813
    /**
814
     * Insert callback query request into database
815
     *
816
     * @param CallbackQuery $callback_query
817
     *
818
     * @return bool If the insert was successful
819
     * @throws TelegramException
820
     */
821
    public static function insertCallbackQueryRequest(CallbackQuery $callback_query): bool
822
    {
823
        if (!self::isDbConnected()) {
824
            return false;
825
        }
826
827
        try {
828
            $sth = self::$pdo->prepare('
829
                INSERT IGNORE INTO `' . TB_CALLBACK_QUERY . '`
830
                (`id`, `user_id`, `chat_id`, `message_id`, `inline_message_id`, `chat_instance`, `data`, `game_short_name`, `created_at`)
831
                VALUES
832
                (:id, :user_id, :chat_id, :message_id, :inline_message_id, :chat_instance, :data, :game_short_name, :created_at)
833
            ');
834
835
            $date    = self::getTimestamp();
836
            $user_id = null;
837
838
            if ($user = $callback_query->getFrom()) {
839
                $user_id = $user->getId();
840
                self::insertUser($user, $date);
841
            }
842
843
            $chat_id    = null;
844
            $message_id = null;
845
            if ($message = $callback_query->getMessage()) {
846
                $chat_id    = $message->getChat()->getId();
0 ignored issues
show
Bug introduced by
The method getChat() does not exist on Longman\TelegramBot\Enti...aybeInaccessibleMessage. Since it exists in all sub-types, consider adding an abstract or default implementation to Longman\TelegramBot\Enti...aybeInaccessibleMessage. ( Ignorable by Annotation )

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

846
                $chat_id    = $message->/** @scrutinizer ignore-call */ getChat()->getId();
Loading history...
847
                $message_id = $message->getMessageId();
0 ignored issues
show
Bug introduced by
The method getMessageId() does not exist on Longman\TelegramBot\Enti...aybeInaccessibleMessage. Since it exists in all sub-types, consider adding an abstract or default implementation to Longman\TelegramBot\Enti...aybeInaccessibleMessage. ( Ignorable by Annotation )

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

847
                /** @scrutinizer ignore-call */ 
848
                $message_id = $message->getMessageId();
Loading history...
848
849
                $is_message = self::$pdo->query('
850
                    SELECT *
851
                    FROM `' . TB_MESSAGE . '`
852
                    WHERE `id` = ' . $message_id . '
853
                      AND `chat_id` = ' . $chat_id . '
854
                    LIMIT 1
855
                ')->rowCount();
856
857
                if ($is_message) {
858
                    self::insertEditedMessageRequest($message);
859
                } else {
860
                    self::insertMessageRequest($message);
861
                }
862
            }
863
864
            $sth->bindValue(':id', $callback_query->getId());
865
            $sth->bindValue(':user_id', $user_id);
866
            $sth->bindValue(':chat_id', $chat_id);
867
            $sth->bindValue(':message_id', $message_id);
868
            $sth->bindValue(':inline_message_id', $callback_query->getInlineMessageId());
869
            $sth->bindValue(':chat_instance', $callback_query->getChatInstance());
870
            $sth->bindValue(':data', $callback_query->getData());
871
            $sth->bindValue(':game_short_name', $callback_query->getGameShortName());
872
            $sth->bindValue(':created_at', $date);
873
874
            return $sth->execute();
875
        } catch (PDOException $e) {
876
            throw new TelegramException($e->getMessage());
877
        }
878
    }
879
880
    /**
881
     * Insert shipping query request into database
882
     *
883
     * @param ShippingQuery $shipping_query
884
     *
885
     * @return bool If the insert was successful
886
     * @throws TelegramException
887
     */
888
    public static function insertShippingQueryRequest(ShippingQuery $shipping_query): bool
889
    {
890
        if (!self::isDbConnected()) {
891
            return false;
892
        }
893
894
        try {
895
            $sth = self::$pdo->prepare('
896
                INSERT IGNORE INTO `' . TB_SHIPPING_QUERY . '`
897
                (`id`, `user_id`, `invoice_payload`, `shipping_address`, `created_at`)
898
                VALUES
899
                (:id, :user_id, :invoice_payload, :shipping_address, :created_at)
900
            ');
901
902
            $date    = self::getTimestamp();
903
            $user_id = null;
904
905
            if ($user = $shipping_query->getFrom()) {
906
                $user_id = $user->getId();
907
                self::insertUser($user, $date);
908
            }
909
910
            $sth->bindValue(':id', $shipping_query->getId());
911
            $sth->bindValue(':user_id', $user_id);
912
            $sth->bindValue(':invoice_payload', $shipping_query->getInvoicePayload());
913
            $sth->bindValue(':shipping_address', $shipping_query->getShippingAddress());
914
            $sth->bindValue(':created_at', $date);
915
916
            return $sth->execute();
917
        } catch (PDOException $e) {
918
            throw new TelegramException($e->getMessage());
919
        }
920
    }
921
922
    /**
923
     * Insert pre checkout query request into database
924
     *
925
     * @param PreCheckoutQuery $pre_checkout_query
926
     *
927
     * @return bool If the insert was successful
928
     * @throws TelegramException
929
     */
930
    public static function insertPreCheckoutQueryRequest(PreCheckoutQuery $pre_checkout_query): bool
931
    {
932
        if (!self::isDbConnected()) {
933
            return false;
934
        }
935
936
        try {
937
            $sth = self::$pdo->prepare('
938
                INSERT IGNORE INTO `' . TB_PRE_CHECKOUT_QUERY . '`
939
                (`id`, `user_id`, `currency`, `total_amount`, `invoice_payload`, `shipping_option_id`, `order_info`, `created_at`)
940
                VALUES
941
                (:id, :user_id, :currency, :total_amount, :invoice_payload, :shipping_option_id, :order_info, :created_at)
942
            ');
943
944
            $date    = self::getTimestamp();
945
            $user_id = null;
946
947
            if ($user = $pre_checkout_query->getFrom()) {
948
                $user_id = $user->getId();
949
                self::insertUser($user, $date);
950
            }
951
952
            $sth->bindValue(':id', $pre_checkout_query->getId());
953
            $sth->bindValue(':user_id', $user_id);
954
            $sth->bindValue(':currency', $pre_checkout_query->getCurrency());
955
            $sth->bindValue(':total_amount', $pre_checkout_query->getTotalAmount());
956
            $sth->bindValue(':invoice_payload', $pre_checkout_query->getInvoicePayload());
957
            $sth->bindValue(':shipping_option_id', $pre_checkout_query->getShippingOptionId());
958
            $sth->bindValue(':order_info', $pre_checkout_query->getOrderInfo());
959
            $sth->bindValue(':created_at', $date);
960
961
            return $sth->execute();
962
        } catch (PDOException $e) {
963
            throw new TelegramException($e->getMessage());
964
        }
965
    }
966
967
    /**
968
     * Insert poll request into database
969
     *
970
     * @param Poll $poll
971
     *
972
     * @return bool If the insert was successful
973
     * @throws TelegramException
974
     */
975
    public static function insertPollRequest(Poll $poll): bool
976
    {
977
        if (!self::isDbConnected()) {
978
            return false;
979
        }
980
981
        try {
982
            $sth = self::$pdo->prepare('
983
                INSERT INTO `' . TB_POLL . '`
984
                (`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`)
985
                VALUES
986
                (: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)
987
                ON DUPLICATE KEY UPDATE
988
                    `options`                 = VALUES(`options`),
989
                    `total_voter_count`       = VALUES(`total_voter_count`),
990
                    `is_closed`               = VALUES(`is_closed`),
991
                    `is_anonymous`            = VALUES(`is_anonymous`),
992
                    `type`                    = VALUES(`type`),
993
                    `allows_multiple_answers` = VALUES(`allows_multiple_answers`),
994
                    `correct_option_id`       = VALUES(`correct_option_id`),
995
                    `explanation`             = VALUES(`explanation`),
996
                    `explanation_entities`    = VALUES(`explanation_entities`),
997
                    `open_period`             = VALUES(`open_period`),
998
                    `close_date`              = VALUES(`close_date`)
999
            ');
1000
1001
            $sth->bindValue(':id', $poll->getId());
1002
            $sth->bindValue(':question', $poll->getQuestion());
1003
            $sth->bindValue(':options', self::entitiesArrayToJson($poll->getOptions() ?: []));
1004
            $sth->bindValue(':total_voter_count', $poll->getTotalVoterCount());
1005
            $sth->bindValue(':is_closed', $poll->getIsClosed(), PDO::PARAM_INT);
1006
            $sth->bindValue(':is_anonymous', $poll->getIsAnonymous(), PDO::PARAM_INT);
1007
            $sth->bindValue(':type', $poll->getType());
1008
            $sth->bindValue(':allows_multiple_answers', $poll->getAllowsMultipleAnswers(), PDO::PARAM_INT);
1009
            $sth->bindValue(':correct_option_id', $poll->getCorrectOptionId());
1010
            $sth->bindValue(':explanation', $poll->getExplanation());
1011
            $sth->bindValue(':explanation_entities', self::entitiesArrayToJson($poll->getExplanationEntities() ?: []));
1012
            $sth->bindValue(':open_period', $poll->getOpenPeriod());
1013
            $sth->bindValue(':close_date', self::getTimestamp($poll->getCloseDate()));
1014
            $sth->bindValue(':created_at', self::getTimestamp());
1015
1016
            return $sth->execute();
1017
        } catch (PDOException $e) {
1018
            throw new TelegramException($e->getMessage());
1019
        }
1020
    }
1021
1022
    /**
1023
     * Insert poll answer request into database
1024
     *
1025
     * @param PollAnswer $poll_answer
1026
     *
1027
     * @return bool If the insert was successful
1028
     * @throws TelegramException
1029
     */
1030
    public static function insertPollAnswerRequest(PollAnswer $poll_answer): bool
1031
    {
1032
        if (!self::isDbConnected()) {
1033
            return false;
1034
        }
1035
1036
        try {
1037
            $sth = self::$pdo->prepare('
1038
                INSERT INTO `' . TB_POLL_ANSWER . '`
1039
                (`poll_id`, `user_id`, `option_ids`, `created_at`)
1040
                VALUES
1041
                (:poll_id, :user_id, :option_ids, :created_at)
1042
                ON DUPLICATE KEY UPDATE
1043
                    `option_ids` = VALUES(`option_ids`)
1044
            ');
1045
1046
            $date    = self::getTimestamp();
1047
            $user_id = null;
1048
1049
            if ($user = $poll_answer->getUser()) {
1050
                $user_id = $user->getId();
1051
                self::insertUser($user, $date);
1052
            }
1053
1054
            $sth->bindValue(':poll_id', $poll_answer->getPollId());
1055
            $sth->bindValue(':user_id', $user_id);
1056
            $sth->bindValue(':option_ids', json_encode($poll_answer->getOptionIds()));
1057
            $sth->bindValue(':created_at', $date);
1058
1059
            return $sth->execute();
1060
        } catch (PDOException $e) {
1061
            throw new TelegramException($e->getMessage());
1062
        }
1063
    }
1064
1065
    /**
1066
     * Insert chat member updated request into database
1067
     *
1068
     * @param ChatMemberUpdated $chat_member_updated
1069
     *
1070 6
     * @return bool If the insert was successful
1071
     * @throws TelegramException
1072 6
     */
1073
    public static function insertChatMemberUpdatedRequest(ChatMemberUpdated $chat_member_updated): bool
1074
    {
1075
        if (!self::isDbConnected()) {
1076 6
            return false;
1077
        }
1078
1079 6
        try {
1080 6
            $sth = self::$pdo->prepare('
1081
                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...
1082 6
                (`chat_id`, `user_id`, `date`, `old_chat_member`, `new_chat_member`, `invite_link`, `created_at`)
1083 6
                VALUES
1084
                (:chat_id, :user_id, :date, :old_chat_member, :new_chat_member, :invite_link, :created_at)
1085
            ');
1086
1087
            $date    = self::getTimestamp();
1088
            $chat_id = null;
1089 6
            $user_id = null;
1090 6
1091
            if ($chat = $chat_member_updated->getChat()) {
1092
                $chat_id = $chat->getId();
1093
                self::insertChat($chat, $date);
1094 6
            }
1095
            if ($user = $chat_member_updated->getFrom()) {
1096 6
                $user_id = $user->getId();
1097
                self::insertUser($user, $date);
1098
            }
1099
1100 6
            $sth->bindValue(':chat_id', $chat_id);
1101
            $sth->bindValue(':user_id', $user_id);
1102
            $sth->bindValue(':date', self::getTimestamp($chat_member_updated->getDate()));
1103
            $sth->bindValue(':old_chat_member', $chat_member_updated->getOldChatMember());
1104
            $sth->bindValue(':new_chat_member', $chat_member_updated->getNewChatMember());
1105 6
            $sth->bindValue(':invite_link', $chat_member_updated->getInviteLink());
1106 6
            $sth->bindValue(':created_at', $date);
1107
1108
            return $sth->execute();
1109
        } catch (PDOException $e) {
1110
            throw new TelegramException($e->getMessage());
1111
        }
1112 6
    }
1113 6
1114
    /**
1115 6
     * Insert chat join request into database
1116 6
     *
1117 6
     * @param ChatJoinRequest $chat_join_request
1118
     *
1119
     * @return bool If the insert was successful
1120
     * @throws TelegramException
1121
     */
1122
    public static function insertChatJoinRequestRequest(ChatJoinRequest $chat_join_request): bool
1123
    {
1124
        if (!self::isDbConnected()) {
1125
            return false;
1126 6
        }
1127
1128
        try {
1129
            $sth = self::$pdo->prepare('
1130
                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...
1131
                (`chat_id`, `user_id`, `date`, `bio`, `invite_link`, `created_at`)
1132
                VALUES
1133 6
                (:chat_id, :user_id, :date, :bio, :invite_link, :created_at)
1134 6
            ');
1135
1136
            $date    = self::getTimestamp();
1137
            $chat_id = null;
1138
            $user_id = null;
1139
1140
            if ($chat = $chat_join_request->getChat()) {
1141
                $chat_id = $chat->getId();
1142
                self::insertChat($chat, $date);
1143
            }
1144
            if ($user = $chat_join_request->getFrom()) {
1145
                $user_id = $user->getId();
1146
                self::insertUser($user, $date);
1147
            }
1148
1149
            $sth->bindValue(':chat_id', $chat_id);
1150
            $sth->bindValue(':user_id', $user_id);
1151
            $sth->bindValue(':date', self::getTimestamp($chat_join_request->getDate()));
1152
            $sth->bindValue(':bio', $chat_join_request->getBio());
1153
            $sth->bindValue(':invite_link', $chat_join_request->getInviteLink());
1154
            $sth->bindValue(':created_at', $date);
1155
1156
            return $sth->execute();
1157
        } catch (PDOException $e) {
1158 6
            throw new TelegramException($e->getMessage());
1159
        }
1160 6
    }
1161 6
1162
    /**
1163 6
     * Insert chat boost updated into database
1164 6
     *
1165
     * @param ChatBoostUpdated $chat_boost_updated
1166
     *
1167
     * @return bool If the insert was successful
1168
     * @throws TelegramException
1169
     */
1170
    public static function insertChatBoostUpdatedRequest(ChatBoostUpdated $chat_boost_updated): bool
1171 6
    {
1172 6
        if (!self::isDbConnected()) {
1173 6
            return false;
1174 6
        }
1175 6
1176 6
        try {
1177 6
            $sth = self::$pdo->prepare('
1178 6
                INSERT INTO `' . TB_CHAT_BOOST_UPDATED . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_CHAT_BOOST_UPDATED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1179 6
                (`chat_id`, `boost`, `created_at`)
1180 6
                VALUES
1181 6
                (:chat_id, :boost, :created_at)
1182 6
            ');
1183 6
1184
            $date    = self::getTimestamp();
1185 6
            $chat_id = null;
1186 6
1187
            if ($chat = $chat_boost_updated->getChat()) {
1188
                $chat_id = $chat->getId();
1189 6
                self::insertChat($chat, $date);
1190 6
            }
1191
1192 6
            $sth->bindValue(':chat_id', $chat_id);
1193 6
            $sth->bindValue(':boost', $chat_boost_updated->getBoost());
1194 6
            $sth->bindValue(':created_at', $date);
1195 6
1196 6
            return $sth->execute();
1197 6
        } catch (PDOException $e) {
1198 6
            throw new TelegramException($e->getMessage());
1199 6
        }
1200 6
    }
1201 6
1202 6
    /**
1203 6
     * Insert chat boost removed into database
1204 6
     *
1205 6
     * @param ChatBoostRemoved $chat_boost_removed
1206 6
     *
1207 6
     * @return bool If the insert was successful
1208 6
     * @throws TelegramException
1209 6
     */
1210 6
    public static function insertChatBoostRemovedRequest(ChatBoostRemoved $chat_boost_removed): bool
1211 6
    {
1212 6
        if (!self::isDbConnected()) {
1213 6
            return false;
1214 6
        }
1215 6
1216 6
        try {
1217 6
            $sth = self::$pdo->prepare('
1218 6
                INSERT INTO `' . TB_CHAT_BOOST_REMOVED . '`
0 ignored issues
show
Bug introduced by
The constant Longman\TelegramBot\TB_CHAT_BOOST_REMOVED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
1219 6
                (`chat_id`, `boost_id`, `remove_date`, `source`, `created_at`)
1220 6
                VALUES
1221 6
                (:chat_id, :boost_id, :remove_date, :source, :created_at)
1222 6
            ');
1223 6
1224 6
            $date    = self::getTimestamp();
1225 6
            $chat_id = null;
1226 6
1227 6
            if ($chat = $chat_boost_removed->getChat()) {
1228 6
                $chat_id = $chat->getId();
1229 6
                self::insertChat($chat, $date);
1230 6
            }
1231 6
1232 6
            $sth->bindValue(':chat_id', $chat_id);
1233 6
            $sth->bindValue(':boost_id', $chat_boost_removed->getBoostId());
1234 6
            $sth->bindValue(':remove_date', self::getTimestamp($chat_boost_removed->getRemoveDate()));
1235 6
            $sth->bindValue(':source', $chat_boost_removed->getSource());
1236 6
            $sth->bindValue(':created_at', $date);
1237 6
1238 6
            return $sth->execute();
1239 6
        } catch (PDOException $e) {
1240 6
            throw new TelegramException($e->getMessage());
1241 6
        }
1242 6
    }
1243 6
1244 6
    /**
1245 6
     * Insert Message request in db
1246 6
     *
1247 6
     * @param Message $message
1248
     *
1249 6
     * @return bool If the insert was successful
1250
     * @throws TelegramException
1251
     */
1252
    public static function insertMessageRequest(Message $message): bool
1253
    {
1254
        if (!self::isDbConnected()) {
1255
            return false;
1256
        }
1257
1258
        $date = self::getTimestamp($message->getDate());
1259
1260
        // Insert chat, update chat id in case it migrated
1261
        $chat = $message->getChat();
1262
        self::insertChat($chat, $date, $message->getMigrateToChatId());
1263
1264
        $sender_chat_id = null;
1265
        if ($sender_chat = $message->getSenderChat()) {
1266
            self::insertChat($sender_chat);
1267
            $sender_chat_id = $sender_chat->getId();
1268
        }
1269
1270
        // Insert user and the relation with the chat
1271
        if ($user = $message->getFrom()) {
1272
            self::insertUser($user, $date, $chat);
1273
        }
1274
1275
        // Insert the forwarded message user in users table
1276
        $forward_date = $message->getForwardDate() ? self::getTimestamp($message->getForwardDate()) : null;
0 ignored issues
show
Bug introduced by
The method getForwardDate() 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

1276
        $forward_date = $message->/** @scrutinizer ignore-call */ getForwardDate() ? self::getTimestamp($message->getForwardDate()) : null;
Loading history...
1277
1278
        if ($forward_from = $message->getForwardFrom()) {
0 ignored issues
show
Bug introduced by
The method getForwardFrom() 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

1278
        if ($forward_from = $message->/** @scrutinizer ignore-call */ getForwardFrom()) {
Loading history...
1279
            self::insertUser($forward_from);
1280
            $forward_from = $forward_from->getId();
1281
        }
1282
        if ($forward_from_chat = $message->getForwardFromChat()) {
0 ignored issues
show
Bug introduced by
The method getForwardFromChat() 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

1282
        if ($forward_from_chat = $message->/** @scrutinizer ignore-call */ getForwardFromChat()) {
Loading history...
1283
            self::insertChat($forward_from_chat);
1284
            $forward_from_chat = $forward_from_chat->getId();
1285
        }
1286
1287
        $via_bot_id = null;
1288
        if ($via_bot = $message->getViaBot()) {
1289
            self::insertUser($via_bot);
1290
            $via_bot_id = $via_bot->getId();
1291
        }
1292
1293
        // New and left chat member
1294
        $new_chat_members_ids = null;
1295
        $left_chat_member_id  = null;
1296
1297
        $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

1297
        /** @scrutinizer ignore-call */ 
1298
        $new_chat_members = $message->getNewChatMembers();
Loading history...
1298
        $left_chat_member = $message->getLeftChatMember();
1299
        if (!empty($new_chat_members)) {
1300
            foreach ($new_chat_members as $new_chat_member) {
1301
                if ($new_chat_member instanceof User) {
1302
                    // Insert the new chat user
1303
                    self::insertUser($new_chat_member, $date, $chat);
1304
                    $new_chat_members_ids[] = $new_chat_member->getId();
1305
                }
1306
            }
1307
            $new_chat_members_ids = implode(',', $new_chat_members_ids);
1308
        } 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...
1309
            // Insert the left chat user
1310
            self::insertUser($left_chat_member, $date, $chat);
1311
            $left_chat_member_id = $left_chat_member->getId();
1312
        }
1313
1314
        try {
1315
            $sth = self::$pdo->prepare('
1316
                INSERT IGNORE INTO `' . TB_MESSAGE . '`
1317
                (
1318
                    `id`, `user_id`, `chat_id`, `message_thread_id`, `sender_chat_id`, `sender_boost_count`, `date`, `forward_from`, `forward_from_chat`, `forward_from_message_id`,
1319
                    `forward_signature`, `forward_sender_name`, `forward_date`, `is_topic_message`,
1320
                    `reply_to_chat`, `reply_to_message`, `external_reply`, `quote`, `reply_to_story`, `via_bot`, `link_preview_options`, `edit_date`, `media_group_id`, `author_signature`, `text`, `entities`, `caption_entities`,
1321
                    `audio`, `document`, `animation`, `game`, `photo`, `sticker`, `story`, `video`, `voice`, `video_note`, `caption`, `has_media_spoiler`, `contact`,
1322
                    `location`, `venue`, `poll`, `dice`, `new_chat_members`, `left_chat_member`,
1323
                    `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`,
1324
                    `supergroup_chat_created`, `channel_chat_created`, `message_auto_delete_timer_changed`, `migrate_to_chat_id`, `migrate_from_chat_id`,
1325
                    `pinned_message`, `invoice`, `successful_payment`, `users_shared`, `chat_shared`, `connected_website`, `write_access_allowed`, `passport_data`, `proximity_alert_triggered`, `boost_added`,
1326
                    `forum_topic_created`, `forum_topic_edited`, `forum_topic_closed`, `forum_topic_reopened`, `general_forum_topic_hidden`, `general_forum_topic_unhidden`,
1327
                    `video_chat_scheduled`, `video_chat_started`, `video_chat_ended`, `video_chat_participants_invited`, `web_app_data`, `reply_markup`
1328
                ) VALUES (
1329
                    :message_id, :user_id, :chat_id, :message_thread_id, :sender_chat_id, :sender_boost_count, :date, :forward_from, :forward_from_chat, :forward_from_message_id,
1330
                    :forward_signature, :forward_sender_name, :forward_date, :is_topic_message,
1331
                    :reply_to_chat, :reply_to_message, :external_reply, :quote, :reply_to_story, :via_bot, :link_preview_options, :edit_date, :media_group_id, :author_signature, :text, :entities, :caption_entities,
1332
                    :audio, :document, :animation, :game, :photo, :sticker, :story, :video, :voice, :video_note, :caption, :has_media_spoiler, :contact,
1333
                    :location, :venue, :poll, :dice, :new_chat_members, :left_chat_member,
1334
                    :new_chat_title, :new_chat_photo, :delete_chat_photo, :group_chat_created,
1335
                    :supergroup_chat_created, :channel_chat_created, :message_auto_delete_timer_changed, :migrate_to_chat_id, :migrate_from_chat_id,
1336
                    :pinned_message, :invoice, :successful_payment, :users_shared, :chat_shared, :connected_website, :write_access_allowed, :passport_data, :proximity_alert_triggered, :boost_added,
1337
                    :forum_topic_created, :forum_topic_edited, :forum_topic_closed, :forum_topic_reopened, :general_forum_topic_hidden, :general_forum_topic_unhidden,
1338
                    :video_chat_scheduled, :video_chat_started, :video_chat_ended, :video_chat_participants_invited, :web_app_data, :reply_markup
1339
                )
1340
            ');
1341
1342
            $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...
1343
            $chat_id = $chat->getId();
1344
1345
            $reply_to_message_id = null;
1346
            if ($reply_to_message = $message->getReplyToMessage()) {
1347
                $reply_to_message_id = $reply_to_message->getMessageId();
1348
                // please notice that, as explained in the documentation, reply_to_message don't contain other
1349
                // reply_to_message field so recursion deep is 1
1350
                self::insertMessageRequest($reply_to_message);
1351
            }
1352
1353
            $sth->bindValue(':message_id', $message->getMessageId());
1354
            $sth->bindValue(':chat_id', $chat_id);
1355
            $sth->bindValue(':sender_chat_id', $sender_chat_id);
1356
            $sth->bindValue(':message_thread_id', $message->getMessageThreadId());
1357
            $sth->bindValue(':user_id', $user_id);
1358
            $sth->bindValue(':sender_boost_count', $message->getSenderBoostCount());
1359
            $sth->bindValue(':date', $date);
1360
            $sth->bindValue(':forward_from', $forward_from);
1361
            $sth->bindValue(':forward_from_chat', $forward_from_chat);
1362
            $sth->bindValue(':forward_from_message_id', $message->getForwardFromMessageId());
0 ignored issues
show
Bug introduced by
The method getForwardFromMessageId() 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

1362
            $sth->bindValue(':forward_from_message_id', $message->/** @scrutinizer ignore-call */ getForwardFromMessageId());
Loading history...
1363
            $sth->bindValue(':forward_signature', $message->getForwardSignature());
0 ignored issues
show
Bug introduced by
The method getForwardSignature() 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

1363
            $sth->bindValue(':forward_signature', $message->/** @scrutinizer ignore-call */ getForwardSignature());
Loading history...
1364
            $sth->bindValue(':forward_sender_name', $message->getForwardSenderName());
0 ignored issues
show
Bug introduced by
The method getForwardSenderName() 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

1364
            $sth->bindValue(':forward_sender_name', $message->/** @scrutinizer ignore-call */ getForwardSenderName());
Loading history...
1365
            $sth->bindValue(':forward_date', $forward_date);
1366
            $sth->bindValue(':is_topic_message', $message->getIsTopicMessage());
1367
1368
            $reply_to_chat_id = null;
1369
            if ($reply_to_message_id !== null) {
1370
                $reply_to_chat_id = $chat_id;
1371
            }
1372
            $sth->bindValue(':reply_to_chat', $reply_to_chat_id);
1373
            $sth->bindValue(':reply_to_message', $reply_to_message_id);
1374
            $sth->bindValue(':external_reply', $message->getExternalReply());
1375
1376
            $sth->bindValue(':quote', $message->getQuote());
1377
            $sth->bindValue(':reply_to_story', $message->getReplyToStory());
1378
            $sth->bindValue(':via_bot', $via_bot_id);
1379
            $sth->bindValue(':link_preview_options', $message->getLinkPreviewOptions());
1380
            $sth->bindValue(':edit_date', self::getTimestamp($message->getEditDate()));
1381
            $sth->bindValue(':media_group_id', $message->getMediaGroupId());
1382
            $sth->bindValue(':author_signature', $message->getAuthorSignature());
1383
            $sth->bindValue(':text', $message->getText());
1384
            $sth->bindValue(':entities', self::entitiesArrayToJson($message->getEntities() ?: []));
1385
            $sth->bindValue(':caption_entities', self::entitiesArrayToJson($message->getCaptionEntities() ?: []));
1386
            $sth->bindValue(':audio', $message->getAudio());
1387
            $sth->bindValue(':document', $message->getDocument());
1388
            $sth->bindValue(':animation', $message->getAnimation());
1389
            $sth->bindValue(':game', $message->getGame());
1390
            $sth->bindValue(':photo', self::entitiesArrayToJson($message->getPhoto() ?: []));
1391
            $sth->bindValue(':sticker', $message->getSticker());
1392
            $sth->bindValue(':story', $message->getStory());
1393
            $sth->bindValue(':video', $message->getVideo());
1394
            $sth->bindValue(':voice', $message->getVoice());
1395
            $sth->bindValue(':video_note', $message->getVideoNote());
1396
            $sth->bindValue(':caption', $message->getCaption());
1397
            $sth->bindValue(':has_media_spoiler', $message->getHasMediaSpoiler());
1398
            $sth->bindValue(':contact', $message->getContact());
1399
            $sth->bindValue(':location', $message->getLocation());
1400
            $sth->bindValue(':venue', $message->getVenue());
1401
            $sth->bindValue(':poll', $message->getPoll());
1402
            $sth->bindValue(':dice', $message->getDice());
1403
            $sth->bindValue(':new_chat_members', $new_chat_members_ids);
1404
            $sth->bindValue(':left_chat_member', $left_chat_member_id);
1405
            $sth->bindValue(':new_chat_title', $message->getNewChatTitle());
1406
            $sth->bindValue(':new_chat_photo', self::entitiesArrayToJson($message->getNewChatPhoto() ?: []));
1407
            $sth->bindValue(':delete_chat_photo', $message->getDeleteChatPhoto());
1408
            $sth->bindValue(':group_chat_created', $message->getGroupChatCreated());
1409
            $sth->bindValue(':supergroup_chat_created', $message->getSupergroupChatCreated());
1410
            $sth->bindValue(':channel_chat_created', $message->getChannelChatCreated());
1411
            $sth->bindValue(':message_auto_delete_timer_changed', $message->getMessageAutoDeleteTimerChanged());
1412
            $sth->bindValue(':migrate_to_chat_id', $message->getMigrateToChatId());
1413
            $sth->bindValue(':migrate_from_chat_id', $message->getMigrateFromChatId());
1414
            $sth->bindValue(':pinned_message', $message->getPinnedMessage());
1415
            $sth->bindValue(':invoice', $message->getInvoice());
1416
            $sth->bindValue(':successful_payment', $message->getSuccessfulPayment());
1417
            $sth->bindValue(':users_shared', $message->getUsersShared());
1418
            $sth->bindValue(':chat_shared', $message->getChatShared());
1419
            $sth->bindValue(':connected_website', $message->getConnectedWebsite());
1420
            $sth->bindValue(':write_access_allowed', $message->getWriteAccessAllowed());
1421
            $sth->bindValue(':passport_data', $message->getPassportData());
1422
            $sth->bindValue(':proximity_alert_triggered', $message->getProximityAlertTriggered());
1423
            $sth->bindValue(':boost_added', $message->getBoostAdded());
1424
            $sth->bindValue(':forum_topic_created', $message->getForumTopicCreated());
1425
            $sth->bindValue(':forum_topic_edited', $message->getForumTopicEdited());
1426
            $sth->bindValue(':forum_topic_closed', $message->getForumTopicClosed());
1427
            $sth->bindValue(':forum_topic_reopened', $message->getForumTopicReopened());
1428
            $sth->bindValue(':general_forum_topic_hidden', $message->getGeneralForumTopicHidden());
1429
            $sth->bindValue(':general_forum_topic_unhidden', $message->getGeneralForumTopicUnhidden());
1430
            $sth->bindValue(':video_chat_scheduled', $message->getVideoChatScheduled());
1431
            $sth->bindValue(':video_chat_started', $message->getVideoChatStarted());
1432
            $sth->bindValue(':video_chat_ended', $message->getVideoChatEnded());
1433
            $sth->bindValue(':video_chat_participants_invited', $message->getVideoChatParticipantsInvited());
1434
            $sth->bindValue(':web_app_data', $message->getWebAppData());
1435
            $sth->bindValue(':reply_markup', $message->getReplyMarkup());
1436
1437
            return $sth->execute();
1438
        } catch (PDOException $e) {
1439
            throw new TelegramException($e->getMessage());
1440
        }
1441
    }
1442
1443
    /**
1444
     * Insert Edited Message request in db
1445
     *
1446
     * @param Message $edited_message
1447
     *
1448
     * @return bool If the insert was successful
1449
     * @throws TelegramException
1450
     */
1451
    public static function insertEditedMessageRequest(Message $edited_message): bool
1452
    {
1453
        if (!self::isDbConnected()) {
1454
            return false;
1455
        }
1456
1457
        try {
1458
            $edit_date = self::getTimestamp($edited_message->getEditDate());
1459
1460
            // Insert chat
1461
            $chat = $edited_message->getChat();
1462
            self::insertChat($chat, $edit_date);
1463
1464
            // Insert user and the relation with the chat
1465
            if ($user = $edited_message->getFrom()) {
1466
                self::insertUser($user, $edit_date, $chat);
1467
            }
1468
1469
            $sth = self::$pdo->prepare('
1470
                INSERT IGNORE INTO `' . TB_EDITED_MESSAGE . '`
1471
                (`chat_id`, `message_id`, `user_id`, `edit_date`, `text`, `entities`, `caption`)
1472
                VALUES
1473
                (:chat_id, :message_id, :user_id, :edit_date, :text, :entities, :caption)
1474
            ');
1475
1476
            $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...
1477
1478
            $sth->bindValue(':chat_id', $chat->getId());
1479
            $sth->bindValue(':message_id', $edited_message->getMessageId());
1480
            $sth->bindValue(':user_id', $user_id);
1481
            $sth->bindValue(':edit_date', $edit_date);
1482
            $sth->bindValue(':text', $edited_message->getText());
1483
            $sth->bindValue(':entities', self::entitiesArrayToJson($edited_message->getEntities() ?: []));
1484
            $sth->bindValue(':caption', $edited_message->getCaption());
1485
1486
            return $sth->execute();
1487
        } catch (PDOException $e) {
1488
            throw new TelegramException($e->getMessage());
1489
        }
1490
    }
1491
1492
    /**
1493
     * Select Groups, Supergroups, Channels and/or single user Chats (also by ID or text)
1494
     *
1495
     * @param $select_chats_params
1496
     *
1497
     * @return array|bool
1498
     * @throws TelegramException
1499
     */
1500
    public static function selectChats($select_chats_params)
1501
    {
1502
        if (!self::isDbConnected()) {
1503
            return false;
1504
        }
1505
1506
        // Set defaults for omitted values.
1507
        $select = array_merge([
1508
            'groups'      => true,
1509 3
            'supergroups' => true,
1510
            'channels'    => true,
1511 3
            'users'       => true,
1512
            'date_from'   => null,
1513
            'date_to'     => null,
1514
            'chat_id'     => null,
1515
            'text'        => null,
1516
            'language'    => null,
1517 3
        ], $select_chats_params);
1518
1519
        if (!$select['groups'] && !$select['users'] && !$select['supergroups'] && !$select['channels']) {
1520 3
            return false;
1521 3
        }
1522 3
1523 3
        try {
1524
            $query = '
1525
                SELECT * ,
1526
                ' . TB_CHAT . '.`id` AS `chat_id`,
1527 3
                ' . TB_CHAT . '.`username` AS `chat_username`,
1528 3
                ' . TB_CHAT . '.`created_at` AS `chat_created_at`,
1529 3
                ' . TB_CHAT . '.`updated_at` AS `chat_updated_at`
1530 3
            ';
1531
            if ($select['users']) {
1532
                $query .= '
1533 3
                    , ' . TB_USER . '.`id` AS `user_id`
1534 3
                    FROM `' . TB_CHAT . '`
1535
                    LEFT JOIN `' . TB_USER . '`
1536 3
                    ON ' . TB_CHAT . '.`id`=' . TB_USER . '.`id`
1537
                ';
1538
            } else {
1539
                $query .= 'FROM `' . TB_CHAT . '`';
1540
            }
1541
1542
            // Building parts of query
1543
            $where  = [];
1544
            $tokens = [];
1545
1546
            if (!$select['groups'] || !$select['users'] || !$select['supergroups'] || !$select['channels']) {
1547
                $chat_or_user = [];
1548
1549
                $select['groups'] && $chat_or_user[] = TB_CHAT . '.`type` = "group"';
1550
                $select['supergroups'] && $chat_or_user[] = TB_CHAT . '.`type` = "supergroup"';
1551
                $select['channels'] && $chat_or_user[] = TB_CHAT . '.`type` = "channel"';
1552
                $select['users'] && $chat_or_user[] = TB_CHAT . '.`type` = "private"';
1553
1554
                $where[] = '(' . implode(' OR ', $chat_or_user) . ')';
1555
            }
1556
1557
            if (null !== $select['date_from']) {
1558
                $where[]              = TB_CHAT . '.`updated_at` >= :date_from';
1559
                $tokens[':date_from'] = $select['date_from'];
1560
            }
1561
1562
            if (null !== $select['date_to']) {
1563
                $where[]            = TB_CHAT . '.`updated_at` <= :date_to';
1564
                $tokens[':date_to'] = $select['date_to'];
1565
            }
1566
1567
            if (null !== $select['chat_id']) {
1568
                $where[]            = TB_CHAT . '.`id` = :chat_id';
1569
                $tokens[':chat_id'] = $select['chat_id'];
1570
            }
1571
1572
            if ($select['users'] && null !== $select['language']) {
1573
                $where[]             = TB_USER . '.`language_code` = :language';
1574
                $tokens[':language'] = $select['language'];
1575
            }
1576
1577
            if (null !== $select['text']) {
1578
                $text_like = '%' . strtolower($select['text']) . '%';
1579
                if ($select['users']) {
1580
                    $where[]          = '(
1581
                        LOWER(' . TB_CHAT . '.`title`) LIKE :text1
1582
                        OR LOWER(' . TB_USER . '.`first_name`) LIKE :text2
1583
                        OR LOWER(' . TB_USER . '.`last_name`) LIKE :text3
1584
                        OR LOWER(' . TB_USER . '.`username`) LIKE :text4
1585
                    )';
1586
                    $tokens[':text1'] = $text_like;
1587
                    $tokens[':text2'] = $text_like;
1588
                    $tokens[':text3'] = $text_like;
1589
                    $tokens[':text4'] = $text_like;
1590
                } else {
1591
                    $where[]         = 'LOWER(' . TB_CHAT . '.`title`) LIKE :text';
1592
                    $tokens[':text'] = $text_like;
1593
                }
1594
            }
1595
1596
            if (!empty($where)) {
1597
                $query .= ' WHERE ' . implode(' AND ', $where);
1598
            }
1599
1600
            $query .= ' ORDER BY ' . TB_CHAT . '.`updated_at` ASC';
1601
1602
            $sth = self::$pdo->prepare($query);
1603
            $sth->execute($tokens);
1604
1605
            return $sth->fetchAll(PDO::FETCH_ASSOC);
1606
        } catch (PDOException $e) {
1607
            throw new TelegramException($e->getMessage());
1608
        }
1609
    }
1610
1611
    /**
1612
     * Get Telegram API request count for current chat / message
1613
     *
1614
     * @param int|string|null $chat_id
1615
     * @param string|null     $inline_message_id
1616
     *
1617
     * @return array|bool Array containing TOTAL and CURRENT fields or false on invalid arguments
1618
     * @throws TelegramException
1619
     */
1620
    public static function getTelegramRequestCount($chat_id = null, string $inline_message_id = null)
1621
    {
1622
        if (!self::isDbConnected()) {
1623
            return false;
1624
        }
1625
1626
        try {
1627
            $sth = self::$pdo->prepare('SELECT
1628
                (SELECT COUNT(DISTINCT `chat_id`) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_1) AS LIMIT_PER_SEC_ALL,
1629
                (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,
1630
                (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_minute AND `chat_id` = :chat_id_2) AS LIMIT_PER_MINUTE
1631
            ');
1632
1633
            $date        = self::getTimestamp();
1634
            $date_minute = self::getTimestamp(strtotime('-1 minute'));
1635
1636
            $sth->bindValue(':chat_id_1', $chat_id);
1637
            $sth->bindValue(':chat_id_2', $chat_id);
1638
            $sth->bindValue(':inline_message_id', $inline_message_id);
1639
            $sth->bindValue(':created_at_1', $date);
1640
            $sth->bindValue(':created_at_2', $date);
1641
            $sth->bindValue(':created_at_minute', $date_minute);
1642
1643
            $sth->execute();
1644
1645
            return $sth->fetch();
1646
        } catch (PDOException $e) {
1647
            throw new TelegramException($e->getMessage());
1648
        }
1649
    }
1650
1651
    /**
1652
     * Insert Telegram API request in db
1653
     *
1654
     * @param string $method
1655
     * @param array  $data
1656
     *
1657
     * @return bool If the insert was successful
1658
     * @throws TelegramException
1659
     */
1660
    public static function insertTelegramRequest(string $method, array $data): bool
1661
    {
1662
        if (!self::isDbConnected()) {
1663
            return false;
1664
        }
1665
1666
        try {
1667
            $sth = self::$pdo->prepare('INSERT INTO `' . TB_REQUEST_LIMITER . '`
1668
                (`method`, `chat_id`, `inline_message_id`, `created_at`)
1669
                VALUES
1670
                (:method, :chat_id, :inline_message_id, :created_at);
1671
            ');
1672
1673
            $chat_id           = $data['chat_id'] ?? null;
1674
            $inline_message_id = $data['inline_message_id'] ?? null;
1675
1676
            $sth->bindValue(':chat_id', $chat_id);
1677
            $sth->bindValue(':inline_message_id', $inline_message_id);
1678
            $sth->bindValue(':method', $method);
1679
            $sth->bindValue(':created_at', self::getTimestamp());
1680
1681
            return $sth->execute();
1682
        } catch (PDOException $e) {
1683
            throw new TelegramException($e->getMessage());
1684
        }
1685
    }
1686
1687
    /**
1688
     * Bulk update the entries of any table
1689
     *
1690
     * @param string $table
1691
     * @param array  $fields_values
1692
     * @param array  $where_fields_values
1693
     *
1694
     * @return bool
1695
     * @throws TelegramException
1696
     */
1697
    public static function update(string $table, array $fields_values, array $where_fields_values): bool
1698
    {
1699
        if (empty($fields_values) || !self::isDbConnected()) {
1700
            return false;
1701
        }
1702
1703
        try {
1704
            // Building parts of query
1705
            $tokens = $fields = $where = [];
1706
1707
            // Fields with values to update
1708
            foreach ($fields_values as $field => $value) {
1709
                $token          = ':' . count($tokens);
1710
                $fields[]       = "`{$field}` = {$token}";
1711
                $tokens[$token] = $value;
1712
            }
1713
1714
            // Where conditions
1715
            foreach ($where_fields_values as $field => $value) {
1716
                $token          = ':' . count($tokens);
1717
                $where[]        = "`{$field}` = {$token}";
1718
                $tokens[$token] = $value;
1719
            }
1720
1721
            $sql = 'UPDATE `' . $table . '` SET ' . implode(', ', $fields);
1722
            $sql .= count($where) > 0 ? ' WHERE ' . implode(' AND ', $where) : '';
1723
1724
            return self::$pdo->prepare($sql)->execute($tokens);
1725
        } catch (PDOException $e) {
1726
            throw new TelegramException($e->getMessage());
1727
        }
1728
    }
1729
}
1730