Completed
Push — 1049_bot_api_4.6 ( 001325...265fe5 )
by Armando
15s queued 12s
created

DB::insertMessageRequest()   F

Complexity

Conditions 18
Paths 17761

Size

Total Lines 143
Code Lines 90

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 73
CRAP Score 20.1839

Importance

Changes 7
Bugs 0 Features 0
Metric Value
cc 18
eloc 90
c 7
b 0
f 0
nc 17761
nop 1
dl 0
loc 143
ccs 73
cts 90
cp 0.8111
crap 20.1839
rs 0.7781

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
            $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();
0 ignored issues
show
introduced by
$user is always a sub-type of Longman\TelegramBot\Entities\User.
Loading history...
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
    public static function insertMessageRequest(Message $message)
922 6
    {
923
        if (!self::isDbConnected()) {
924 6
            return false;
925
        }
926
927
        $date = self::getTimestamp($message->getDate());
928 6
929
        // Insert chat, update chat id in case it migrated
930
        $chat = $message->getChat();
931 6
        self::insertChat($chat, $date, $message->getMigrateToChatId());
932 6
933
        // Insert user and the relation with the chat
934
        if ($user = $message->getFrom()) {
935 6
            self::insertUser($user, $date, $chat);
936 6
        }
937
938
        // Insert the forwarded message user in users table
939
        $forward_date = $message->getForwardDate() ? self::getTimestamp($message->getForwardDate()) : null;
940 6
941
        if ($forward_from = $message->getForwardFrom()) {
942 6
            self::insertUser($forward_from);
943
            $forward_from = $forward_from->getId();
944
        }
945
        if ($forward_from_chat = $message->getForwardFromChat()) {
946 6
            self::insertChat($forward_from_chat);
947
            $forward_from_chat = $forward_from_chat->getId();
948
        }
949
950
        // New and left chat member
951
        $new_chat_members_ids = null;
952 6
        $left_chat_member_id  = null;
953 6
954
        $new_chat_members = $message->getNewChatMembers();
955 6
        $left_chat_member = $message->getLeftChatMember();
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

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