Completed
Push — develop ( b12b2e...9d855c )
by Armando
9s
created

DB::insertChat()   B

Complexity

Conditions 4
Paths 20

Size

Total Lines 47
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 4.2211

Importance

Changes 0
Metric Value
dl 0
loc 47
ccs 19
cts 25
cp 0.76
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 26
nc 20
nop 3
crap 4.2211
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
            'telegram_update',
140
            'user',
141
            'user_chat',
142
        ];
143 9
        foreach ($tables as $table) {
144 9
            $table_name = 'TB_' . strtoupper($table);
145 9
            if (!defined($table_name)) {
146 9
                define($table_name, self::$table_prefix . $table);
147
            }
148
        }
149 9
    }
150
151
    /**
152
     * Check if database connection has been created
153
     *
154
     * @return bool
155
     */
156 9
    public static function isDbConnected()
157
    {
158 9
        return self::$pdo !== null;
159
    }
160
161
    /**
162
     * Fetch update(s) from DB
163
     *
164
     * @param int $limit Limit the number of updates to fetch
165
     *
166
     * @return array|bool Fetched data or false if not connected
167
     * @throws \Longman\TelegramBot\Exception\TelegramException
168
     */
169 View Code Duplication
    public static function selectTelegramUpdate($limit = null)
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...
170
    {
171
        if (!self::isDbConnected()) {
172
            return false;
173
        }
174
175
        try {
176
            $sql = '
177
                SELECT `id`
178
                FROM `' . TB_TELEGRAM_UPDATE . '`
179
                ORDER BY `id` DESC
180
            ';
181
182
            if ($limit !== null) {
183
                $sql .= 'LIMIT :limit';
184
            }
185
186
            $sth = self::$pdo->prepare($sql);
187
            $sth->bindParam(':limit', $limit, PDO::PARAM_INT);
188
            $sth->execute();
189
190
            return $sth->fetchAll(PDO::FETCH_ASSOC);
191
        } catch (PDOException $e) {
192
            throw new TelegramException($e->getMessage());
193
        }
194
    }
195
196
    /**
197
     * Fetch message(s) from DB
198
     *
199
     * @param int $limit Limit the number of messages to fetch
200
     *
201
     * @return array|bool Fetched data or false if not connected
202
     * @throws \Longman\TelegramBot\Exception\TelegramException
203
     */
204 View Code Duplication
    public static function selectMessages($limit = null)
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...
205
    {
206
        if (!self::isDbConnected()) {
207
            return false;
208
        }
209
210
        try {
211
            $sql = '
212
                SELECT *
213
                FROM `' . TB_MESSAGE . '`
214
                WHERE `update_id` != 0
215
                ORDER BY `message_id` DESC
216
            ';
217
218
            if ($limit !== null) {
219
                $sql .= 'LIMIT :limit';
220
            }
221
222
            $sth = self::$pdo->prepare($sql);
223
            $sth->bindParam(':limit', $limit, PDO::PARAM_INT);
224
            $sth->execute();
225
226
            return $sth->fetchAll(PDO::FETCH_ASSOC);
227
        } catch (PDOException $e) {
228
            throw new TelegramException($e->getMessage());
229
        }
230
    }
231
232
    /**
233
     * Convert from unix timestamp to timestamp
234
     *
235
     * @param int $time Unix timestamp (if null, current timestamp is used)
236
     *
237
     * @return string
238
     */
239 7
    protected static function getTimestamp($time = null)
240
    {
241 7
        if ($time === null) {
242 6
            $time = time();
243
        }
244
245 7
        return date('Y-m-d H:i:s', $time);
246
    }
247
248
    /**
249
     * Convert array of Entity items to a JSON array
250
     *
251
     * @todo Find a better way, as json_* functions are very heavy
252
     *
253
     * @param array|null $entities
254
     * @param mixed      $default
255
     *
256
     * @return mixed
257
     */
258 6
    public static function entitiesArrayToJson($entities, $default = null)
259
    {
260 6
        if (!is_array($entities)) {
261 6
            return $default;
262
        }
263
264
        //Convert each Entity item into an object based on its JSON reflection
265
        $json_entities = array_map(function ($entity) {
266
            return json_decode($entity, true);
267
        }, $entities);
268
269
        return json_encode($json_entities);
270
    }
271
272
    /**
273
     * Insert entry to telegram_update table
274
     *
275
     * @param int $id
276
     * @param int $chat_id
277
     * @param int $message_id
278
     * @param int $inline_query_id
279
     * @param int $chosen_inline_result_id
280
     * @param int $callback_query_id
281
     * @param int $edited_message_id
282
     *
283
     * @return bool If the insert was successful
284
     * @throws \Longman\TelegramBot\Exception\TelegramException
285
     */
286
    public static function insertTelegramUpdate(
287
        $id,
288
        $chat_id,
289
        $message_id,
290
        $inline_query_id,
291
        $chosen_inline_result_id,
292
        $callback_query_id,
293
        $edited_message_id
294
    ) {
295
        if ($message_id === null && $inline_query_id === null && $chosen_inline_result_id === null && $callback_query_id === null && $edited_message_id === null) {
296
            throw new TelegramException('message_id, inline_query_id, chosen_inline_result_id, callback_query_id, edited_message_id are all null');
297
        }
298
299
        if (!self::isDbConnected()) {
300
            return false;
301
        }
302
303
        try {
304
            $sth = self::$pdo->prepare('
305
                INSERT IGNORE INTO `' . TB_TELEGRAM_UPDATE . '`
306
                (`id`, `chat_id`, `message_id`, `inline_query_id`, `chosen_inline_result_id`, `callback_query_id`, `edited_message_id`)
307
                VALUES
308
                (:id, :chat_id, :message_id, :inline_query_id, :chosen_inline_result_id, :callback_query_id, :edited_message_id)
309
            ');
310
311
            $sth->bindParam(':id', $id, PDO::PARAM_INT);
312
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_INT);
313
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_INT);
314
            $sth->bindParam(':inline_query_id', $inline_query_id, PDO::PARAM_INT);
315
            $sth->bindParam(':chosen_inline_result_id', $chosen_inline_result_id, PDO::PARAM_INT);
316
            $sth->bindParam(':callback_query_id', $callback_query_id, PDO::PARAM_INT);
317
            $sth->bindParam(':edited_message_id', $edited_message_id, PDO::PARAM_INT);
318
319
            return $sth->execute();
320
        } catch (PDOException $e) {
321
            throw new TelegramException($e->getMessage());
322
        }
323
    }
324
325
    /**
326
     * Insert users and save their connection to chats
327
     *
328
     * @param  \Longman\TelegramBot\Entities\User $user
329
     * @param  string                             $date
330
     * @param  \Longman\TelegramBot\Entities\Chat $chat
331
     *
332
     * @return bool If the insert was successful
333
     * @throws \Longman\TelegramBot\Exception\TelegramException
334
     */
335 6
    public static function insertUser(User $user, $date, Chat $chat = null)
336
    {
337 6
        if (!self::isDbConnected()) {
338
            return false;
339
        }
340
341 6
        $user_id    = $user->getId();
342 6
        $username   = $user->getUsername();
343 6
        $first_name = $user->getFirstName();
344 6
        $last_name  = $user->getLastName();
345
346
        try {
347 6
            $sth = self::$pdo->prepare('
348 6
                INSERT INTO `' . TB_USER . '`
349
                (`id`, `username`, `first_name`, `last_name`, `created_at`, `updated_at`)
350
                VALUES
351
                (:id, :username, :first_name, :last_name, :date, :date)
352
                ON DUPLICATE KEY UPDATE
353
                    `username`   = :username,
354
                    `first_name` = :first_name,
355
                    `last_name`  = :last_name,
356
                    `updated_at` = :date
357 6
            ');
358
359 6
            $sth->bindParam(':id', $user_id, PDO::PARAM_INT);
360 6
            $sth->bindParam(':username', $username, PDO::PARAM_STR, 255);
361 6
            $sth->bindParam(':first_name', $first_name, PDO::PARAM_STR, 255);
362 6
            $sth->bindParam(':last_name', $last_name, PDO::PARAM_STR, 255);
363 6
            $sth->bindParam(':date', $date, PDO::PARAM_STR);
364
365 6
            $status = $sth->execute();
366
        } catch (PDOException $e) {
367
            throw new TelegramException($e->getMessage());
368
        }
369
370
        //insert also the relationship to the chat into user_chat table
371 6
        if ($chat instanceof Chat) {
372 6
            $chat_id = $chat->getId();
373
            try {
374 6
                $sth = self::$pdo->prepare('
375 6
                    INSERT IGNORE INTO `' . TB_USER_CHAT . '`
376
                    (`user_id`, `chat_id`)
377
                    VALUES
378
                    (:user_id, :chat_id)
379 6
                ');
380
381 6
                $sth->bindParam(':user_id', $user_id, PDO::PARAM_INT);
382 6
                $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_INT);
383
384 6
                $status = $sth->execute();
385
            } catch (PDOException $e) {
386
                throw new TelegramException($e->getMessage());
387
            }
388
        }
389
390 6
        return $status;
391
    }
392
393
    /**
394
     * Insert chat
395
     *
396
     * @param  \Longman\TelegramBot\Entities\Chat $chat
397
     * @param  string                             $date
398
     * @param  int                                $migrate_to_chat_id
399
     *
400
     * @return bool If the insert was successful
401
     * @throws \Longman\TelegramBot\Exception\TelegramException
402
     */
403 6
    public static function insertChat(Chat $chat, $date, $migrate_to_chat_id = null)
404
    {
405 6
        if (!self::isDbConnected()) {
406
            return false;
407
        }
408
409 6
        $chat_id                             = $chat->getId();
410 6
        $chat_title                          = $chat->getTitle();
411 6
        $chat_username                       = $chat->getUsername();
412 6
        $chat_type                           = $chat->getType();
413 6
        $chat_all_members_are_administrators = $chat->getAllMembersAreAdministrators();
414
415
        try {
416 6
            $sth = self::$pdo->prepare('
417 6
                INSERT IGNORE INTO `' . TB_CHAT . '`
418
                (`id`, `type`, `title`, `username`, `all_members_are_administrators`, `created_at` ,`updated_at`, `old_id`)
419
                VALUES
420
                (:id, :type, :title, :username, :all_members_are_administrators, :date, :date, :oldid)
421
                ON DUPLICATE KEY UPDATE
422
                    `type`                           = :type,
423
                    `title`                          = :title,
424
                    `username`                       = :username,
425
                    `all_members_are_administrators` = :all_members_are_administrators,
426
                    `updated_at`                     = :date
427 6
            ');
428
429 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...
430
                $chat_type = 'supergroup';
431
432
                $sth->bindParam(':id', $migrate_to_chat_id, PDO::PARAM_INT);
433
                $sth->bindParam(':oldid', $chat_id, PDO::PARAM_INT);
434
            } else {
435 6
                $sth->bindParam(':id', $chat_id, PDO::PARAM_INT);
436 6
                $sth->bindParam(':oldid', $migrate_to_chat_id, PDO::PARAM_INT);
437
            }
438
439 6
            $sth->bindParam(':type', $chat_type, PDO::PARAM_INT);
440 6
            $sth->bindParam(':title', $chat_title, PDO::PARAM_STR, 255);
441 6
            $sth->bindParam(':username', $chat_username, PDO::PARAM_STR, 255);
442 6
            $sth->bindParam(':all_members_are_administrators', $chat_all_members_are_administrators, PDO::PARAM_INT);
443 6
            $sth->bindParam(':date', $date, PDO::PARAM_STR);
444
445 6
            return $sth->execute();
446
        } catch (PDOException $e) {
447
            throw new TelegramException($e->getMessage());
448
        }
449
    }
450
451
    /**
452
     * Insert request into database
453
     *
454
     * @todo self::$pdo->lastInsertId() - unsafe usage if expected previous insert fails?
455
     *
456
     * @param \Longman\TelegramBot\Entities\Update $update
457
     *
458
     * @return bool
459
     * @throws \Longman\TelegramBot\Exception\TelegramException
460
     */
461
    public static function insertRequest(Update $update)
462
    {
463
        $update_id   = $update->getUpdateId();
464
        $update_type = $update->getUpdateType();
465
466
        if ($update_type === 'message') {
467
            $message = $update->getMessage();
468
469 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...
470
                $message_id = $message->getMessageId();
471
                $chat_id    = $message->getChat()->getId();
472
473
                return self::insertTelegramUpdate($update_id, $chat_id, $message_id, null, null, null, null);
474
            }
475 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...
476
            $edited_message = $update->getEditedMessage();
477
478
            if (self::insertEditedMessageRequest($edited_message)) {
479
                $chat_id                 = $edited_message->getChat()->getId();
480
                $edited_message_local_id = self::$pdo->lastInsertId();
481
482
                return self::insertTelegramUpdate(
483
                    $update_id,
484
                    $chat_id,
485
                    null,
486
                    null,
487
                    null,
488
                    null,
489
                    $edited_message_local_id
490
                );
491
            }
492
        } elseif ($update_type === 'channel_post') {
493
            $channel_post = $update->getChannelPost();
494
495 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...
496
                $message_id = $channel_post->getMessageId();
497
                $chat_id    = $channel_post->getChat()->getId();
498
499
                return self::insertTelegramUpdate($update_id, $chat_id, $message_id, null, null, null, null);
500
            }
501 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...
502
            $edited_channel_post = $update->getEditedChannelPost();
503
504
            if (self::insertEditedMessageRequest($edited_channel_post)) {
505
                $chat_id                      = $edited_channel_post->getChat()->getId();
506
                $edited_channel_post_local_id = self::$pdo->lastInsertId();
507
508
                return self::insertTelegramUpdate(
509
                    $update_id,
510
                    $chat_id,
511
                    null,
512
                    null,
513
                    null,
514
                    null,
515
                    $edited_channel_post_local_id
516
                );
517
            }
518
        } elseif ($update_type === 'inline_query') {
519
            $inline_query = $update->getInlineQuery();
520
521
            if (self::insertInlineQueryRequest($inline_query)) {
522
                $inline_query_id = $inline_query->getId();
523
524
                return self::insertTelegramUpdate($update_id, null, null, $inline_query_id, null, null, null);
525
            }
526
        } elseif ($update_type === 'chosen_inline_result') {
527
            $chosen_inline_result = $update->getChosenInlineResult();
528
529
            if (self::insertChosenInlineResultRequest($chosen_inline_result)) {
530
                $chosen_inline_result_local_id = self::$pdo->lastInsertId();
531
532
                return self::insertTelegramUpdate(
533
                    $update_id,
534
                    null,
535
                    null,
536
                    null,
537
                    $chosen_inline_result_local_id,
538
                    null,
539
                    null
540
                );
541
            }
542
        } elseif ($update_type === 'callback_query') {
543
            $callback_query = $update->getCallbackQuery();
544
545
            if (self::insertCallbackQueryRequest($callback_query)) {
546
                $callback_query_id = $callback_query->getId();
547
548
                return self::insertTelegramUpdate($update_id, null, null, null, null, $callback_query_id, null);
549
            }
550
        }
551
552
        return false;
553
    }
554
555
    /**
556
     * Insert inline query request into database
557
     *
558
     * @param \Longman\TelegramBot\Entities\InlineQuery $inline_query
559
     *
560
     * @return bool If the insert was successful
561
     * @throws \Longman\TelegramBot\Exception\TelegramException
562
     */
563 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...
564
    {
565
        if (!self::isDbConnected()) {
566
            return false;
567
        }
568
569
        try {
570
            $sth = self::$pdo->prepare('
571
                INSERT IGNORE INTO `' . TB_INLINE_QUERY . '`
572
                (`id`, `user_id`, `location`, `query`, `offset`, `created_at`)
573
                VALUES
574
                (:inline_query_id, :user_id, :location, :query, :param_offset, :created_at)
575
            ');
576
577
            $date            = self::getTimestamp();
578
            $inline_query_id = $inline_query->getId();
579
            $from            = $inline_query->getFrom();
580
            $user_id         = null;
581
            if ($from instanceof User) {
582
                $user_id = $from->getId();
583
                self::insertUser($from, $date);
584
            }
585
586
            $location = $inline_query->getLocation();
587
            $query    = $inline_query->getQuery();
588
            $offset   = $inline_query->getOffset();
589
590
            $sth->bindParam(':inline_query_id', $inline_query_id, PDO::PARAM_INT);
591
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_INT);
592
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
593
            $sth->bindParam(':query', $query, PDO::PARAM_STR);
594
            $sth->bindParam(':param_offset', $offset, PDO::PARAM_STR);
595
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
596
597
            return $sth->execute();
598
        } catch (PDOException $e) {
599
            throw new TelegramException($e->getMessage());
600
        }
601
    }
602
603
    /**
604
     * Insert chosen inline result request into database
605
     *
606
     * @param \Longman\TelegramBot\Entities\ChosenInlineResult $chosen_inline_result
607
     *
608
     * @return bool If the insert was successful
609
     * @throws \Longman\TelegramBot\Exception\TelegramException
610
     */
611 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...
612
    {
613
        if (!self::isDbConnected()) {
614
            return false;
615
        }
616
617
        try {
618
            $sth = self::$pdo->prepare('
619
                INSERT INTO `' . TB_CHOSEN_INLINE_RESULT . '`
620
                (`result_id`, `user_id`, `location`, `inline_message_id`, `query`, `created_at`)
621
                VALUES
622
                (:result_id, :user_id, :location, :inline_message_id, :query, :created_at)
623
            ');
624
625
            $date      = self::getTimestamp();
626
            $result_id = $chosen_inline_result->getResultId();
627
            $from      = $chosen_inline_result->getFrom();
628
            $user_id   = null;
629
            if ($from instanceof User) {
630
                $user_id = $from->getId();
631
                self::insertUser($from, $date);
632
            }
633
634
            $location          = $chosen_inline_result->getLocation();
635
            $inline_message_id = $chosen_inline_result->getInlineMessageId();
636
            $query             = $chosen_inline_result->getQuery();
637
638
            $sth->bindParam(':result_id', $result_id, PDO::PARAM_STR);
639
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_INT);
640
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
641
            $sth->bindParam(':inline_message_id', $inline_message_id, PDO::PARAM_STR);
642
            $sth->bindParam(':query', $query, PDO::PARAM_STR);
643
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
644
645
            return $sth->execute();
646
        } catch (PDOException $e) {
647
            throw new TelegramException($e->getMessage());
648
        }
649
    }
650
651
    /**
652
     * Insert callback query request into database
653
     *
654
     * @param \Longman\TelegramBot\Entities\CallbackQuery $callback_query
655
     *
656
     * @return bool If the insert was successful
657
     * @throws \Longman\TelegramBot\Exception\TelegramException
658
     */
659
    public static function insertCallbackQueryRequest(CallbackQuery $callback_query)
660
    {
661
        if (!self::isDbConnected()) {
662
            return false;
663
        }
664
665
        try {
666
            $sth = self::$pdo->prepare('
667
                INSERT IGNORE INTO `' . TB_CALLBACK_QUERY . '`
668
                (`id`, `user_id`, `chat_id`, `message_id`, `inline_message_id`, `data`, `created_at`)
669
                VALUES
670
                (:callback_query_id, :user_id, :chat_id, :message_id, :inline_message_id, :data, :created_at)
671
            ');
672
673
            $date              = self::getTimestamp();
674
            $callback_query_id = $callback_query->getId();
675
            $from              = $callback_query->getFrom();
676
            $user_id           = null;
677
            if ($from instanceof User) {
678
                $user_id = $from->getId();
679
                self::insertUser($from, $date);
680
            }
681
682
            $message    = $callback_query->getMessage();
683
            $chat_id    = null;
684
            $message_id = null;
685
            if ($message instanceof Message) {
686
                $chat_id    = $message->getChat()->getId();
687
                $message_id = $message->getMessageId();
688
689
                $is_message = self::$pdo->query('
690
                    SELECT *
691
                    FROM `' . TB_MESSAGE . '`
692
                    WHERE `id` = ' . $message_id . '
693
                      AND `chat_id` = ' . $chat_id . '
694
                    LIMIT 1
695
                ')->rowCount();
696
697
                if ($is_message) {
698
                    self::insertEditedMessageRequest($message);
699
                } else {
700
                    self::insertMessageRequest($message);
701
                }
702
            }
703
704
            $inline_message_id = $callback_query->getInlineMessageId();
705
            $data              = $callback_query->getData();
706
707
            $sth->bindParam(':callback_query_id', $callback_query_id, PDO::PARAM_INT);
708
            $sth->bindParam(':user_id', $user_id, PDO::PARAM_INT);
709
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_INT);
710
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_INT);
711
            $sth->bindParam(':inline_message_id', $inline_message_id, PDO::PARAM_STR);
712
            $sth->bindParam(':data', $data, PDO::PARAM_STR);
713
            $sth->bindParam(':created_at', $date, PDO::PARAM_STR);
714
715
            return $sth->execute();
716
        } catch (PDOException $e) {
717
            throw new TelegramException($e->getMessage());
718
        }
719
    }
720
721
    /**
722
     * Insert Message request in db
723
     *
724
     * @param \Longman\TelegramBot\Entities\Message $message
725
     *
726
     * @return bool If the insert was successful
727
     * @throws \Longman\TelegramBot\Exception\TelegramException
728
     */
729 6
    public static function insertMessageRequest(Message $message)
730
    {
731 6
        if (!self::isDbConnected()) {
732
            return false;
733
        }
734
735 6
        $from = $message->getFrom();
736 6
        $chat = $message->getChat();
737
738 6
        $chat_id = $chat->getId();
739
740 6
        $date = self::getTimestamp($message->getDate());
741
742 6
        $forward_from            = $message->getForwardFrom();
743 6
        $forward_from_chat       = $message->getForwardFromChat();
744 6
        $forward_from_message_id = $message->getForwardFromMessageId();
745 6
        $photo                   = self::entitiesArrayToJson($message->getPhoto(), '');
746 6
        $entities                = self::entitiesArrayToJson($message->getEntities(), null);
747 6
        $new_chat_member         = $message->getNewChatMember();
748 6
        $new_chat_photo          = self::entitiesArrayToJson($message->getNewChatPhoto(), '');
749 6
        $left_chat_member        = $message->getLeftChatMember();
750 6
        $migrate_to_chat_id      = $message->getMigrateToChatId();
751
752
        //Insert chat, update chat id in case it migrated
753 6
        self::insertChat($chat, $date, $migrate_to_chat_id);
754
755
        //Insert user and the relation with the chat
756 6
        if (is_object($from)) {
757 6
            self::insertUser($from, $date, $chat);
758
        }
759
760
        //Insert the forwarded message user in users table
761 6
        if ($forward_from instanceof User) {
762
            $forward_date = self::getTimestamp($message->getForwardDate());
763
            self::insertUser($forward_from, $forward_date);
764
            $forward_from = $forward_from->getId();
765
        }
766
767 6
        if ($forward_from_chat instanceof Chat) {
768
            $forward_date = self::getTimestamp($message->getForwardDate());
769
            self::insertChat($forward_from_chat, $forward_date);
770
            $forward_from_chat = $forward_from_chat->getId();
771
        }
772
773
        //New and left chat member
774 6
        if ($new_chat_member instanceof User) {
775
            //Insert the new chat user
776
            self::insertUser($new_chat_member, $date, $chat);
777
            $new_chat_member = $new_chat_member->getId();
778
        } elseif ($left_chat_member instanceof User) {
779
            //Insert the left chat user
780
            self::insertUser($left_chat_member, $date, $chat);
781
            $left_chat_member = $left_chat_member->getId();
782
        }
783
784
        try {
785 6
            $sth = self::$pdo->prepare('
786 6
                INSERT IGNORE INTO `' . TB_MESSAGE . '`
787
                (
788
                    `id`, `user_id`, `chat_id`, `date`, `forward_from`, `forward_from_chat`, `forward_from_message_id`,
789
                    `forward_date`, `reply_to_chat`, `reply_to_message`, `text`, `entities`, `audio`, `document`,
790
                    `photo`, `sticker`, `video`, `voice`, `caption`, `contact`,
791
                    `location`, `venue`, `new_chat_member`, `left_chat_member`,
792
                    `new_chat_title`,`new_chat_photo`, `delete_chat_photo`, `group_chat_created`,
793
                    `supergroup_chat_created`, `channel_chat_created`,
794
                    `migrate_from_chat_id`, `migrate_to_chat_id`, `pinned_message`
795
                ) VALUES (
796
                    :message_id, :user_id, :chat_id, :date, :forward_from, :forward_from_chat, :forward_from_message_id,
797
                    :forward_date, :reply_to_chat, :reply_to_message, :text, :entities, :audio, :document,
798
                    :photo, :sticker, :video, :voice, :caption, :contact,
799
                    :location, :venue, :new_chat_member, :left_chat_member,
800
                    :new_chat_title, :new_chat_photo, :delete_chat_photo, :group_chat_created,
801
                    :supergroup_chat_created, :channel_chat_created,
802
                    :migrate_from_chat_id, :migrate_to_chat_id, :pinned_message
803
                )
804 6
            ');
805
806 6
            $message_id = $message->getMessageId();
807
808 6
            if (is_object($from)) {
809 6
                $from_id = $from->getId();
810
            } else {
811
                $from_id = null;
812
            }
813
814 6
            $reply_to_message    = $message->getReplyToMessage();
815 6
            $reply_to_message_id = null;
816 6
            if ($reply_to_message instanceof ReplyToMessage) {
817
                $reply_to_message_id = $reply_to_message->getMessageId();
818
                // please notice that, as explained in the documentation, reply_to_message don't contain other
819
                // reply_to_message field so recursion deep is 1
820
                self::insertMessageRequest($reply_to_message);
821
            }
822
823 6
            $text                    = $message->getText();
824 6
            $audio                   = $message->getAudio();
825 6
            $document                = $message->getDocument();
826 6
            $sticker                 = $message->getSticker();
827 6
            $video                   = $message->getVideo();
828 6
            $voice                   = $message->getVoice();
829 6
            $caption                 = $message->getCaption();
830 6
            $contact                 = $message->getContact();
831 6
            $location                = $message->getLocation();
832 6
            $venue                   = $message->getVenue();
833 6
            $new_chat_title          = $message->getNewChatTitle();
834 6
            $delete_chat_photo       = $message->getDeleteChatPhoto();
835 6
            $group_chat_created      = $message->getGroupChatCreated();
836 6
            $supergroup_chat_created = $message->getSupergroupChatCreated();
837 6
            $channel_chat_created    = $message->getChannelChatCreated();
838 6
            $migrate_from_chat_id    = $message->getMigrateFromChatId();
839 6
            $migrate_to_chat_id      = $message->getMigrateToChatId();
840 6
            $pinned_message          = $message->getPinnedMessage();
841
842 6
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_INT);
843 6
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_INT);
844 6
            $sth->bindParam(':user_id', $from_id, PDO::PARAM_INT);
845 6
            $sth->bindParam(':date', $date, PDO::PARAM_STR);
846 6
            $sth->bindParam(':forward_from', $forward_from, PDO::PARAM_INT);
847 6
            $sth->bindParam(':forward_from_chat', $forward_from_chat, PDO::PARAM_INT);
848 6
            $sth->bindParam(':forward_from_message_id', $forward_from_message_id, PDO::PARAM_INT);
849 6
            $sth->bindParam(':forward_date', $forward_date, PDO::PARAM_STR);
850
851 6
            $reply_to_chat_id = null;
852 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...
853
                $reply_to_chat_id = $chat_id;
854
            }
855
856 6
            $sth->bindParam(':reply_to_chat', $reply_to_chat_id, PDO::PARAM_INT);
857 6
            $sth->bindParam(':reply_to_message', $reply_to_message_id, PDO::PARAM_INT);
858 6
            $sth->bindParam(':text', $text, PDO::PARAM_STR);
859 6
            $sth->bindParam(':entities', $entities, PDO::PARAM_STR);
860 6
            $sth->bindParam(':audio', $audio, PDO::PARAM_STR);
861 6
            $sth->bindParam(':document', $document, PDO::PARAM_STR);
862 6
            $sth->bindParam(':photo', $photo, PDO::PARAM_STR);
863 6
            $sth->bindParam(':sticker', $sticker, PDO::PARAM_STR);
864 6
            $sth->bindParam(':video', $video, PDO::PARAM_STR);
865 6
            $sth->bindParam(':voice', $voice, PDO::PARAM_STR);
866 6
            $sth->bindParam(':caption', $caption, PDO::PARAM_STR);
867 6
            $sth->bindParam(':contact', $contact, PDO::PARAM_STR);
868 6
            $sth->bindParam(':location', $location, PDO::PARAM_STR);
869 6
            $sth->bindParam(':venue', $venue, PDO::PARAM_STR);
870 6
            $sth->bindParam(':new_chat_member', $new_chat_member, PDO::PARAM_INT);
871 6
            $sth->bindParam(':left_chat_member', $left_chat_member, PDO::PARAM_INT);
872 6
            $sth->bindParam(':new_chat_title', $new_chat_title, PDO::PARAM_STR);
873 6
            $sth->bindParam(':new_chat_photo', $new_chat_photo, PDO::PARAM_STR);
874 6
            $sth->bindParam(':delete_chat_photo', $delete_chat_photo, PDO::PARAM_INT);
875 6
            $sth->bindParam(':group_chat_created', $group_chat_created, PDO::PARAM_INT);
876 6
            $sth->bindParam(':supergroup_chat_created', $supergroup_chat_created, PDO::PARAM_INT);
877 6
            $sth->bindParam(':channel_chat_created', $channel_chat_created, PDO::PARAM_INT);
878 6
            $sth->bindParam(':migrate_from_chat_id', $migrate_from_chat_id, PDO::PARAM_INT);
879 6
            $sth->bindParam(':migrate_to_chat_id', $migrate_to_chat_id, PDO::PARAM_INT);
880 6
            $sth->bindParam(':pinned_message', $pinned_message, PDO::PARAM_STR);
881
882 6
            return $sth->execute();
883
        } catch (PDOException $e) {
884
            throw new TelegramException($e->getMessage());
885
        }
886
    }
887
888
    /**
889
     * Insert Edited Message request in db
890
     *
891
     * @param \Longman\TelegramBot\Entities\Message $edited_message
892
     *
893
     * @return bool If the insert was successful
894
     * @throws \Longman\TelegramBot\Exception\TelegramException
895
     */
896
    public static function insertEditedMessageRequest(Message $edited_message)
897
    {
898
        if (!self::isDbConnected()) {
899
            return false;
900
        }
901
902
        $from = $edited_message->getFrom();
903
        $chat = $edited_message->getChat();
904
905
        $chat_id = $chat->getId();
906
907
        $edit_date = self::getTimestamp($edited_message->getEditDate());
908
909
        $entities = self::entitiesArrayToJson($edited_message->getEntities(), null);
910
911
        //Insert chat
912
        self::insertChat($chat, $edit_date);
913
914
        //Insert user and the relation with the chat
915
        if (is_object($from)) {
916
            self::insertUser($from, $edit_date, $chat);
917
        }
918
919
        try {
920
            $sth = self::$pdo->prepare('
921
                INSERT IGNORE INTO `' . TB_EDITED_MESSAGE . '`
922
                (`chat_id`, `message_id`, `user_id`, `edit_date`, `text`, `entities`, `caption`)
923
                VALUES
924
                (:chat_id, :message_id, :user_id, :date, :text, :entities, :caption)
925
            ');
926
927
            $message_id = $edited_message->getMessageId();
928
929
            if (is_object($from)) {
930
                $from_id = $from->getId();
931
            } else {
932
                $from_id = null;
933
            }
934
935
            $text    = $edited_message->getText();
936
            $caption = $edited_message->getCaption();
937
938
            $sth->bindParam(':chat_id', $chat_id, PDO::PARAM_INT);
939
            $sth->bindParam(':message_id', $message_id, PDO::PARAM_INT);
940
            $sth->bindParam(':user_id', $from_id, PDO::PARAM_INT);
941
            $sth->bindParam(':date', $edit_date, PDO::PARAM_STR);
942
            $sth->bindParam(':text', $text, PDO::PARAM_STR);
943
            $sth->bindParam(':entities', $entities, PDO::PARAM_STR);
944
            $sth->bindParam(':caption', $caption, PDO::PARAM_STR);
945
946
            return $sth->execute();
947
        } catch (PDOException $e) {
948
            throw new TelegramException($e->getMessage());
949
        }
950
    }
951
952
    /**
953
     * Select Group and/or single Chats
954
     *
955
     * @param bool   $select_groups
956
     * @param bool   $select_super_groups
957
     * @param bool   $select_users
958
     * @param string $date_from
959
     * @param string $date_to
960
     * @param int    $chat_id
961
     * @param string $text
962
     *
963
     * @return array|bool (Selected chats or false if invalid arguments)
964
     * @throws \Longman\TelegramBot\Exception\TelegramException
965
     */
966
    public static function selectChats(
967
        $select_groups = true,
968
        $select_super_groups = true,
969
        $select_users = true,
970
        $date_from = null,
971
        $date_to = null,
972
        $chat_id = null,
973
        $text = null
974
    ) {
975
        if (!self::isDbConnected()) {
976
            return false;
977
        }
978
979
        if (!$select_groups && !$select_users && !$select_super_groups) {
980
            return false;
981
        }
982
983
        try {
984
            $query = '
985
                SELECT * ,
986
                ' . TB_CHAT . '.`id` AS `chat_id`,
987
                ' . TB_CHAT . '.`created_at` AS `chat_created_at`,
988
                ' . TB_CHAT . '.`updated_at` AS `chat_updated_at`
989
            ';
990
            if ($select_users) {
991
                $query .= '
992
                    , ' . TB_USER . '.`id` AS `user_id`
993
                    FROM `' . TB_CHAT . '`
994
                    LEFT JOIN `' . TB_USER . '`
995
                    ON ' . TB_CHAT . '.`id`=' . TB_USER . '.`id`
996
                ';
997
            } else {
998
                $query .= 'FROM `' . TB_CHAT . '`';
999
            }
1000
1001
            //Building parts of query
1002
            $where  = [];
1003
            $tokens = [];
1004
1005
            if (!$select_groups || !$select_users || !$select_super_groups) {
1006
                $chat_or_user = [];
1007
1008
                $select_groups && $chat_or_user[] = TB_CHAT . '.`type` = "group"';
1009
                $select_super_groups && $chat_or_user[] = TB_CHAT . '.`type` = "supergroup"';
1010
                $select_users && $chat_or_user[] = TB_CHAT . '.`type` = "private"';
1011
1012
                $where[] = '(' . implode(' OR ', $chat_or_user) . ')';
1013
            }
1014
1015
            if (null !== $date_from) {
1016
                $where[]              = TB_CHAT . '.`updated_at` >= :date_from';
1017
                $tokens[':date_from'] = $date_from;
1018
            }
1019
1020
            if (null !== $date_to) {
1021
                $where[]            = TB_CHAT . '.`updated_at` <= :date_to';
1022
                $tokens[':date_to'] = $date_to;
1023
            }
1024
1025
            if (null !== $chat_id) {
1026
                $where[]            = TB_CHAT . '.`id` = :chat_id';
1027
                $tokens[':chat_id'] = $chat_id;
1028
            }
1029
1030
            if (null !== $text) {
1031
                if ($select_users) {
1032
                    $where[] = '(
1033
                        LOWER(' . TB_CHAT . '.`title`) LIKE :text
1034
                        OR LOWER(' . TB_USER . '.`first_name`) LIKE :text
1035
                        OR LOWER(' . TB_USER . '.`last_name`) LIKE :text
1036
                        OR LOWER(' . TB_USER . '.`username`) LIKE :text
1037
                    )';
1038
                } else {
1039
                    $where[] = 'LOWER(' . TB_CHAT . '.`title`) LIKE :text';
1040
                }
1041
                $tokens[':text'] = '%' . strtolower($text) . '%';
1042
            }
1043
1044
            if (!empty($where)) {
1045
                $query .= ' WHERE ' . implode(' AND ', $where);
1046
            }
1047
1048
            $query .= ' ORDER BY ' . TB_CHAT . '.`updated_at` ASC';
1049
1050
            $sth = self::$pdo->prepare($query);
1051
            $sth->execute($tokens);
1052
1053
            return $sth->fetchAll(PDO::FETCH_ASSOC);
1054
        } catch (PDOException $e) {
1055
            throw new TelegramException($e->getMessage());
1056
        }
1057
    }
1058
}
1059