Passed
Push — develop ( 294b7c...a3f329 )
by Armando
02:56 queued 14s
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 2
Bugs 0 Features 0
Metric Value
cc 6
eloc 27
c 2
b 0
f 0
nc 18
nop 3
dl 0
loc 56
ccs 21
cts 26
cp 0.8077
crap 6.256
rs 8.8657

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

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

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