Passed
Push — master ( 85d52f...78024d )
by Armando
01:42
created

DB::insertTelegramUpdate()   C

Complexity

Conditions 14
Paths 18

Size

Total Lines 48
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 210

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 14
eloc 23
c 4
b 0
f 0
nc 18
nop 13
dl 0
loc 48
ccs 0
cts 23
cp 0
crap 210
rs 6.2666

How to fix   Complexity    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
            $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`, `created_at`)
841
                VALUES
842
                (:id, :question, :options, :total_voter_count, :is_closed, :is_anonymous, :type, :allows_multiple_answers, :correct_option_id, :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
            ');
852
853
            $sth->bindValue(':id', $poll->getId());
854
            $sth->bindValue(':question', $poll->getQuestion());
855
            $sth->bindValue(':options', self::entitiesArrayToJson($poll->getOptions() ?: null));
856
            $sth->bindValue(':total_voter_count', $poll->getTotalVoterCount());
857
            $sth->bindValue(':is_closed', $poll->getIsClosed(), PDO::PARAM_INT);
858
            $sth->bindValue(':is_anonymous', $poll->getIsAnonymous(), PDO::PARAM_INT);
859
            $sth->bindValue(':type', $poll->getType());
860
            $sth->bindValue(':allows_multiple_answers', $poll->getAllowsMultipleAnswers(), PDO::PARAM_INT);
861
            $sth->bindValue(':correct_option_id', $poll->getCorrectOptionId());
862
            $sth->bindValue(':created_at', self::getTimestamp());
863
864
            return $sth->execute();
865
        } catch (PDOException $e) {
866
            throw new TelegramException($e->getMessage());
867
        }
868
    }
869
870
    /**
871
     * Insert poll answer request into database
872
     *
873
     * @param PollAnswer $poll_answer
874
     *
875
     * @return bool If the insert was successful
876
     * @throws TelegramException
877
     */
878
    public static function insertPollAnswerRequest(PollAnswer $poll_answer)
879
    {
880
        if (!self::isDbConnected()) {
881
            return false;
882
        }
883
884
        try {
885
            $sth = self::$pdo->prepare('
886
                INSERT INTO `' . TB_POLL_ANSWER . '`
887
                (`poll_id`, `user_id`, `option_ids`, `created_at`)
888
                VALUES
889
                (:poll_id, :user_id, :option_ids, :created_at)
890
                ON DUPLICATE KEY UPDATE
891
                    `option_ids` = VALUES(`option_ids`)
892
            ');
893
894
            $date    = self::getTimestamp();
895
            $user_id = null;
896
897
            if ($user = $poll_answer->getUser()) {
898
                $user_id = $user->getId();
899
                self::insertUser($user, $date);
900
            }
901
902
            $sth->bindValue(':poll_id', $poll_answer->getPollId());
903
            $sth->bindValue(':user_id', $user_id);
904
            $sth->bindValue(':option_ids', json_encode($poll_answer->getOptionIds()));
905
            $sth->bindValue(':created_at', $date);
906
907
            return $sth->execute();
908
        } catch (PDOException $e) {
909
            throw new TelegramException($e->getMessage());
910
        }
911
    }
912
913
    /**
914
     * Insert Message request in db
915
     *
916
     * @param Message $message
917
     *
918
     * @return bool If the insert was successful
919
     * @throws TelegramException
920
     */
921 6
    public static function insertMessageRequest(Message $message)
922
    {
923 6
        if (!self::isDbConnected()) {
924
            return false;
925
        }
926
927 6
        $date = self::getTimestamp($message->getDate());
928
929
        // Insert chat, update chat id in case it migrated
930 6
        $chat = $message->getChat();
931 6
        self::insertChat($chat, $date, $message->getMigrateToChatId());
932
933
        // Insert user and the relation with the chat
934 6
        if ($user = $message->getFrom()) {
935 6
            self::insertUser($user, $date, $chat);
936
        }
937
938
        // Insert the forwarded message user in users table
939 6
        $forward_date = $message->getForwardDate() ? self::getTimestamp($message->getForwardDate()) : null;
940
941 6
        if ($forward_from = $message->getForwardFrom()) {
942
            self::insertUser($forward_from);
943
            $forward_from = $forward_from->getId();
944
        }
945 6
        if ($forward_from_chat = $message->getForwardFromChat()) {
946
            self::insertChat($forward_from_chat);
947
            $forward_from_chat = $forward_from_chat->getId();
948
        }
949
950
        // New and left chat member
951 6
        $new_chat_members_ids = null;
952 6
        $left_chat_member_id  = null;
953
954 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

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