Completed
Push — master ( 1c54e2...48ad84 )
by Armando
02:22
created

DB::insertRequest()   D

Complexity

Conditions 15
Paths 15

Size

Total Lines 93
Code Lines 64

Duplication

Lines 48
Ratio 51.61 %

Code Coverage

Tests 0
CRAP Score 240

Importance

Changes 0
Metric Value
dl 48
loc 93
rs 4.9121
c 0
b 0
f 0
ccs 0
cts 56
cp 0
cc 15
eloc 64
nc 15
nop 1
crap 240

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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