Passed
Push — bot_api_5.1 ( ccb32d...5b70fc )
by Armando
02:43
created

DB::insertUser()   B

Complexity

Conditions 6
Paths 18

Size

Total Lines 56
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 6.256

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 6
eloc 27
c 3
b 0
f 0
nc 18
nop 3
dl 0
loc 56
rs 8.8657
ccs 21
cts 26
cp 0.8077
crap 6.256

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

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

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

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