Passed
Push — master ( f3fe5e...097177 )
by Armando
05:18 queued 02:03
created

DB::insertTelegramUpdate()   C

Complexity

Conditions 17
Paths 21

Size

Total Lines 64
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 306

Importance

Changes 0
Metric Value
cc 17
eloc 26
c 0
b 0
f 0
nc 21
nop 16
dl 0
loc 64
ccs 0
cts 25
cp 0
crap 306
rs 5.2166

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\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
     * @param string   $encoding     Database character encoding
69
     *
70
     * @return PDO PDO database object
71
     * @throws TelegramException
72
     */
73 9
    public static function initialize(
74
        array $credentials,
75
        Telegram $telegram,
76
        $table_prefix = '',
77
        $encoding = 'utf8mb4'
78
    ): PDO {
79 9
        if (empty($credentials)) {
80
            throw new TelegramException('MySQL credentials not provided!');
81
        }
82 9
        if (isset($credentials['unix_socket'])) {
83
            $dsn = 'mysql:unix_socket=' . $credentials['unix_socket'];
84
        } else {
85 9
            $dsn = 'mysql:host=' . $credentials['host'];
86
        }
87 9
        $dsn .= ';dbname=' . $credentials['database'];
88
89 9
        if (!empty($credentials['port'])) {
90 9
            $dsn .= ';port=' . $credentials['port'];
91
        }
92
93 9
        $options = [PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $encoding];
94
        try {
95 9
            $pdo = new PDO($dsn, $credentials['user'], $credentials['password'], $options);
96 9
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
97
        } catch (PDOException $e) {
98
            throw new TelegramException($e->getMessage());
99
        }
100
101 9
        self::$pdo               = $pdo;
102 9
        self::$telegram          = $telegram;
103 9
        self::$mysql_credentials = $credentials;
104 9
        self::$table_prefix      = $table_prefix;
105
106 9
        self::defineTables();
107
108 9
        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
132
        self::$pdo               = $external_pdo_connection;
133
        self::$telegram          = $telegram;
134
        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
    {
147
        $tables = [
148
            'callback_query',
149
            'chat',
150
            'chat_join_request',
151
            'chat_member_updated',
152
            'chosen_inline_result',
153
            'edited_message',
154
            'inline_query',
155
            'message',
156
            'poll',
157
            'poll_answer',
158
            'pre_checkout_query',
159
            'request_limiter',
160
            'shipping_query',
161
            'telegram_update',
162
            'user',
163
            'user_chat',
164
        ];
165 9
        foreach ($tables as $table) {
166 9
            $table_name = 'TB_' . strtoupper($table);
167 9
            if (!defined($table_name)) {
168 1
                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 9
    public static function isDbConnected(): bool
179
    {
180 9
        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 . '`
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 . '`
259
                ORDER BY `id` DESC
260
            ';
261
262
            if ($limit > 0) {
263
                $sql .= ' LIMIT :limit';
264
            }
265
266
            $sth = self::$pdo->prepare($sql);
267
268
            if ($limit > 0) {
269
                $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
     *
283
     * @param ?int $unixtime Unix timestamp (if empty, current timestamp is used)
284
     *
285
     * @return string
286
     */
287 7
    protected static function getTimestamp(?int $unixtime = null): string
288
    {
289 7
        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 6
    public static function entitiesArrayToJson(array $entities, $default = null)
303
    {
304 6
        if (empty($entities)) {
305 6
            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
            return false;
362
        }
363
364
        try {
365
            $sth = self::$pdo->prepare('
366
                INSERT IGNORE INTO `' . TB_TELEGRAM_UPDATE . '`
367
                (
368
                    `id`, `chat_id`, `message_id`, `edited_message_id`,
369
                    `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
            $sth->bindValue(':id', $update_id);
383
            $sth->bindValue(':chat_id', $chat_id);
384
            $sth->bindValue(':message_id', $message_id);
385
            $sth->bindValue(':edited_message_id', $edited_message_id);
386
            $sth->bindValue(':channel_post_id', $channel_post_id);
387
            $sth->bindValue(':edited_channel_post_id', $edited_channel_post_id);
388
            $sth->bindValue(':inline_query_id', $inline_query_id);
389
            $sth->bindValue(':chosen_inline_result_id', $chosen_inline_result_id);
390
            $sth->bindValue(':callback_query_id', $callback_query_id);
391
            $sth->bindValue(':shipping_query_id', $shipping_query_id);
392
            $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
399
            return $sth->execute();
400
        } catch (PDOException $e) {
401
            throw new TelegramException($e->getMessage());
402
        }
403
    }
404
405
    /**
406
     * Insert users and save their connection to chats
407
     *
408
     * @param User        $user
409
     * @param string|null $date
410
     * @param Chat|null   $chat
411
     *
412
     * @return bool If the insert was successful
413
     * @throws TelegramException
414
     */
415 6
    public static function insertUser(User $user, ?string $date = null, ?Chat $chat = null): bool
416
    {
417 6
        if (!self::isDbConnected()) {
418
            return false;
419
        }
420
421
        try {
422 6
            $sth = self::$pdo->prepare('
423
                INSERT INTO `' . TB_USER . '`
424
                (`id`, `is_bot`, `username`, `first_name`, `last_name`, `language_code`, `is_premium`, `added_to_attachment_menu`, `created_at`, `updated_at`)
425
                VALUES
426
                (:id, :is_bot, :username, :first_name, :last_name, :language_code, :is_premium, :added_to_attachment_menu, :created_at, :updated_at)
427
                ON DUPLICATE KEY UPDATE
428
                    `is_bot`                   = VALUES(`is_bot`),
429
                    `username`                 = VALUES(`username`),
430
                    `first_name`               = VALUES(`first_name`),
431
                    `last_name`                = VALUES(`last_name`),
432
                    `language_code`            = VALUES(`language_code`),
433
                    `is_premium`               = VALUES(`is_premium`),
434
                    `added_to_attachment_menu` = VALUES(`added_to_attachment_menu`),
435
                    `updated_at`               = VALUES(`updated_at`)
436
            ');
437
438 6
            $sth->bindValue(':id', $user->getId());
439 6
            $sth->bindValue(':is_bot', $user->getIsBot(), PDO::PARAM_INT);
440 6
            $sth->bindValue(':username', $user->getUsername());
441 6
            $sth->bindValue(':first_name', $user->getFirstName());
442 6
            $sth->bindValue(':last_name', $user->getLastName());
443 6
            $sth->bindValue(':language_code', $user->getLanguageCode());
444 6
            $sth->bindValue(':is_premium', $user->getIsPremium(), PDO::PARAM_INT);
445 6
            $sth->bindValue(':added_to_attachment_menu', $user->getAddedToAttachmentMenu(), PDO::PARAM_INT);
446 6
            $date = $date ?: self::getTimestamp();
447 6
            $sth->bindValue(':created_at', $date);
448 6
            $sth->bindValue(':updated_at', $date);
449
450 6
            $status = $sth->execute();
451
        } catch (PDOException $e) {
452
            throw new TelegramException($e->getMessage());
453
        }
454
455
        // Also insert the relationship to the chat into the user_chat table
456 6
        if ($chat) {
457
            try {
458 6
                $sth = self::$pdo->prepare('
459
                    INSERT IGNORE INTO `' . TB_USER_CHAT . '`
460
                    (`user_id`, `chat_id`)
461
                    VALUES
462
                    (:user_id, :chat_id)
463
                ');
464
465 6
                $sth->bindValue(':user_id', $user->getId());
466 6
                $sth->bindValue(':chat_id', $chat->getId());
467
468 6
                $status = $sth->execute();
469
            } catch (PDOException $e) {
470
                throw new TelegramException($e->getMessage());
471
            }
472
        }
473
474 6
        return $status;
475
    }
476
477
    /**
478
     * Insert chat
479
     *
480
     * @param Chat        $chat
481
     * @param string|null $date
482
     * @param int|null    $migrate_to_chat_id
483
     *
484
     * @return bool If the insert was successful
485
     * @throws TelegramException
486
     */
487 6
    public static function insertChat(Chat $chat, ?string $date = null, ?int $migrate_to_chat_id = null): ?bool
488
    {
489 6
        if (!self::isDbConnected()) {
490
            return false;
491
        }
492
493
        try {
494 6
            $sth = self::$pdo->prepare('
495
                INSERT IGNORE INTO `' . TB_CHAT . '`
496
                (`id`, `type`, `title`, `username`, `first_name`, `last_name`, `created_at` ,`updated_at`, `old_id`)
497
                VALUES
498
                (:id, :type, :title, :username, :first_name, :last_name, :created_at, :updated_at, :old_id)
499
                ON DUPLICATE KEY UPDATE
500
                    `type`                           = VALUES(`type`),
501
                    `title`                          = VALUES(`title`),
502
                    `username`                       = VALUES(`username`),
503
                    `first_name`                     = VALUES(`first_name`),
504
                    `last_name`                      = VALUES(`last_name`),
505
                    `updated_at`                     = VALUES(`updated_at`)
506
            ');
507
508 6
            $chat_id   = $chat->getId();
509 6
            $chat_type = $chat->getType();
510
511 6
            if ($migrate_to_chat_id !== null) {
512
                $chat_type = 'supergroup';
513
514
                $sth->bindValue(':id', $migrate_to_chat_id);
515
                $sth->bindValue(':old_id', $chat_id);
516
            } else {
517 6
                $sth->bindValue(':id', $chat_id);
518 6
                $sth->bindValue(':old_id', $migrate_to_chat_id);
519
            }
520
521 6
            $sth->bindValue(':type', $chat_type);
522 6
            $sth->bindValue(':title', $chat->getTitle());
523 6
            $sth->bindValue(':username', $chat->getUsername());
524 6
            $sth->bindValue(':first_name', $chat->getFirstName());
525 6
            $sth->bindValue(':last_name', $chat->getLastName());
526 6
            $date = $date ?: self::getTimestamp();
527 6
            $sth->bindValue(':created_at', $date);
528 6
            $sth->bindValue(':updated_at', $date);
529
530 6
            return $sth->execute();
531
        } catch (PDOException $e) {
532
            throw new TelegramException($e->getMessage());
533
        }
534
    }
535
536
    /**
537
     * Insert request into database
538
     *
539
     * @todo self::$pdo->lastInsertId() - unsafe usage if expected previous insert fails?
540
     *
541
     * @param Update $update
542
     *
543
     * @return bool
544
     * @throws TelegramException
545
     */
546
    public static function insertRequest(Update $update): bool
547
    {
548
        if (!self::isDbConnected()) {
549
            return false;
550
        }
551
552
        $chat_id                   = null;
553
        $message_id                = null;
554
        $edited_message_id         = null;
555
        $channel_post_id           = null;
556
        $edited_channel_post_id    = null;
557
        $inline_query_id           = null;
558
        $chosen_inline_result_id   = null;
559
        $callback_query_id         = null;
560
        $shipping_query_id         = null;
561
        $pre_checkout_query_id     = null;
562
        $poll_id                   = null;
563
        $poll_answer_poll_id       = null;
564
        $my_chat_member_updated_id = null;
565
        $chat_member_updated_id    = null;
566
        $chat_join_request_id      = null;
567
568
        if (($message = $update->getMessage()) && self::insertMessageRequest($message)) {
569
            $chat_id    = $message->getChat()->getId();
570
            $message_id = $message->getMessageId();
571
        } elseif (($edited_message = $update->getEditedMessage()) && self::insertEditedMessageRequest($edited_message)) {
572
            $chat_id           = $edited_message->getChat()->getId();
573
            $edited_message_id = (int) self::$pdo->lastInsertId();
574
        } elseif (($channel_post = $update->getChannelPost()) && self::insertMessageRequest($channel_post)) {
575
            $chat_id         = $channel_post->getChat()->getId();
576
            $channel_post_id = $channel_post->getMessageId();
577
        } elseif (($edited_channel_post = $update->getEditedChannelPost()) && self::insertEditedMessageRequest($edited_channel_post)) {
578
            $chat_id                = $edited_channel_post->getChat()->getId();
579
            $edited_channel_post_id = (int) self::$pdo->lastInsertId();
580
        } elseif (($inline_query = $update->getInlineQuery()) && self::insertInlineQueryRequest($inline_query)) {
581
            $inline_query_id = $inline_query->getId();
582
        } elseif (($chosen_inline_result = $update->getChosenInlineResult()) && self::insertChosenInlineResultRequest($chosen_inline_result)) {
583
            $chosen_inline_result_id = self::$pdo->lastInsertId();
584
        } elseif (($callback_query = $update->getCallbackQuery()) && self::insertCallbackQueryRequest($callback_query)) {
585
            $callback_query_id = $callback_query->getId();
586
        } elseif (($shipping_query = $update->getShippingQuery()) && self::insertShippingQueryRequest($shipping_query)) {
587
            $shipping_query_id = $shipping_query->getId();
588
        } elseif (($pre_checkout_query = $update->getPreCheckoutQuery()) && self::insertPreCheckoutQueryRequest($pre_checkout_query)) {
589
            $pre_checkout_query_id = $pre_checkout_query->getId();
590
        } elseif (($poll = $update->getPoll()) && self::insertPollRequest($poll)) {
591
            $poll_id = $poll->getId();
592
        } elseif (($poll_answer = $update->getPollAnswer()) && self::insertPollAnswerRequest($poll_answer)) {
593
            $poll_answer_poll_id = $poll_answer->getPollId();
594
        } elseif (($my_chat_member = $update->getMyChatMember()) && self::insertChatMemberUpdatedRequest($my_chat_member)) {
595
            $my_chat_member_updated_id = self::$pdo->lastInsertId();
596
        } elseif (($chat_member = $update->getChatMember()) && self::insertChatMemberUpdatedRequest($chat_member)) {
597
            $chat_member_updated_id = self::$pdo->lastInsertId();
598
        } elseif (($chat_join_request = $update->getChatJoinRequest()) && self::insertChatJoinRequestRequest($chat_join_request)) {
599
            $chat_join_request_id = self::$pdo->lastInsertId();
600
        } else {
601
            return false;
602
        }
603
604
        return self::insertTelegramUpdate(
605
            $update->getUpdateId(),
606
            $chat_id,
607
            $message_id,
608
            $edited_message_id,
609
            $channel_post_id,
610
            $edited_channel_post_id,
611
            $inline_query_id,
612
            $chosen_inline_result_id,
613
            $callback_query_id,
614
            $shipping_query_id,
615
            $pre_checkout_query_id,
616
            $poll_id,
617
            $poll_answer_poll_id,
618
            $my_chat_member_updated_id,
619
            $chat_member_updated_id,
620
            $chat_join_request_id
621
        );
622
    }
623
624
    /**
625
     * Insert inline query request into database
626
     *
627
     * @param InlineQuery $inline_query
628
     *
629
     * @return bool If the insert was successful
630
     * @throws TelegramException
631
     */
632
    public static function insertInlineQueryRequest(InlineQuery $inline_query): bool
633
    {
634
        if (!self::isDbConnected()) {
635
            return false;
636
        }
637
638
        try {
639
            $sth = self::$pdo->prepare('
640
                INSERT IGNORE INTO `' . TB_INLINE_QUERY . '`
641
                (`id`, `user_id`, `location`, `query`, `offset`, `chat_type`, `created_at`)
642
                VALUES
643
                (:id, :user_id, :location, :query, :offset, :chat_type, :created_at)
644
            ');
645
646
            $date    = self::getTimestamp();
647
            $user_id = null;
648
649
            if ($user = $inline_query->getFrom()) {
650
                $user_id = $user->getId();
651
                self::insertUser($user, $date);
652
            }
653
654
            $sth->bindValue(':id', $inline_query->getId());
655
            $sth->bindValue(':user_id', $user_id);
656
            $sth->bindValue(':location', $inline_query->getLocation());
657
            $sth->bindValue(':query', $inline_query->getQuery());
658
            $sth->bindValue(':offset', $inline_query->getOffset());
659
            $sth->bindValue(':chat_type', $inline_query->getChatType());
660
            $sth->bindValue(':created_at', $date);
661
662
            return $sth->execute();
663
        } catch (PDOException $e) {
664
            throw new TelegramException($e->getMessage());
665
        }
666
    }
667
668
    /**
669
     * Insert chosen inline result request into database
670
     *
671
     * @param ChosenInlineResult $chosen_inline_result
672
     *
673
     * @return bool If the insert was successful
674
     * @throws TelegramException
675
     */
676
    public static function insertChosenInlineResultRequest(ChosenInlineResult $chosen_inline_result): bool
677
    {
678
        if (!self::isDbConnected()) {
679
            return false;
680
        }
681
682
        try {
683
            $sth = self::$pdo->prepare('
684
                INSERT INTO `' . TB_CHOSEN_INLINE_RESULT . '`
685
                (`result_id`, `user_id`, `location`, `inline_message_id`, `query`, `created_at`)
686
                VALUES
687
                (:result_id, :user_id, :location, :inline_message_id, :query, :created_at)
688
            ');
689
690
            $date    = self::getTimestamp();
691
            $user_id = null;
692
693
            if ($user = $chosen_inline_result->getFrom()) {
694
                $user_id = $user->getId();
695
                self::insertUser($user, $date);
696
            }
697
698
            $sth->bindValue(':result_id', $chosen_inline_result->getResultId());
699
            $sth->bindValue(':user_id', $user_id);
700
            $sth->bindValue(':location', $chosen_inline_result->getLocation());
701
            $sth->bindValue(':inline_message_id', $chosen_inline_result->getInlineMessageId());
702
            $sth->bindValue(':query', $chosen_inline_result->getQuery());
703
            $sth->bindValue(':created_at', $date);
704
705
            return $sth->execute();
706
        } catch (PDOException $e) {
707
            throw new TelegramException($e->getMessage());
708
        }
709
    }
710
711
    /**
712
     * Insert callback query request into database
713
     *
714
     * @param CallbackQuery $callback_query
715
     *
716
     * @return bool If the insert was successful
717
     * @throws TelegramException
718
     */
719
    public static function insertCallbackQueryRequest(CallbackQuery $callback_query): bool
720
    {
721
        if (!self::isDbConnected()) {
722
            return false;
723
        }
724
725
        try {
726
            $sth = self::$pdo->prepare('
727
                INSERT IGNORE INTO `' . TB_CALLBACK_QUERY . '`
728
                (`id`, `user_id`, `chat_id`, `message_id`, `inline_message_id`, `chat_instance`, `data`, `game_short_name`, `created_at`)
729
                VALUES
730
                (:id, :user_id, :chat_id, :message_id, :inline_message_id, :chat_instance, :data, :game_short_name, :created_at)
731
            ');
732
733
            $date    = self::getTimestamp();
734
            $user_id = null;
735
736
            if ($user = $callback_query->getFrom()) {
737
                $user_id = $user->getId();
738
                self::insertUser($user, $date);
739
            }
740
741
            $chat_id    = null;
742
            $message_id = null;
743
            if ($message = $callback_query->getMessage()) {
744
                $chat_id    = $message->getChat()->getId();
745
                $message_id = $message->getMessageId();
746
747
                $is_message = self::$pdo->query('
748
                    SELECT *
749
                    FROM `' . TB_MESSAGE . '`
750
                    WHERE `id` = ' . $message_id . '
751
                      AND `chat_id` = ' . $chat_id . '
752
                    LIMIT 1
753
                ')->rowCount();
754
755
                if ($is_message) {
756
                    self::insertEditedMessageRequest($message);
757
                } else {
758
                    self::insertMessageRequest($message);
759
                }
760
            }
761
762
            $sth->bindValue(':id', $callback_query->getId());
763
            $sth->bindValue(':user_id', $user_id);
764
            $sth->bindValue(':chat_id', $chat_id);
765
            $sth->bindValue(':message_id', $message_id);
766
            $sth->bindValue(':inline_message_id', $callback_query->getInlineMessageId());
767
            $sth->bindValue(':chat_instance', $callback_query->getChatInstance());
768
            $sth->bindValue(':data', $callback_query->getData());
769
            $sth->bindValue(':game_short_name', $callback_query->getGameShortName());
770
            $sth->bindValue(':created_at', $date);
771
772
            return $sth->execute();
773
        } catch (PDOException $e) {
774
            throw new TelegramException($e->getMessage());
775
        }
776
    }
777
778
    /**
779
     * Insert shipping query request into database
780
     *
781
     * @param ShippingQuery $shipping_query
782
     *
783
     * @return bool If the insert was successful
784
     * @throws TelegramException
785
     */
786
    public static function insertShippingQueryRequest(ShippingQuery $shipping_query): bool
787
    {
788
        if (!self::isDbConnected()) {
789
            return false;
790
        }
791
792
        try {
793
            $sth = self::$pdo->prepare('
794
                INSERT IGNORE INTO `' . TB_SHIPPING_QUERY . '`
795
                (`id`, `user_id`, `invoice_payload`, `shipping_address`, `created_at`)
796
                VALUES
797
                (:id, :user_id, :invoice_payload, :shipping_address, :created_at)
798
            ');
799
800
            $date    = self::getTimestamp();
801
            $user_id = null;
802
803
            if ($user = $shipping_query->getFrom()) {
804
                $user_id = $user->getId();
805
                self::insertUser($user, $date);
806
            }
807
808
            $sth->bindValue(':id', $shipping_query->getId());
809
            $sth->bindValue(':user_id', $user_id);
810
            $sth->bindValue(':invoice_payload', $shipping_query->getInvoicePayload());
811
            $sth->bindValue(':shipping_address', $shipping_query->getShippingAddress());
812
            $sth->bindValue(':created_at', $date);
813
814
            return $sth->execute();
815
        } catch (PDOException $e) {
816
            throw new TelegramException($e->getMessage());
817
        }
818
    }
819
820
    /**
821
     * Insert pre checkout query request into database
822
     *
823
     * @param PreCheckoutQuery $pre_checkout_query
824
     *
825
     * @return bool If the insert was successful
826
     * @throws TelegramException
827
     */
828
    public static function insertPreCheckoutQueryRequest(PreCheckoutQuery $pre_checkout_query): bool
829
    {
830
        if (!self::isDbConnected()) {
831
            return false;
832
        }
833
834
        try {
835
            $sth = self::$pdo->prepare('
836
                INSERT IGNORE INTO `' . TB_PRE_CHECKOUT_QUERY . '`
837
                (`id`, `user_id`, `currency`, `total_amount`, `invoice_payload`, `shipping_option_id`, `order_info`, `created_at`)
838
                VALUES
839
                (:id, :user_id, :currency, :total_amount, :invoice_payload, :shipping_option_id, :order_info, :created_at)
840
            ');
841
842
            $date    = self::getTimestamp();
843
            $user_id = null;
844
845
            if ($user = $pre_checkout_query->getFrom()) {
846
                $user_id = $user->getId();
847
                self::insertUser($user, $date);
848
            }
849
850
            $sth->bindValue(':id', $pre_checkout_query->getId());
851
            $sth->bindValue(':user_id', $user_id);
852
            $sth->bindValue(':currency', $pre_checkout_query->getCurrency());
853
            $sth->bindValue(':total_amount', $pre_checkout_query->getTotalAmount());
854
            $sth->bindValue(':invoice_payload', $pre_checkout_query->getInvoicePayload());
855
            $sth->bindValue(':shipping_option_id', $pre_checkout_query->getShippingOptionId());
856
            $sth->bindValue(':order_info', $pre_checkout_query->getOrderInfo());
857
            $sth->bindValue(':created_at', $date);
858
859
            return $sth->execute();
860
        } catch (PDOException $e) {
861
            throw new TelegramException($e->getMessage());
862
        }
863
    }
864
865
    /**
866
     * Insert poll request into database
867
     *
868
     * @param Poll $poll
869
     *
870
     * @return bool If the insert was successful
871
     * @throws TelegramException
872
     */
873
    public static function insertPollRequest(Poll $poll): bool
874
    {
875
        if (!self::isDbConnected()) {
876
            return false;
877
        }
878
879
        try {
880
            $sth = self::$pdo->prepare('
881
                INSERT INTO `' . TB_POLL . '`
882
                (`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
                VALUES
884
                (: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)
885
                ON DUPLICATE KEY UPDATE
886
                    `options`                 = VALUES(`options`),
887
                    `total_voter_count`       = VALUES(`total_voter_count`),
888
                    `is_closed`               = VALUES(`is_closed`),
889
                    `is_anonymous`            = VALUES(`is_anonymous`),
890
                    `type`                    = VALUES(`type`),
891
                    `allows_multiple_answers` = VALUES(`allows_multiple_answers`),
892
                    `correct_option_id`       = VALUES(`correct_option_id`),
893
                    `explanation`             = VALUES(`explanation`),
894
                    `explanation_entities`    = VALUES(`explanation_entities`),
895
                    `open_period`             = VALUES(`open_period`),
896
                    `close_date`              = VALUES(`close_date`)
897
            ');
898
899
            $sth->bindValue(':id', $poll->getId());
900
            $sth->bindValue(':question', $poll->getQuestion());
901
            $sth->bindValue(':options', self::entitiesArrayToJson($poll->getOptions() ?: []));
902
            $sth->bindValue(':total_voter_count', $poll->getTotalVoterCount());
903
            $sth->bindValue(':is_closed', $poll->getIsClosed(), PDO::PARAM_INT);
904
            $sth->bindValue(':is_anonymous', $poll->getIsAnonymous(), PDO::PARAM_INT);
905
            $sth->bindValue(':type', $poll->getType());
906
            $sth->bindValue(':allows_multiple_answers', $poll->getAllowsMultipleAnswers(), PDO::PARAM_INT);
907
            $sth->bindValue(':correct_option_id', $poll->getCorrectOptionId());
908
            $sth->bindValue(':explanation', $poll->getExplanation());
909
            $sth->bindValue(':explanation_entities', self::entitiesArrayToJson($poll->getExplanationEntities() ?: []));
910
            $sth->bindValue(':open_period', $poll->getOpenPeriod());
911
            $sth->bindValue(':close_date', self::getTimestamp($poll->getCloseDate()));
912
            $sth->bindValue(':created_at', self::getTimestamp());
913
914
            return $sth->execute();
915
        } catch (PDOException $e) {
916
            throw new TelegramException($e->getMessage());
917
        }
918
    }
919
920
    /**
921
     * Insert poll answer request into database
922
     *
923
     * @param PollAnswer $poll_answer
924
     *
925
     * @return bool If the insert was successful
926
     * @throws TelegramException
927
     */
928
    public static function insertPollAnswerRequest(PollAnswer $poll_answer): bool
929
    {
930
        if (!self::isDbConnected()) {
931
            return false;
932
        }
933
934
        try {
935
            $sth = self::$pdo->prepare('
936
                INSERT INTO `' . TB_POLL_ANSWER . '`
937
                (`poll_id`, `user_id`, `option_ids`, `created_at`)
938
                VALUES
939
                (:poll_id, :user_id, :option_ids, :created_at)
940
                ON DUPLICATE KEY UPDATE
941
                    `option_ids` = VALUES(`option_ids`)
942
            ');
943
944
            $date    = self::getTimestamp();
945
            $user_id = null;
946
947
            if ($user = $poll_answer->getUser()) {
948
                $user_id = $user->getId();
949
                self::insertUser($user, $date);
950
            }
951
952
            $sth->bindValue(':poll_id', $poll_answer->getPollId());
953
            $sth->bindValue(':user_id', $user_id);
954
            $sth->bindValue(':option_ids', json_encode($poll_answer->getOptionIds()));
955
            $sth->bindValue(':created_at', $date);
956
957
            return $sth->execute();
958
        } catch (PDOException $e) {
959
            throw new TelegramException($e->getMessage());
960
        }
961
    }
962
963
    /**
964
     * Insert chat member updated request into database
965
     *
966
     * @param ChatMemberUpdated $chat_member_updated
967
     *
968
     * @return bool If the insert was successful
969
     * @throws TelegramException
970
     */
971
    public static function insertChatMemberUpdatedRequest(ChatMemberUpdated $chat_member_updated): bool
972
    {
973
        if (!self::isDbConnected()) {
974
            return false;
975
        }
976
977
        try {
978
            $sth = self::$pdo->prepare('
979
                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...
980
                (`chat_id`, `user_id`, `date`, `old_chat_member`, `new_chat_member`, `invite_link`, `created_at`)
981
                VALUES
982
                (:chat_id, :user_id, :date, :old_chat_member, :new_chat_member, :invite_link, :created_at)
983
            ');
984
985
            $date    = self::getTimestamp();
986
            $chat_id = null;
987
            $user_id = null;
988
989
            if ($chat = $chat_member_updated->getChat()) {
990
                $chat_id = $chat->getId();
991
                self::insertChat($chat, $date);
992
            }
993
            if ($user = $chat_member_updated->getFrom()) {
994
                $user_id = $user->getId();
995
                self::insertUser($user, $date);
996
            }
997
998
            $sth->bindValue(':chat_id', $chat_id);
999
            $sth->bindValue(':user_id', $user_id);
1000
            $sth->bindValue(':date', self::getTimestamp($chat_member_updated->getDate()));
1001
            $sth->bindValue(':old_chat_member', $chat_member_updated->getOldChatMember());
1002
            $sth->bindValue(':new_chat_member', $chat_member_updated->getNewChatMember());
1003
            $sth->bindValue(':invite_link', $chat_member_updated->getInviteLink());
1004
            $sth->bindValue(':created_at', $date);
1005
1006
            return $sth->execute();
1007
        } catch (PDOException $e) {
1008
            throw new TelegramException($e->getMessage());
1009
        }
1010
    }
1011
1012
    /**
1013
     * Insert chat join request into database
1014
     *
1015
     * @param ChatJoinRequest $chat_join_request
1016
     *
1017
     * @return bool If the insert was successful
1018
     * @throws TelegramException
1019
     */
1020
    public static function insertChatJoinRequestRequest(ChatJoinRequest $chat_join_request): bool
1021
    {
1022
        if (!self::isDbConnected()) {
1023
            return false;
1024
        }
1025
1026
        try {
1027
            $sth = self::$pdo->prepare('
1028
                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...
1029
                (`chat_id`, `user_id`, `date`, `bio`, `invite_link`, `created_at`)
1030
                VALUES
1031
                (:chat_id, :user_id, :date, :bio, :invite_link, :created_at)
1032
            ');
1033
1034
            $date    = self::getTimestamp();
1035
            $chat_id = null;
1036
            $user_id = null;
1037
1038
            if ($chat = $chat_join_request->getChat()) {
1039
                $chat_id = $chat->getId();
1040
                self::insertChat($chat, $date);
1041
            }
1042
            if ($user = $chat_join_request->getFrom()) {
1043
                $user_id = $user->getId();
1044
                self::insertUser($user, $date);
1045
            }
1046
1047
            $sth->bindValue(':chat_id', $chat_id);
1048
            $sth->bindValue(':user_id', $user_id);
1049
            $sth->bindValue(':date', self::getTimestamp($chat_join_request->getDate()));
1050
            $sth->bindValue(':bio', $chat_join_request->getBio());
1051
            $sth->bindValue(':invite_link', $chat_join_request->getInviteLink());
1052
            $sth->bindValue(':created_at', $date);
1053
1054
            return $sth->execute();
1055
        } catch (PDOException $e) {
1056
            throw new TelegramException($e->getMessage());
1057
        }
1058
    }
1059
1060
    /**
1061
     * Insert Message request in db
1062
     *
1063
     * @param Message $message
1064
     *
1065
     * @return bool If the insert was successful
1066
     * @throws TelegramException
1067
     */
1068 6
    public static function insertMessageRequest(Message $message): bool
1069
    {
1070 6
        if (!self::isDbConnected()) {
1071
            return false;
1072
        }
1073
1074 6
        $date = self::getTimestamp($message->getDate());
1075
1076
        // Insert chat, update chat id in case it migrated
1077 6
        $chat = $message->getChat();
1078 6
        self::insertChat($chat, $date, $message->getMigrateToChatId());
1079
1080 6
        $sender_chat_id = null;
1081 6
        if ($sender_chat = $message->getSenderChat()) {
1082
            self::insertChat($sender_chat);
1083
            $sender_chat_id = $sender_chat->getId();
1084
        }
1085
1086
        // Insert user and the relation with the chat
1087 6
        if ($user = $message->getFrom()) {
1088 6
            self::insertUser($user, $date, $chat);
1089
        }
1090
1091
        // Insert the forwarded message user in users table
1092 6
        $forward_date = $message->getForwardDate() ? self::getTimestamp($message->getForwardDate()) : null;
1093
1094 6
        if ($forward_from = $message->getForwardFrom()) {
1095
            self::insertUser($forward_from);
1096
            $forward_from = $forward_from->getId();
1097
        }
1098 6
        if ($forward_from_chat = $message->getForwardFromChat()) {
1099
            self::insertChat($forward_from_chat);
1100
            $forward_from_chat = $forward_from_chat->getId();
1101
        }
1102
1103 6
        $via_bot_id = null;
1104 6
        if ($via_bot = $message->getViaBot()) {
1105
            self::insertUser($via_bot);
1106
            $via_bot_id = $via_bot->getId();
1107
        }
1108
1109
        // New and left chat member
1110 6
        $new_chat_members_ids = null;
1111 6
        $left_chat_member_id  = null;
1112
1113 6
        $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

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