Passed
Push — scrutinizer_fixes ( 163d53 )
by Armando
03:04
created

DB::insertTelegramUpdate()   C

Complexity

Conditions 13
Paths 17

Size

Total Lines 46
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 13
eloc 22
c 4
b 0
f 0
nc 17
nop 12
dl 0
loc 46
ccs 0
cts 22
cp 0
crap 182
rs 6.6166

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

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

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