Passed
Push — master ( 097177...94d770 )
by Armando
04:40 queued 01:51
created

DB::insertUser()   B

Complexity

Conditions 6
Paths 20

Size

Total Lines 60
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 6.205

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 29
c 1
b 0
f 0
nc 20
nop 3
dl 0
loc 60
ccs 23
cts 28
cp 0.8214
crap 6.205
rs 8.8337

How to fix   Long Method   

Long Method

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

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

Commonly applied refactorings include:

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

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