Completed
Push — master ( 9d4d02...0bdd7a )
by Armando
06:45
created

DB::insertChat()   B

Complexity

Conditions 4
Paths 20

Size

Total Lines 47
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 4.25

Importance

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

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
449
                $chat_type = 'supergroup';
450
451
                $sth->bindParam(':id', $migrate_to_chat_id, PDO::PARAM_INT);
452
                $sth->bindParam(':oldid', $chat_id, PDO::PARAM_INT);
453
            } else {
454 6
                $sth->bindParam(':id', $chat_id, PDO::PARAM_INT);
455 6
                $sth->bindParam(':oldid', $migrate_to_chat_id, PDO::PARAM_INT);
456
            }
457
458 6
            $sth->bindParam(':type', $chat_type, PDO::PARAM_INT);
459 6
            $sth->bindParam(':title', $chat_title, PDO::PARAM_STR, 255);
460 6
            $sth->bindParam(':username', $chat_username, PDO::PARAM_STR, 255);
461 6
            $sth->bindParam(':all_members_are_administrators', $chat_all_members_are_administrators, PDO::PARAM_INT);
462 6
            $sth->bindParam(':date', $date, PDO::PARAM_STR);
463
464 6
            return $sth->execute();
465
        } catch (PDOException $e) {
466
            throw new TelegramException($e->getMessage());
467
        }
468
    }
469
470
    /**
471
     * Insert request into database
472
     *
473
     * @todo self::$pdo->lastInsertId() - unsafe usage if expected previous insert fails?
474
     *
475
     * @param \Longman\TelegramBot\Entities\Update $update
476
     *
477
     * @return bool
478
     * @throws \Longman\TelegramBot\Exception\TelegramException
479
     */
480
    public static function insertRequest(Update $update)
481
    {
482
        $update_id   = $update->getUpdateId();
483
        $update_type = $update->getUpdateType();
484
485
        if (count(self::selectTelegramUpdate(1, $update->getUpdateId())) === 1) {
486
            throw new TelegramException('Duplicate update received!');
487
        }
488
489
        if ($update_type === 'message') {
490
            $message = $update->getMessage();
491
492 View Code Duplication
            if (self::insertMessageRequest($message)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
493
                $message_id = $message->getMessageId();
494
                $chat_id    = $message->getChat()->getId();
495
496
                return self::insertTelegramUpdate($update_id, $chat_id, $message_id, null, null, null, null);
497
            }
498 View Code Duplication
        } elseif ($update_type === 'edited_message') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
499
            $edited_message = $update->getEditedMessage();
500
501
            if (self::insertEditedMessageRequest($edited_message)) {
502
                $chat_id                 = $edited_message->getChat()->getId();
503
                $edited_message_local_id = self::$pdo->lastInsertId();
504
505
                return self::insertTelegramUpdate(
506
                    $update_id,
507
                    $chat_id,
508
                    null,
509
                    null,
510
                    null,
511
                    null,
512
                    $edited_message_local_id
513
                );
514
            }
515
        } elseif ($update_type === 'channel_post') {
516
            $channel_post = $update->getChannelPost();
517
518 View Code Duplication
            if (self::insertMessageRequest($channel_post)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
519
                $message_id = $channel_post->getMessageId();
520
                $chat_id    = $channel_post->getChat()->getId();
521
522
                return self::insertTelegramUpdate($update_id, $chat_id, $message_id, null, null, null, null);
523
            }
524 View Code Duplication
        } elseif ($update_type === 'edited_channel_post') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
525
            $edited_channel_post = $update->getEditedChannelPost();
526
527
            if (self::insertEditedMessageRequest($edited_channel_post)) {
528
                $chat_id                      = $edited_channel_post->getChat()->getId();
529
                $edited_channel_post_local_id = self::$pdo->lastInsertId();
530
531
                return self::insertTelegramUpdate(
532
                    $update_id,
533
                    $chat_id,
534
                    null,
535
                    null,
536
                    null,
537
                    null,
538
                    $edited_channel_post_local_id
539
                );
540
            }
541
        } elseif ($update_type === 'inline_query') {
542
            $inline_query = $update->getInlineQuery();
543
544
            if (self::insertInlineQueryRequest($inline_query)) {
545
                $inline_query_id = $inline_query->getId();
546
547
                return self::insertTelegramUpdate($update_id, null, null, $inline_query_id, null, null, null);
548
            }
549
        } elseif ($update_type === 'chosen_inline_result') {
550
            $chosen_inline_result = $update->getChosenInlineResult();
551
552
            if (self::insertChosenInlineResultRequest($chosen_inline_result)) {
553
                $chosen_inline_result_local_id = self::$pdo->lastInsertId();
554
555
                return self::insertTelegramUpdate(
556
                    $update_id,
557
                    null,
558
                    null,
559
                    null,
560
                    $chosen_inline_result_local_id,
561
                    null,
562
                    null
563
                );
564
            }
565
        } elseif ($update_type === 'callback_query') {
566
            $callback_query = $update->getCallbackQuery();
567
568
            if (self::insertCallbackQueryRequest($callback_query)) {
569
                $callback_query_id = $callback_query->getId();
570
571
                return self::insertTelegramUpdate($update_id, null, null, null, null, $callback_query_id, null);
572
            }
573
        }
574
575
        return false;
576
    }
577
578
    /**
579
     * Insert inline query request into database
580
     *
581
     * @param \Longman\TelegramBot\Entities\InlineQuery $inline_query
582
     *
583
     * @return bool If the insert was successful
584
     * @throws \Longman\TelegramBot\Exception\TelegramException
585
     */
586 View Code Duplication
    public static function insertInlineQueryRequest(InlineQuery $inline_query)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
587
    {
588
        if (!self::isDbConnected()) {
589
            return false;
590
        }
591
592
        try {
593
            $sth = self::$pdo->prepare('
594
                INSERT IGNORE INTO `' . TB_INLINE_QUERY . '`
595
                (`id`, `user_id`, `location`, `query`, `offset`, `created_at`)
596
                VALUES
597
                (:inline_query_id, :user_id, :location, :query, :param_offset, :created_at)
598
            ');
599
600
            $date            = self::getTimestamp();
601
            $inline_query_id = $inline_query->getId();
602
            $from            = $inline_query->getFrom();
603
            $user_id         = null;
604
            if ($from instanceof User) {
605
                $user_id = $from->getId();
606
                self::insertUser($from, $date);
607
            }
608
609
            $location = $inline_query->getLocation();
610
            $query    = $inline_query->getQuery();
611
            $offset   = $inline_query->getOffset();
612
613
            $sth->bindParam(':inline_query_id', $inline_query_id, PDO::PARAM_INT);
614
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_INT);
615
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
616
            $sth->bindParam(':query', $query, PDO::PARAM_STR);
617
            $sth->bindParam(':param_offset', $offset, PDO::PARAM_STR);
618
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
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 \Longman\TelegramBot\Entities\ChosenInlineResult $chosen_inline_result
630
     *
631
     * @return bool If the insert was successful
632
     * @throws \Longman\TelegramBot\Exception\TelegramException
633
     */
634 View Code Duplication
    public static function insertChosenInlineResultRequest(ChosenInlineResult $chosen_inline_result)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
            $result_id = $chosen_inline_result->getResultId();
650
            $from      = $chosen_inline_result->getFrom();
651
            $user_id   = null;
652
            if ($from instanceof User) {
653
                $user_id = $from->getId();
654
                self::insertUser($from, $date);
655
            }
656
657
            $location          = $chosen_inline_result->getLocation();
658
            $inline_message_id = $chosen_inline_result->getInlineMessageId();
659
            $query             = $chosen_inline_result->getQuery();
660
661
            $sth->bindParam(':result_id', $result_id, PDO::PARAM_STR);
662
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_INT);
663
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
664
            $sth->bindParam(':inline_message_id', $inline_message_id, PDO::PARAM_STR);
665
            $sth->bindParam(':query', $query, PDO::PARAM_STR);
666
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
667
668
            return $sth->execute();
669
        } catch (PDOException $e) {
670
            throw new TelegramException($e->getMessage());
671
        }
672
    }
673
674
    /**
675
     * Insert callback query request into database
676
     *
677
     * @param \Longman\TelegramBot\Entities\CallbackQuery $callback_query
678
     *
679
     * @return bool If the insert was successful
680
     * @throws \Longman\TelegramBot\Exception\TelegramException
681
     */
682
    public static function insertCallbackQueryRequest(CallbackQuery $callback_query)
683
    {
684
        if (!self::isDbConnected()) {
685
            return false;
686
        }
687
688
        try {
689
            $sth = self::$pdo->prepare('
690
                INSERT IGNORE INTO `' . TB_CALLBACK_QUERY . '`
691
                (`id`, `user_id`, `chat_id`, `message_id`, `inline_message_id`, `data`, `created_at`)
692
                VALUES
693
                (:callback_query_id, :user_id, :chat_id, :message_id, :inline_message_id, :data, :created_at)
694
            ');
695
696
            $date              = self::getTimestamp();
697
            $callback_query_id = $callback_query->getId();
698
            $from              = $callback_query->getFrom();
699
            $user_id           = null;
700
            if ($from instanceof User) {
701
                $user_id = $from->getId();
702
                self::insertUser($from, $date);
703
            }
704
705
            $message    = $callback_query->getMessage();
706
            $chat_id    = null;
707
            $message_id = null;
708
            if ($message instanceof Message) {
709
                $chat_id    = $message->getChat()->getId();
710
                $message_id = $message->getMessageId();
711
712
                $is_message = self::$pdo->query('
713
                    SELECT *
714
                    FROM `' . TB_MESSAGE . '`
715
                    WHERE `id` = ' . $message_id . '
716
                      AND `chat_id` = ' . $chat_id . '
717
                    LIMIT 1
718
                ')->rowCount();
719
720
                if ($is_message) {
721
                    self::insertEditedMessageRequest($message);
722
                } else {
723
                    self::insertMessageRequest($message);
724
                }
725
            }
726
727
            $inline_message_id = $callback_query->getInlineMessageId();
728
            $data              = $callback_query->getData();
729
730
            $sth->bindParam(':callback_query_id', $callback_query_id, PDO::PARAM_INT);
731
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_INT);
732
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_INT);
733
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_INT);
734
            $sth->bindParam(':inline_message_id', $inline_message_id, PDO::PARAM_STR);
735
            $sth->bindParam(':data', $data, PDO::PARAM_STR);
736
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
737
738
            return $sth->execute();
739
        } catch (PDOException $e) {
740
            throw new TelegramException($e->getMessage());
741
        }
742
    }
743
744
    /**
745
     * Insert Message request in db
746
     *
747
     * @param \Longman\TelegramBot\Entities\Message $message
748
     *
749
     * @return bool If the insert was successful
750
     * @throws \Longman\TelegramBot\Exception\TelegramException
751
     */
752 6
    public static function insertMessageRequest(Message $message)
753
    {
754 6
        if (!self::isDbConnected()) {
755
            return false;
756
        }
757
758 6
        $from = $message->getFrom();
759 6
        $chat = $message->getChat();
760
761 6
        $chat_id = $chat->getId();
762
763 6
        $date = self::getTimestamp($message->getDate());
764
765 6
        $forward_from            = $message->getForwardFrom();
766 6
        $forward_from_chat       = $message->getForwardFromChat();
767 6
        $forward_from_message_id = $message->getForwardFromMessageId();
768 6
        $photo                   = self::entitiesArrayToJson($message->getPhoto(), '');
769 6
        $entities                = self::entitiesArrayToJson($message->getEntities(), null);
770 6
        $new_chat_member         = $message->getNewChatMember();
771 6
        $new_chat_photo          = self::entitiesArrayToJson($message->getNewChatPhoto(), '');
772 6
        $left_chat_member        = $message->getLeftChatMember();
773 6
        $migrate_to_chat_id      = $message->getMigrateToChatId();
774
775
        //Insert chat, update chat id in case it migrated
776 6
        self::insertChat($chat, $date, $migrate_to_chat_id);
777
778
        //Insert user and the relation with the chat
779 6
        if (is_object($from)) {
780 6
            self::insertUser($from, $date, $chat);
781
        }
782
783
        //Insert the forwarded message user in users table
784 6
        if ($forward_from instanceof User) {
785
            $forward_date = self::getTimestamp($message->getForwardDate());
786
            self::insertUser($forward_from, $forward_date);
787
            $forward_from = $forward_from->getId();
788
        }
789
790 6
        if ($forward_from_chat instanceof Chat) {
791
            $forward_date = self::getTimestamp($message->getForwardDate());
792
            self::insertChat($forward_from_chat, $forward_date);
793
            $forward_from_chat = $forward_from_chat->getId();
794
        }
795
796
        //New and left chat member
797 6
        if ($new_chat_member instanceof User) {
798
            //Insert the new chat user
799
            self::insertUser($new_chat_member, $date, $chat);
800
            $new_chat_member = $new_chat_member->getId();
801 6
        } elseif ($left_chat_member instanceof User) {
802
            //Insert the left chat user
803
            self::insertUser($left_chat_member, $date, $chat);
804
            $left_chat_member = $left_chat_member->getId();
805
        }
806
807
        try {
808 6
            $sth = self::$pdo->prepare('
809 6
                INSERT IGNORE INTO `' . TB_MESSAGE . '`
810
                (
811
                    `id`, `user_id`, `chat_id`, `date`, `forward_from`, `forward_from_chat`, `forward_from_message_id`,
812
                    `forward_date`, `reply_to_chat`, `reply_to_message`, `text`, `entities`, `audio`, `document`,
813
                    `photo`, `sticker`, `video`, `voice`, `caption`, `contact`,
814
                    `location`, `venue`, `new_chat_member`, `left_chat_member`,
815
                    `new_chat_title`,`new_chat_photo`, `delete_chat_photo`, `group_chat_created`,
816
                    `supergroup_chat_created`, `channel_chat_created`,
817
                    `migrate_from_chat_id`, `migrate_to_chat_id`, `pinned_message`
818
                ) VALUES (
819
                    :message_id, :user_id, :chat_id, :date, :forward_from, :forward_from_chat, :forward_from_message_id,
820
                    :forward_date, :reply_to_chat, :reply_to_message, :text, :entities, :audio, :document,
821
                    :photo, :sticker, :video, :voice, :caption, :contact,
822
                    :location, :venue, :new_chat_member, :left_chat_member,
823
                    :new_chat_title, :new_chat_photo, :delete_chat_photo, :group_chat_created,
824
                    :supergroup_chat_created, :channel_chat_created,
825
                    :migrate_from_chat_id, :migrate_to_chat_id, :pinned_message
826
                )
827
            ');
828
829 6
            $message_id = $message->getMessageId();
830
831 6
            if (is_object($from)) {
832 6
                $from_id = $from->getId();
833
            } else {
834
                $from_id = null;
835
            }
836
837 6
            $reply_to_message    = $message->getReplyToMessage();
838 6
            $reply_to_message_id = null;
839 6
            if ($reply_to_message instanceof ReplyToMessage) {
840
                $reply_to_message_id = $reply_to_message->getMessageId();
841
                // please notice that, as explained in the documentation, reply_to_message don't contain other
842
                // reply_to_message field so recursion deep is 1
843
                self::insertMessageRequest($reply_to_message);
844
            }
845
846 6
            $text                    = $message->getText();
847 6
            $audio                   = $message->getAudio();
848 6
            $document                = $message->getDocument();
849 6
            $sticker                 = $message->getSticker();
850 6
            $video                   = $message->getVideo();
851 6
            $voice                   = $message->getVoice();
852 6
            $caption                 = $message->getCaption();
853 6
            $contact                 = $message->getContact();
854 6
            $location                = $message->getLocation();
855 6
            $venue                   = $message->getVenue();
856 6
            $new_chat_title          = $message->getNewChatTitle();
857 6
            $delete_chat_photo       = $message->getDeleteChatPhoto();
858 6
            $group_chat_created      = $message->getGroupChatCreated();
859 6
            $supergroup_chat_created = $message->getSupergroupChatCreated();
860 6
            $channel_chat_created    = $message->getChannelChatCreated();
861 6
            $migrate_from_chat_id    = $message->getMigrateFromChatId();
862 6
            $migrate_to_chat_id      = $message->getMigrateToChatId();
863 6
            $pinned_message          = $message->getPinnedMessage();
864
865 6
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_INT);
866 6
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_INT);
867 6
            $sth->bindParam(':user_id', $from_id, PDO::PARAM_INT);
868 6
            $sth->bindParam(':date', $date, PDO::PARAM_STR);
869 6
            $sth->bindParam(':forward_from', $forward_from, PDO::PARAM_INT);
870 6
            $sth->bindParam(':forward_from_chat', $forward_from_chat, PDO::PARAM_INT);
871 6
            $sth->bindParam(':forward_from_message_id', $forward_from_message_id, PDO::PARAM_INT);
872 6
            $sth->bindParam(':forward_date', $forward_date, PDO::PARAM_STR);
873
874 6
            $reply_to_chat_id = null;
875 6
            if ($reply_to_message_id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $reply_to_message_id of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
876
                $reply_to_chat_id = $chat_id;
877
            }
878
879 6
            $sth->bindParam(':reply_to_chat', $reply_to_chat_id, PDO::PARAM_INT);
880 6
            $sth->bindParam(':reply_to_message', $reply_to_message_id, PDO::PARAM_INT);
881 6
            $sth->bindParam(':text', $text, PDO::PARAM_STR);
882 6
            $sth->bindParam(':entities', $entities, PDO::PARAM_STR);
883 6
            $sth->bindParam(':audio', $audio, PDO::PARAM_STR);
884 6
            $sth->bindParam(':document', $document, PDO::PARAM_STR);
885 6
            $sth->bindParam(':photo', $photo, PDO::PARAM_STR);
886 6
            $sth->bindParam(':sticker', $sticker, PDO::PARAM_STR);
887 6
            $sth->bindParam(':video', $video, PDO::PARAM_STR);
888 6
            $sth->bindParam(':voice', $voice, PDO::PARAM_STR);
889 6
            $sth->bindParam(':caption', $caption, PDO::PARAM_STR);
890 6
            $sth->bindParam(':contact', $contact, PDO::PARAM_STR);
891 6
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
892 6
            $sth->bindParam(':venue', $venue, PDO::PARAM_STR);
893 6
            $sth->bindParam(':new_chat_member', $new_chat_member, PDO::PARAM_INT);
894 6
            $sth->bindParam(':left_chat_member', $left_chat_member, PDO::PARAM_INT);
895 6
            $sth->bindParam(':new_chat_title', $new_chat_title, PDO::PARAM_STR);
896 6
            $sth->bindParam(':new_chat_photo', $new_chat_photo, PDO::PARAM_STR);
897 6
            $sth->bindParam(':delete_chat_photo', $delete_chat_photo, PDO::PARAM_INT);
898 6
            $sth->bindParam(':group_chat_created', $group_chat_created, PDO::PARAM_INT);
899 6
            $sth->bindParam(':supergroup_chat_created', $supergroup_chat_created, PDO::PARAM_INT);
900 6
            $sth->bindParam(':channel_chat_created', $channel_chat_created, PDO::PARAM_INT);
901 6
            $sth->bindParam(':migrate_from_chat_id', $migrate_from_chat_id, PDO::PARAM_INT);
902 6
            $sth->bindParam(':migrate_to_chat_id', $migrate_to_chat_id, PDO::PARAM_INT);
903 6
            $sth->bindParam(':pinned_message', $pinned_message, PDO::PARAM_STR);
904
905 6
            return $sth->execute();
906
        } catch (PDOException $e) {
907
            throw new TelegramException($e->getMessage());
908
        }
909
    }
910
911
    /**
912
     * Insert Edited Message request in db
913
     *
914
     * @param \Longman\TelegramBot\Entities\Message $edited_message
915
     *
916
     * @return bool If the insert was successful
917
     * @throws \Longman\TelegramBot\Exception\TelegramException
918
     */
919
    public static function insertEditedMessageRequest(Message $edited_message)
920
    {
921
        if (!self::isDbConnected()) {
922
            return false;
923
        }
924
925
        $from = $edited_message->getFrom();
926
        $chat = $edited_message->getChat();
927
928
        $chat_id = $chat->getId();
929
930
        $edit_date = self::getTimestamp($edited_message->getEditDate());
931
932
        $entities = self::entitiesArrayToJson($edited_message->getEntities(), null);
933
934
        //Insert chat
935
        self::insertChat($chat, $edit_date);
936
937
        //Insert user and the relation with the chat
938
        if (is_object($from)) {
939
            self::insertUser($from, $edit_date, $chat);
940
        }
941
942
        try {
943
            $sth = self::$pdo->prepare('
944
                INSERT IGNORE INTO `' . TB_EDITED_MESSAGE . '`
945
                (`chat_id`, `message_id`, `user_id`, `edit_date`, `text`, `entities`, `caption`)
946
                VALUES
947
                (:chat_id, :message_id, :user_id, :date, :text, :entities, :caption)
948
            ');
949
950
            $message_id = $edited_message->getMessageId();
951
952
            if (is_object($from)) {
953
                $from_id = $from->getId();
954
            } else {
955
                $from_id = null;
956
            }
957
958
            $text    = $edited_message->getText();
959
            $caption = $edited_message->getCaption();
960
961
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_INT);
962
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_INT);
963
            $sth->bindParam(':user_id', $from_id, PDO::PARAM_INT);
964
            $sth->bindParam(':date', $edit_date, PDO::PARAM_STR);
965
            $sth->bindParam(':text', $text, PDO::PARAM_STR);
966
            $sth->bindParam(':entities', $entities, PDO::PARAM_STR);
967
            $sth->bindParam(':caption', $caption, PDO::PARAM_STR);
968
969
            return $sth->execute();
970
        } catch (PDOException $e) {
971
            throw new TelegramException($e->getMessage());
972
        }
973
    }
974
975
    /**
976
     * Select Group and/or single Chats
977
     *
978
     * @param bool   $select_groups
979
     * @param bool   $select_super_groups
980
     * @param bool   $select_users
981
     * @param string $date_from
982
     * @param string $date_to
983
     * @param int    $chat_id
984
     * @param string $text
985
     *
986
     * @return array|bool (Selected chats or false if invalid arguments)
987
     * @throws \Longman\TelegramBot\Exception\TelegramException
988
     */
989
    public static function selectChats(
990
        $select_groups = true,
991
        $select_super_groups = true,
992
        $select_users = true,
993
        $date_from = null,
994
        $date_to = null,
995
        $chat_id = null,
996
        $text = null
997
    ) {
998
        if (!self::isDbConnected()) {
999
            return false;
1000
        }
1001
1002
        if (!$select_groups && !$select_users && !$select_super_groups) {
1003
            return false;
1004
        }
1005
1006
        try {
1007
            $query = '
1008
                SELECT * ,
1009
                ' . TB_CHAT . '.`id` AS `chat_id`,
1010
                ' . TB_CHAT . '.`created_at` AS `chat_created_at`,
1011
                ' . TB_CHAT . '.`updated_at` AS `chat_updated_at`
1012
            ';
1013
            if ($select_users) {
1014
                $query .= '
1015
                    , ' . TB_USER . '.`id` AS `user_id`
1016
                    FROM `' . TB_CHAT . '`
1017
                    LEFT JOIN `' . TB_USER . '`
1018
                    ON ' . TB_CHAT . '.`id`=' . TB_USER . '.`id`
1019
                ';
1020
            } else {
1021
                $query .= 'FROM `' . TB_CHAT . '`';
1022
            }
1023
1024
            //Building parts of query
1025
            $where  = [];
1026
            $tokens = [];
1027
1028
            if (!$select_groups || !$select_users || !$select_super_groups) {
1029
                $chat_or_user = [];
1030
1031
                $select_groups && $chat_or_user[] = TB_CHAT . '.`type` = "group"';
1032
                $select_super_groups && $chat_or_user[] = TB_CHAT . '.`type` = "supergroup"';
1033
                $select_users && $chat_or_user[] = TB_CHAT . '.`type` = "private"';
1034
1035
                $where[] = '(' . implode(' OR ', $chat_or_user) . ')';
1036
            }
1037
1038
            if (null !== $date_from) {
1039
                $where[]              = TB_CHAT . '.`updated_at` >= :date_from';
1040
                $tokens[':date_from'] = $date_from;
1041
            }
1042
1043
            if (null !== $date_to) {
1044
                $where[]            = TB_CHAT . '.`updated_at` <= :date_to';
1045
                $tokens[':date_to'] = $date_to;
1046
            }
1047
1048
            if (null !== $chat_id) {
1049
                $where[]            = TB_CHAT . '.`id` = :chat_id';
1050
                $tokens[':chat_id'] = $chat_id;
1051
            }
1052
1053
            if (null !== $text) {
1054
                if ($select_users) {
1055
                    $where[] = '(
1056
                        LOWER(' . TB_CHAT . '.`title`) LIKE :text
1057
                        OR LOWER(' . TB_USER . '.`first_name`) LIKE :text
1058
                        OR LOWER(' . TB_USER . '.`last_name`) LIKE :text
1059
                        OR LOWER(' . TB_USER . '.`username`) LIKE :text
1060
                    )';
1061
                } else {
1062
                    $where[] = 'LOWER(' . TB_CHAT . '.`title`) LIKE :text';
1063
                }
1064
                $tokens[':text'] = '%' . strtolower($text) . '%';
1065
            }
1066
1067
            if (!empty($where)) {
1068
                $query .= ' WHERE ' . implode(' AND ', $where);
1069
            }
1070
1071
            $query .= ' ORDER BY ' . TB_CHAT . '.`updated_at` ASC';
1072
1073
            $sth = self::$pdo->prepare($query);
1074
            $sth->execute($tokens);
1075
1076
            return $sth->fetchAll(PDO::FETCH_ASSOC);
1077
        } catch (PDOException $e) {
1078
            throw new TelegramException($e->getMessage());
1079
        }
1080
    }
1081
1082
    /**
1083
     * Get Telegram API request count for current chat / message
1084
     *
1085
     * @param integer $chat_id
1086
     * @param string  $inline_message_id
1087
     *
1088
     * @return array|bool (Array containing TOTAL and CURRENT fields or false on invalid arguments)
1089
     * @throws \Longman\TelegramBot\Exception\TelegramException
1090
     */
1091
    public static function getTelegramRequestCount($chat_id = null, $inline_message_id = null)
1092
    {
1093
        if (!self::isDbConnected()) {
1094
            return false;
1095
        }
1096
1097
        try {
1098
            $sth = self::$pdo->prepare('SELECT 
1099
                (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE `created_at` >= :date) as LIMIT_PER_SEC_ALL,
1100
                (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE ((`chat_id` = :chat_id AND `inline_message_id` IS NULL) OR (`inline_message_id` = :inline_message_id AND `chat_id` IS NULL)) AND `created_at` >= :date) as LIMIT_PER_SEC,
1101
                (SELECT COUNT(*) FROM `' . TB_REQUEST_LIMITER . '` WHERE `chat_id` = :chat_id AND `created_at` >= :date_minute) as LIMIT_PER_MINUTE
1102
            ');
1103
1104
            $date = self::getTimestamp();
1105
            $date_minute = self::getTimestamp(strtotime('-1 minute'));
1106
1107
            $sth->bindParam(':chat_id', $chat_id, \PDO::PARAM_STR);
1108
            $sth->bindParam(':inline_message_id', $inline_message_id, \PDO::PARAM_STR);
1109
            $sth->bindParam(':date', $date, \PDO::PARAM_STR);
1110
            $sth->bindParam(':date_minute', $date_minute, \PDO::PARAM_STR);
1111
1112
            $sth->execute();
1113
1114
            return $sth->fetch();
1115
        } catch (\Exception $e) {
1116
            throw new TelegramException($e->getMessage());
1117
        }
1118
    }
1119
1120
    /**
1121
     * Insert Telegram API request in db
1122
     *
1123
     * @param string $method
1124
     * @param array  $data
1125
     *
1126
     * @return bool If the insert was successful
1127
     * @throws \Longman\TelegramBot\Exception\TelegramException
1128
     */
1129
    public static function insertTelegramRequest($method, $data)
1130
    {
1131
        if (!self::isDbConnected()) {
1132
            return false;
1133
        }
1134
1135
        $chat_id = ((isset($data['chat_id'])) ? $data['chat_id'] : null);
1136
        $inline_message_id = (isset($data['inline_message_id']) ? $data['inline_message_id'] : null);
1137
1138
        try {
1139
            $sth = self::$pdo->prepare('INSERT INTO `' . TB_REQUEST_LIMITER . '`
1140
                (
1141
                `method`, `chat_id`, `inline_message_id`, `created_at`
1142
                )
1143
                VALUES (
1144
                :method, :chat_id, :inline_message_id, :date
1145
                );
1146
            ');
1147
1148
            $created_at = self::getTimestamp();
1149
1150
            $sth->bindParam(':chat_id', $chat_id, \PDO::PARAM_STR);
1151
            $sth->bindParam(':inline_message_id', $inline_message_id, \PDO::PARAM_STR);
1152
            $sth->bindParam(':method', $method, \PDO::PARAM_STR);
1153
            $sth->bindParam(':date', $created_at, \PDO::PARAM_STR);
1154
1155
            return $sth->execute();
1156
        } catch (\Exception $e) {
1157
            throw new TelegramException($e->getMessage());
1158
        }
1159
    }
1160
}
1161