Passed
Push — master ( 78024d...fb0f34 )
by Armando
02:41
created

DB::insertMessageRequest()   F

Complexity

Conditions 19
Paths > 20000

Size

Total Lines 151
Code Lines 96

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 77
CRAP Score 21.7978

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 19
eloc 96
c 6
b 0
f 0
nc 37057
nop 1
dl 0
loc 151
ccs 77
cts 96
cp 0.8021
crap 21.7978
rs 0.3672

How to fix   Long Method    Complexity   

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

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

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