Passed
Push — 1049_bot_api_4.6 ( 239a99 )
by Armando
02:50
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 6
Bugs 0 Features 0
Metric Value
cc 6
eloc 27
c 6
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\ChosenInlineResult;
18
use Longman\TelegramBot\Entities\InlineQuery;
19
use Longman\TelegramBot\Entities\Message;
20
use Longman\TelegramBot\Entities\Payments\PreCheckoutQuery;
21
use Longman\TelegramBot\Entities\Payments\ShippingQuery;
22
use Longman\TelegramBot\Entities\Poll;
23
use Longman\TelegramBot\Entities\PollAnswer;
24
use Longman\TelegramBot\Entities\ReplyToMessage;
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 = null,
76
        $encoding = 'utf8mb4'
77
    ) {
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
            $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
        $external_pdo_connection,
119
        Telegram $telegram,
120
        $table_prefix = null
121
    ) {
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()
140
    {
141
        $tables = [
142 9
            'callback_query',
143
            'chat',
144
            'chosen_inline_result',
145
            'edited_message',
146
            'inline_query',
147
            'message',
148
            'pre_checkout_query',
149
            'poll',
150
            'poll_answer',
151
            'request_limiter',
152
            'shipping_query',
153
            'telegram_update',
154
            'user',
155
            'user_chat',
156
        ];
157 9
        foreach ($tables as $table) {
158 9
            $table_name = 'TB_' . strtoupper($table);
159 9
            if (!defined($table_name)) {
160 1
                define($table_name, self::$table_prefix . $table);
161
            }
162
        }
163 9
    }
164
165
    /**
166
     * Check if database connection has been created
167
     *
168
     * @return bool
169
     */
170 9
    public static function isDbConnected()
171
    {
172 9
        return self::$pdo !== null;
173
    }
174
175
    /**
176
     * Get the PDO object of the connected database
177
     *
178
     * @return PDO
179
     */
180
    public static function getPdo()
181
    {
182
        return self::$pdo;
183
    }
184
185
    /**
186
     * Fetch update(s) from DB
187
     *
188
     * @param int    $limit Limit the number of updates to fetch
189
     * @param string $id    Check for unique update id
190
     *
191
     * @return array|bool Fetched data or false if not connected
192
     * @throws TelegramException
193
     */
194
    public static function selectTelegramUpdate($limit = null, $id = null)
195
    {
196
        if (!self::isDbConnected()) {
197
            return false;
198
        }
199
200
        try {
201
            $sql = '
202
                SELECT `id`
203
                FROM `' . TB_TELEGRAM_UPDATE . '`
204
            ';
205
206
            if ($id !== null) {
207
                $sql .= ' WHERE `id` = :id';
208
            } else {
209
                $sql .= ' ORDER BY `id` DESC';
210
            }
211
212
            if ($limit !== null) {
213
                $sql .= ' LIMIT :limit';
214
            }
215
216
            $sth = self::$pdo->prepare($sql);
217
218
            if ($limit !== null) {
219
                $sth->bindValue(':limit', $limit, PDO::PARAM_INT);
220
            }
221
            if ($id !== null) {
222
                $sth->bindValue(':id', $id);
223
            }
224
225
            $sth->execute();
226
227
            return $sth->fetchAll(PDO::FETCH_ASSOC);
228
        } catch (PDOException $e) {
229
            throw new TelegramException($e->getMessage());
230
        }
231
    }
232
233
    /**
234
     * Fetch message(s) from DB
235
     *
236
     * @param int $limit Limit the number of messages to fetch
237
     *
238
     * @return array|bool Fetched data or false if not connected
239
     * @throws TelegramException
240
     */
241
    public static function selectMessages($limit = null)
242
    {
243
        if (!self::isDbConnected()) {
244
            return false;
245
        }
246
247
        try {
248
            $sql = '
249
                SELECT *
250
                FROM `' . TB_MESSAGE . '`
251
                ORDER BY `id` DESC
252
            ';
253
254
            if ($limit !== null) {
255
                $sql .= ' LIMIT :limit';
256
            }
257
258
            $sth = self::$pdo->prepare($sql);
259
260
            if ($limit !== null) {
261
                $sth->bindValue(':limit', $limit, PDO::PARAM_INT);
262
            }
263
264
            $sth->execute();
265
266
            return $sth->fetchAll(PDO::FETCH_ASSOC);
267
        } catch (PDOException $e) {
268
            throw new TelegramException($e->getMessage());
269
        }
270
    }
271
272
    /**
273
     * Convert from unix timestamp to timestamp
274
     *
275
     * @param int $time Unix timestamp (if empty, current timestamp is used)
276
     *
277
     * @return string
278
     */
279 7
    protected static function getTimestamp($time = null)
280
    {
281 7
        return date('Y-m-d H:i:s', $time ?: time());
282
    }
283
284
    /**
285
     * Convert array of Entity items to a JSON array
286
     *
287
     * @todo Find a better way, as json_* functions are very heavy
288
     *
289
     * @param array|null $entities
290
     * @param mixed      $default
291
     *
292
     * @return mixed
293
     */
294 6
    public static function entitiesArrayToJson($entities, $default = null)
295
    {
296 6
        if (!is_array($entities)) {
297 6
            return $default;
298
        }
299
300
        // Convert each Entity item into an object based on its JSON reflection
301
        $json_entities = array_map(function ($entity) {
302
            return json_decode($entity, true);
303
        }, $entities);
304
305
        return json_encode($json_entities);
306
    }
307
308
    /**
309
     * Insert entry to telegram_update table
310
     *
311
     * @param string      $update_id
312
     * @param string|null $chat_id
313
     * @param string|null $message_id
314
     * @param string|null $edited_message_id
315
     * @param string|null $channel_post_id
316
     * @param string|null $edited_channel_post_id
317
     * @param string|null $inline_query_id
318
     * @param string|null $chosen_inline_result_id
319
     * @param string|null $callback_query_id
320
     * @param string|null $shipping_query_id
321
     * @param string|null $pre_checkout_query_id
322
     * @param string|null $poll_id
323
     * @param string|null $poll_answer_poll_id
324
     *
325
     * @return bool If the insert was successful
326
     * @throws TelegramException
327
     */
328
    protected static function insertTelegramUpdate(
329
        $update_id,
330
        $chat_id = null,
331
        $message_id = null,
332
        $edited_message_id = null,
333
        $channel_post_id = null,
334
        $edited_channel_post_id = null,
335
        $inline_query_id = null,
336
        $chosen_inline_result_id = null,
337
        $callback_query_id = null,
338
        $shipping_query_id = null,
339
        $pre_checkout_query_id = null,
340
        $poll_id = null,
341
        $poll_answer_poll_id = null
342
    ) {
343
        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) {
344
            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 are all null');
345
        }
346
347
        if (!self::isDbConnected()) {
348
            return false;
349
        }
350
351
        try {
352
            $sth = self::$pdo->prepare('
353
                INSERT IGNORE INTO `' . TB_TELEGRAM_UPDATE . '`
354
                (`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`)
355
                VALUES
356
                (: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)
357
            ');
358
359
            $sth->bindValue(':id', $update_id);
360
            $sth->bindValue(':chat_id', $chat_id);
361
            $sth->bindValue(':message_id', $message_id);
362
            $sth->bindValue(':edited_message_id', $edited_message_id);
363
            $sth->bindValue(':channel_post_id', $channel_post_id);
364
            $sth->bindValue(':edited_channel_post_id', $edited_channel_post_id);
365
            $sth->bindValue(':inline_query_id', $inline_query_id);
366
            $sth->bindValue(':chosen_inline_result_id', $chosen_inline_result_id);
367
            $sth->bindValue(':callback_query_id', $callback_query_id);
368
            $sth->bindValue(':shipping_query_id', $shipping_query_id);
369
            $sth->bindValue(':pre_checkout_query_id', $pre_checkout_query_id);
370
            $sth->bindValue(':poll_id', $poll_id);
371
            $sth->bindValue(':poll_answer_poll_id', $poll_answer_poll_id);
372
373
            return $sth->execute();
374
        } catch (PDOException $e) {
375
            throw new TelegramException($e->getMessage());
376
        }
377
    }
378
379
    /**
380
     * Insert users and save their connection to chats
381
     *
382
     * @param User   $user
383
     * @param string $date
384
     * @param Chat   $chat
385
     *
386
     * @return bool If the insert was successful
387
     * @throws TelegramException
388
     */
389 6
    public static function insertUser(User $user, $date = null, Chat $chat = null)
390
    {
391 6
        if (!self::isDbConnected()) {
392
            return false;
393
        }
394
395
        try {
396 6
            $sth = self::$pdo->prepare('
397 6
                INSERT INTO `' . TB_USER . '`
398
                (`id`, `is_bot`, `username`, `first_name`, `last_name`, `language_code`, `created_at`, `updated_at`)
399
                VALUES
400
                (:id, :is_bot, :username, :first_name, :last_name, :language_code, :created_at, :updated_at)
401
                ON DUPLICATE KEY UPDATE
402
                    `is_bot`         = VALUES(`is_bot`),
403
                    `username`       = VALUES(`username`),
404
                    `first_name`     = VALUES(`first_name`),
405
                    `last_name`      = VALUES(`last_name`),
406
                    `language_code`  = VALUES(`language_code`),
407
                    `updated_at`     = VALUES(`updated_at`)
408
            ');
409
410 6
            $sth->bindValue(':id', $user->getId());
411 6
            $sth->bindValue(':is_bot', $user->getIsBot(), PDO::PARAM_INT);
412 6
            $sth->bindValue(':username', $user->getUsername());
413 6
            $sth->bindValue(':first_name', $user->getFirstName());
414 6
            $sth->bindValue(':last_name', $user->getLastName());
415 6
            $sth->bindValue(':language_code', $user->getLanguageCode());
416 6
            $date = $date ?: self::getTimestamp();
417 6
            $sth->bindValue(':created_at', $date);
418 6
            $sth->bindValue(':updated_at', $date);
419
420 6
            $status = $sth->execute();
421
        } catch (PDOException $e) {
422
            throw new TelegramException($e->getMessage());
423
        }
424
425
        // Also insert the relationship to the chat into the user_chat table
426 6
        if ($chat instanceof Chat) {
427
            try {
428 6
                $sth = self::$pdo->prepare('
429 6
                    INSERT IGNORE INTO `' . TB_USER_CHAT . '`
430
                    (`user_id`, `chat_id`)
431
                    VALUES
432
                    (:user_id, :chat_id)
433
                ');
434
435 6
                $sth->bindValue(':user_id', $user->getId());
436 6
                $sth->bindValue(':chat_id', $chat->getId());
437
438 6
                $status = $sth->execute();
439
            } catch (PDOException $e) {
440
                throw new TelegramException($e->getMessage());
441
            }
442
        }
443
444 6
        return $status;
445
    }
446
447
    /**
448
     * Insert chat
449
     *
450
     * @param Chat   $chat
451
     * @param string $date
452
     * @param string $migrate_to_chat_id
453
     *
454
     * @return bool If the insert was successful
455
     * @throws TelegramException
456
     */
457 6
    public static function insertChat(Chat $chat, $date = null, $migrate_to_chat_id = null)
458
    {
459 6
        if (!self::isDbConnected()) {
460
            return false;
461
        }
462
463
        try {
464 6
            $sth = self::$pdo->prepare('
465 6
                INSERT IGNORE INTO `' . TB_CHAT . '`
466
                (`id`, `type`, `title`, `username`, `first_name`, `last_name`, `all_members_are_administrators`, `created_at` ,`updated_at`, `old_id`)
467
                VALUES
468
                (:id, :type, :title, :username, :first_name, :last_name, :all_members_are_administrators, :created_at, :updated_at, :old_id)
469
                ON DUPLICATE KEY UPDATE
470
                    `type`                           = VALUES(`type`),
471
                    `title`                          = VALUES(`title`),
472
                    `username`                       = VALUES(`username`),
473
                    `first_name`                     = VALUES(`first_name`),
474
                    `last_name`                      = VALUES(`last_name`),
475
                    `all_members_are_administrators` = VALUES(`all_members_are_administrators`),
476
                    `updated_at`                     = VALUES(`updated_at`)
477
            ');
478
479 6
            $chat_id   = $chat->getId();
480 6
            $chat_type = $chat->getType();
481
482 6
            if ($migrate_to_chat_id !== null) {
483
                $chat_type = 'supergroup';
484
485
                $sth->bindValue(':id', $migrate_to_chat_id);
486
                $sth->bindValue(':old_id', $chat_id);
487
            } else {
488 6
                $sth->bindValue(':id', $chat_id);
489 6
                $sth->bindValue(':old_id', $migrate_to_chat_id);
490
            }
491
492 6
            $sth->bindValue(':type', $chat_type);
493 6
            $sth->bindValue(':title', $chat->getTitle());
494 6
            $sth->bindValue(':username', $chat->getUsername());
495 6
            $sth->bindValue(':first_name', $chat->getFirstName());
496 6
            $sth->bindValue(':last_name', $chat->getLastName());
497 6
            $sth->bindValue(':all_members_are_administrators', $chat->getAllMembersAreAdministrators(), PDO::PARAM_INT);
0 ignored issues
show
Bug introduced by
The method getAllMembersAreAdministrators() does not exist on Longman\TelegramBot\Entities\Chat. 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

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

965
        /** @scrutinizer ignore-call */ 
966
        $new_chat_members = $message->getNewChatMembers();
Loading history...
966 6
        $left_chat_member = $message->getLeftChatMember();
967 6
        if (!empty($new_chat_members)) {
968
            foreach ($new_chat_members as $new_chat_member) {
969
                if ($new_chat_member instanceof User) {
970
                    // Insert the new chat user
971
                    self::insertUser($new_chat_member, $date, $chat);
972
                    $new_chat_members_ids[] = $new_chat_member->getId();
973
                }
974
            }
975
            $new_chat_members_ids = implode(',', $new_chat_members_ids);
976 6
        } elseif ($left_chat_member instanceof User) {
0 ignored issues
show
introduced by
$left_chat_member is always a sub-type of Longman\TelegramBot\Entities\User.
Loading history...
977
            // Insert the left chat user
978
            self::insertUser($left_chat_member, $date, $chat);
979
            $left_chat_member_id = $left_chat_member->getId();
980
        }
981
982
        try {
983 6
            $sth = self::$pdo->prepare('
984 6
                INSERT IGNORE INTO `' . TB_MESSAGE . '`
985
                (
986
                    `id`, `user_id`, `chat_id`, `date`, `forward_from`, `forward_from_chat`, `forward_from_message_id`,
987
                    `forward_signature`, `forward_sender_name`, `forward_date`,
988
                    `reply_to_chat`, `reply_to_message`, `edit_date`, `media_group_id`, `author_signature`, `text`, `entities`, `caption_entities`,
989
                    `audio`, `document`, `animation`, `game`, `photo`, `sticker`, `video`, `voice`, `video_note`, `caption`, `contact`,
990
                    `location`, `venue`, `poll`, `new_chat_members`, `left_chat_member`,
991
                    `new_chat_title`, `new_chat_photo`, `delete_chat_photo`, `group_chat_created`,
992
                    `supergroup_chat_created`, `channel_chat_created`, `migrate_to_chat_id`, `migrate_from_chat_id`,
993
                    `pinned_message`, `invoice`, `successful_payment`, `connected_website`, `passport_data`, `reply_markup`
994
                ) VALUES (
995
                    :message_id, :user_id, :chat_id, :date, :forward_from, :forward_from_chat, :forward_from_message_id,
996
                    :forward_signature, :forward_sender_name, :forward_date,
997
                    :reply_to_chat, :reply_to_message, :edit_date, :media_group_id, :author_signature, :text, :entities, :caption_entities,
998
                    :audio, :document, :animation, :game, :photo, :sticker, :video, :voice, :video_note, :caption, :contact,
999
                    :location, :venue, :poll, :new_chat_members, :left_chat_member,
1000
                    :new_chat_title, :new_chat_photo, :delete_chat_photo, :group_chat_created,
1001
                    :supergroup_chat_created, :channel_chat_created, :migrate_to_chat_id, :migrate_from_chat_id,
1002
                    :pinned_message, :invoice, :successful_payment, :connected_website, :passport_data, :reply_markup
1003
                )
1004
            ');
1005
1006 6
            $user_id = null;
1007 6
            if ($user instanceof User) {
0 ignored issues
show
introduced by
$user is always a sub-type of Longman\TelegramBot\Entities\User.
Loading history...
1008 6
                $user_id = $user->getId();
1009
            }
1010 6
            $chat_id = $chat->getId();
1011
1012 6
            $reply_to_message    = $message->getReplyToMessage();
1013 6
            $reply_to_message_id = null;
1014 6
            if ($reply_to_message instanceof ReplyToMessage) {
1015
                $reply_to_message_id = $reply_to_message->getMessageId();
1016
                // please notice that, as explained in the documentation, reply_to_message don't contain other
1017
                // reply_to_message field so recursion deep is 1
1018
                self::insertMessageRequest($reply_to_message);
1019
            }
1020
1021 6
            $sth->bindValue(':message_id', $message->getMessageId());
1022 6
            $sth->bindValue(':chat_id', $chat_id);
1023 6
            $sth->bindValue(':user_id', $user_id);
1024 6
            $sth->bindValue(':date', $date);
1025 6
            $sth->bindValue(':forward_from', $forward_from);
1026 6
            $sth->bindValue(':forward_from_chat', $forward_from_chat);
1027 6
            $sth->bindValue(':forward_from_message_id', $message->getForwardFromMessageId());
1028 6
            $sth->bindValue(':forward_signature', $message->getForwardSignature());
1029 6
            $sth->bindValue(':forward_sender_name', $message->getForwardSenderName());
1030 6
            $sth->bindValue(':forward_date', $forward_date);
1031
1032 6
            $reply_to_chat_id = null;
1033 6
            if ($reply_to_message_id !== null) {
1034
                $reply_to_chat_id = $chat_id;
1035
            }
1036 6
            $sth->bindValue(':reply_to_chat', $reply_to_chat_id);
1037 6
            $sth->bindValue(':reply_to_message', $reply_to_message_id);
1038
1039 6
            $sth->bindValue(':edit_date', $message->getEditDate());
1040 6
            $sth->bindValue(':media_group_id', $message->getMediaGroupId());
1041 6
            $sth->bindValue(':author_signature', $message->getAuthorSignature());
1042 6
            $sth->bindValue(':text', $message->getText());
1043 6
            $sth->bindValue(':entities', self::entitiesArrayToJson($message->getEntities() ?: null));
1044 6
            $sth->bindValue(':caption_entities', self::entitiesArrayToJson($message->getCaptionEntities() ?: null));
1045 6
            $sth->bindValue(':audio', $message->getAudio());
1046 6
            $sth->bindValue(':document', $message->getDocument());
1047 6
            $sth->bindValue(':animation', $message->getAnimation());
1048 6
            $sth->bindValue(':game', $message->getGame());
1049 6
            $sth->bindValue(':photo', self::entitiesArrayToJson($message->getPhoto() ?: null));
1050 6
            $sth->bindValue(':sticker', $message->getSticker());
1051 6
            $sth->bindValue(':video', $message->getVideo());
1052 6
            $sth->bindValue(':voice', $message->getVoice());
1053 6
            $sth->bindValue(':video_note', $message->getVideoNote());
1054 6
            $sth->bindValue(':caption', $message->getCaption());
1055 6
            $sth->bindValue(':contact', $message->getContact());
1056 6
            $sth->bindValue(':location', $message->getLocation());
1057 6
            $sth->bindValue(':venue', $message->getVenue());
1058 6
            $sth->bindValue(':poll', $message->getPoll());
1059 6
            $sth->bindValue(':new_chat_members', $new_chat_members_ids);
1060 6
            $sth->bindValue(':left_chat_member', $left_chat_member_id);
1061 6
            $sth->bindValue(':new_chat_title', $message->getNewChatTitle());
1062 6
            $sth->bindValue(':new_chat_photo', self::entitiesArrayToJson($message->getNewChatPhoto() ?: null));
1063 6
            $sth->bindValue(':delete_chat_photo', $message->getDeleteChatPhoto());
1064 6
            $sth->bindValue(':group_chat_created', $message->getGroupChatCreated());
1065 6
            $sth->bindValue(':supergroup_chat_created', $message->getSupergroupChatCreated());
1066 6
            $sth->bindValue(':channel_chat_created', $message->getChannelChatCreated());
1067 6
            $sth->bindValue(':migrate_to_chat_id', $message->getMigrateToChatId());
1068 6
            $sth->bindValue(':migrate_from_chat_id', $message->getMigrateFromChatId());
1069 6
            $sth->bindValue(':pinned_message', $message->getPinnedMessage());
1070 6
            $sth->bindValue(':invoice', $message->getInvoice());
1071 6
            $sth->bindValue(':successful_payment', $message->getSuccessfulPayment());
1072 6
            $sth->bindValue(':connected_website', $message->getConnectedWebsite());
1073 6
            $sth->bindValue(':passport_data', $message->getPassportData());
1074 6
            $sth->bindValue(':reply_markup', $message->getReplyMarkup());
1075
1076 6
            return $sth->execute();
1077
        } catch (PDOException $e) {
1078
            throw new TelegramException($e->getMessage());
1079
        }
1080
    }
1081
1082
    /**
1083
     * Insert Edited Message request in db
1084
     *
1085
     * @param Message $edited_message
1086
     *
1087
     * @return bool If the insert was successful
1088
     * @throws TelegramException
1089
     */
1090
    public static function insertEditedMessageRequest(Message $edited_message)
1091
    {
1092
        if (!self::isDbConnected()) {
1093
            return false;
1094
        }
1095
1096
        try {
1097
            $edit_date = self::getTimestamp($edited_message->getEditDate());
1098
1099
            // Insert chat
1100
            $chat = $edited_message->getChat();
1101
            self::insertChat($chat, $edit_date);
1102
1103
            // Insert user and the relation with the chat
1104
            $user = $edited_message->getFrom();
1105
            if ($user instanceof User) {
0 ignored issues
show
introduced by
$user is always a sub-type of Longman\TelegramBot\Entities\User.
Loading history...
1106
                self::insertUser($user, $edit_date, $chat);
1107
            }
1108
1109
            $sth = self::$pdo->prepare('
1110
                INSERT IGNORE INTO `' . TB_EDITED_MESSAGE . '`
1111
                (`chat_id`, `message_id`, `user_id`, `edit_date`, `text`, `entities`, `caption`)
1112
                VALUES
1113
                (:chat_id, :message_id, :user_id, :edit_date, :text, :entities, :caption)
1114
            ');
1115
1116
            $user_id = null;
1117
            if ($user instanceof User) {
0 ignored issues
show
introduced by
$user is always a sub-type of Longman\TelegramBot\Entities\User.
Loading history...
1118
                $user_id = $user->getId();
1119
            }
1120
1121
            $sth->bindValue(':chat_id', $chat->getId());
1122
            $sth->bindValue(':message_id', $edited_message->getMessageId());
1123
            $sth->bindValue(':user_id', $user_id);
1124
            $sth->bindValue(':edit_date', $edit_date);
1125
            $sth->bindValue(':text', $edited_message->getText());
1126
            $sth->bindValue(':entities', self::entitiesArrayToJson($edited_message->getEntities() ?: null));
1127
            $sth->bindValue(':caption', $edited_message->getCaption());
1128
1129
            return $sth->execute();
1130
        } catch (PDOException $e) {
1131
            throw new TelegramException($e->getMessage());
1132
        }
1133
    }
1134
1135
    /**
1136
     * Select Groups, Supergroups, Channels and/or single user Chats (also by ID or text)
1137
     *
1138
     * @param $select_chats_params
1139
     *
1140
     * @return array|bool
1141
     * @throws TelegramException
1142
     */
1143
    public static function selectChats($select_chats_params)
1144
    {
1145
        if (!self::isDbConnected()) {
1146
            return false;
1147
        }
1148
1149
        // Set defaults for omitted values.
1150
        $select = array_merge([
1151
            'groups'      => true,
1152
            'supergroups' => true,
1153
            'channels'    => true,
1154
            'users'       => true,
1155
            'date_from'   => null,
1156
            'date_to'     => null,
1157
            'chat_id'     => null,
1158
            'text'        => null,
1159
            'language'    => null,
1160
        ], $select_chats_params);
1161
1162
        if (!$select['groups'] && !$select['users'] && !$select['supergroups'] && !$select['channels']) {
1163
            return false;
1164
        }
1165
1166
        try {
1167
            $query = '
1168
                SELECT * ,
1169
                ' . TB_CHAT . '.`id` AS `chat_id`,
1170
                ' . TB_CHAT . '.`username` AS `chat_username`,
1171
                ' . TB_CHAT . '.`created_at` AS `chat_created_at`,
1172
                ' . TB_CHAT . '.`updated_at` AS `chat_updated_at`
1173
            ';
1174
            if ($select['users']) {
1175
                $query .= '
1176
                    , ' . TB_USER . '.`id` AS `user_id`
1177
                    FROM `' . TB_CHAT . '`
1178
                    LEFT JOIN `' . TB_USER . '`
1179
                    ON ' . TB_CHAT . '.`id`=' . TB_USER . '.`id`
1180
                ';
1181
            } else {
1182
                $query .= 'FROM `' . TB_CHAT . '`';
1183
            }
1184
1185
            // Building parts of query
1186
            $where  = [];
1187
            $tokens = [];
1188
1189
            if (!$select['groups'] || !$select['users'] || !$select['supergroups'] || !$select['channels']) {
1190
                $chat_or_user = [];
1191
1192
                $select['groups'] && $chat_or_user[] = TB_CHAT . '.`type` = "group"';
1193
                $select['supergroups'] && $chat_or_user[] = TB_CHAT . '.`type` = "supergroup"';
1194
                $select['channels'] && $chat_or_user[] = TB_CHAT . '.`type` = "channel"';
1195
                $select['users'] && $chat_or_user[] = TB_CHAT . '.`type` = "private"';
1196
1197
                $where[] = '(' . implode(' OR ', $chat_or_user) . ')';
1198
            }
1199
1200
            if (null !== $select['date_from']) {
1201
                $where[]              = TB_CHAT . '.`updated_at` >= :date_from';
1202
                $tokens[':date_from'] = $select['date_from'];
1203
            }
1204
1205
            if (null !== $select['date_to']) {
1206
                $where[]            = TB_CHAT . '.`updated_at` <= :date_to';
1207
                $tokens[':date_to'] = $select['date_to'];
1208
            }
1209
1210
            if (null !== $select['chat_id']) {
1211
                $where[]            = TB_CHAT . '.`id` = :chat_id';
1212
                $tokens[':chat_id'] = $select['chat_id'];
1213
            }
1214
1215
            if ($select['users'] && null !== $select['language']) {
1216
                $where[]             = TB_USER . '.`language_code` = :language';
1217
                $tokens[':language'] = $select['language'];
1218
            }
1219
1220
            if (null !== $select['text']) {
1221
                $text_like = '%' . strtolower($select['text']) . '%';
1222
                if ($select['users']) {
1223
                    $where[]          = '(
1224
                        LOWER(' . TB_CHAT . '.`title`) LIKE :text1
1225
                        OR LOWER(' . TB_USER . '.`first_name`) LIKE :text2
1226
                        OR LOWER(' . TB_USER . '.`last_name`) LIKE :text3
1227
                        OR LOWER(' . TB_USER . '.`username`) LIKE :text4
1228
                    )';
1229
                    $tokens[':text1'] = $text_like;
1230
                    $tokens[':text2'] = $text_like;
1231
                    $tokens[':text3'] = $text_like;
1232
                    $tokens[':text4'] = $text_like;
1233
                } else {
1234
                    $where[]         = 'LOWER(' . TB_CHAT . '.`title`) LIKE :text';
1235
                    $tokens[':text'] = $text_like;
1236
                }
1237
            }
1238
1239
            if (!empty($where)) {
1240
                $query .= ' WHERE ' . implode(' AND ', $where);
1241
            }
1242
1243
            $query .= ' ORDER BY ' . TB_CHAT . '.`updated_at` ASC';
1244
1245
            $sth = self::$pdo->prepare($query);
1246
            $sth->execute($tokens);
1247
1248
            return $sth->fetchAll(PDO::FETCH_ASSOC);
1249
        } catch (PDOException $e) {
1250
            throw new TelegramException($e->getMessage());
1251
        }
1252
    }
1253
1254
    /**
1255
     * Get Telegram API request count for current chat / message
1256
     *
1257
     * @param integer $chat_id
1258
     * @param string  $inline_message_id
1259
     *
1260
     * @return array Array containing TOTAL and CURRENT fields or false on invalid arguments
1261
     * @throws TelegramException
1262
     */
1263
    public static function getTelegramRequestCount($chat_id = null, $inline_message_id = null)
1264
    {
1265
        if (!self::isDbConnected()) {
1266
            return [];
1267
        }
1268
1269
        try {
1270
            $sth = self::$pdo->prepare('SELECT
1271
                (SELECT COUNT(DISTINCT `chat_id`) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_1) AS LIMIT_PER_SEC_ALL,
1272
                (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,
1273
                (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :created_at_minute AND `chat_id` = :chat_id_2) AS LIMIT_PER_MINUTE
1274
            ');
1275
1276
            $date        = self::getTimestamp();
1277
            $date_minute = self::getTimestamp(strtotime('-1 minute'));
1278
1279
            $sth->bindValue(':chat_id_1', $chat_id);
1280
            $sth->bindValue(':chat_id_2', $chat_id);
1281
            $sth->bindValue(':inline_message_id', $inline_message_id);
1282
            $sth->bindValue(':created_at_1', $date);
1283
            $sth->bindValue(':created_at_2', $date);
1284
            $sth->bindValue(':created_at_minute', $date_minute);
1285
1286
            $sth->execute();
1287
1288
            return $sth->fetch();
1289
        } catch (PDOException $e) {
1290
            throw new TelegramException($e->getMessage());
1291
        }
1292
    }
1293
1294
    /**
1295
     * Insert Telegram API request in db
1296
     *
1297
     * @param string $method
1298
     * @param array  $data
1299
     *
1300
     * @return bool If the insert was successful
1301
     * @throws TelegramException
1302
     */
1303
    public static function insertTelegramRequest($method, $data)
1304
    {
1305
        if (!self::isDbConnected()) {
1306
            return false;
1307
        }
1308
1309
        try {
1310
            $sth = self::$pdo->prepare('INSERT INTO `' . TB_REQUEST_LIMITER . '`
1311
                (`method`, `chat_id`, `inline_message_id`, `created_at`)
1312
                VALUES
1313
                (:method, :chat_id, :inline_message_id, :created_at);
1314
            ');
1315
1316
            $chat_id           = isset($data['chat_id']) ? $data['chat_id'] : null;
1317
            $inline_message_id = isset($data['inline_message_id']) ? $data['inline_message_id'] : null;
1318
1319
            $sth->bindValue(':chat_id', $chat_id);
1320
            $sth->bindValue(':inline_message_id', $inline_message_id);
1321
            $sth->bindValue(':method', $method);
1322
            $sth->bindValue(':created_at', self::getTimestamp());
1323
1324
            return $sth->execute();
1325
        } catch (PDOException $e) {
1326
            throw new TelegramException($e->getMessage());
1327
        }
1328
    }
1329
1330
    /**
1331
     * Bulk update the entries of any table
1332
     *
1333
     * @param string $table
1334
     * @param array  $fields_values
1335
     * @param array  $where_fields_values
1336
     *
1337
     * @return bool
1338
     * @throws TelegramException
1339
     */
1340 3
    public static function update($table, array $fields_values, array $where_fields_values)
1341
    {
1342 3
        if (empty($fields_values) || !self::isDbConnected()) {
1343
            return false;
1344
        }
1345
1346
        try {
1347
            // Building parts of query
1348 3
            $tokens = $fields = $where = [];
1349
1350
            // Fields with values to update
1351 3
            foreach ($fields_values as $field => $value) {
1352 3
                $token          = ':' . count($tokens);
1353 3
                $fields[]       = "`{$field}` = {$token}";
1354 3
                $tokens[$token] = $value;
1355
            }
1356
1357
            // Where conditions
1358 3
            foreach ($where_fields_values as $field => $value) {
1359 3
                $token          = ':' . count($tokens);
1360 3
                $where[]        = "`{$field}` = {$token}";
1361 3
                $tokens[$token] = $value;
1362
            }
1363
1364 3
            $sql = 'UPDATE `' . $table . '` SET ' . implode(', ', $fields);
1365 3
            $sql .= count($where) > 0 ? ' WHERE ' . implode(' AND ', $where) : '';
1366
1367 3
            return self::$pdo->prepare($sql)->execute($tokens);
1368
        } catch (PDOException $e) {
1369
            throw new TelegramException($e->getMessage());
1370
        }
1371
    }
1372
}
1373