Passed
Push — master ( 4c2b59...061776 )
by Shahrad
02:09
created

CrashPad::setDebugMode()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 13
c 1
b 0
f 0
dl 0
loc 18
rs 9.2222
cc 6
nc 4
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace TelegramBot;
5
6
/**
7
 * CrashPad class
8
 *
9
 * @link    https://github.com/telegram-bot-php/core
10
 * @author  Shahrad Elahi (https://github.com/shahradelahi)
11
 * @license https://github.com/telegram-bot-php/core/blob/master/LICENSE (MIT License)
12
 */
13
class CrashPad
14
{
15
16
    /**
17
     * Admin chat id
18
     *
19
     * @var int
20
     */
21
    private static int $adminChatId = -1;
22
23
    /**
24
     * Report the error to the developers from the Telegram Bot API.
25
     *
26
     * @param int $chat_id The chat id of the group to send the message to.
27
     * @param \Exception $exception The exception to report.
28
     * @param string|null $update (Optional) The update that caused the exception.
29
     * @retrun bool
30
     */
31
    public static function report(int $chat_id, \Exception $exception, string|null $update = null): bool
32
    {
33
        if ($chat_id === -1) {
34
            throw new \RuntimeException(sprintf(
35
                'The given `chat_id` is not valid. given: %s',
36
                $chat_id
37
            ));
38
        }
39
40
        TelegramLog::error(($message = sprintf(
41
            "%s(%d): %s\n%s",
42
            $exception->getFile(),
43
            $exception->getLine(),
44
            $exception->getMessage(),
45
            $exception->getTraceAsString()
46
        )));
47
48
        echo '<b>TelegramError:</b> ' . $message;
49
50
        $text = Request::sendMessage([
51
            'chat_id' => $chat_id,
52
            'text' => $message,
53
        ]);
54
55
        if ($update !== null) {
56
            $document = Request::sendDocument([
57
                'chat_id' => $chat_id,
58
                'document' => self::createCrashFile(
59
                    $message . "\n\n" . $update
60
                ),
61
            ]);
62
            return $text->isOk() && $document->isOk();
63
        }
64
65
        return $text->isOk();
66
    }
67
68
    /**
69
     * Create a log file for the error.
70
     *
71
     * @param string $content The content of the log file.
72
     * @retrun string The path of the log file.
73
     */
74
    private static function createCrashFile(string $content): string
75
    {
76
        $base_path = $_SERVER['DOCUMENT_ROOT'] . '.telegram-bot/';
77
        if (!file_exists($base_path)) {
78
            mkdir($base_path, 0777, true);
79
        }
80
81
        file_put_contents(($file = $base_path . uniqid('error_') . '.log'), $content);
82
        return $file;
83
    }
84
85
    /**
86
     * Clear crash files.
87
     *
88
     * @return void
89
     */
90
    public static function clearCrashFiles(): void
91
    {
92
        $files = glob(getcwd() . '.telegram-bot/*.log');
93
        foreach ($files as $file) {
94
            unlink($file);
95
        }
96
    }
97
98
    /**
99
     * @return int
100
     */
101
    public static function getAdminChatId(): int
102
    {
103
        return static::$adminChatId;
0 ignored issues
show
Bug introduced by
Since $adminChatId is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $adminChatId to at least protected.
Loading history...
104
    }
105
106
    /**
107
     * @param int $adminChatId
108
     */
109
    public static function setAdminChatId(int $adminChatId): void
110
    {
111
        static::$adminChatId = $adminChatId;
0 ignored issues
show
Bug introduced by
Since $adminChatId is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $adminChatId to at least protected.
Loading history...
112
    }
113
114
    /**
115
     * Debug mode. Catch the crash reports.
116
     *
117
     * @param int $admin_id (optional) The admin chat id.
118
     * @return void
119
     */
120
    public static function setDebugMode(int $admin_id = -1): void
121
    {
122
        error_reporting(E_ALL);
123
        ini_set('display_errors', '1');
124
125
        defined('DEBUG_MODE') or define('DEBUG_MODE', true);
126
        if ($admin_id !== -1) {
127
            CrashPad::setAdminChatId($admin_id);
128
        }
129
130
        set_exception_handler(function ($exception) {
131
            if (!defined('DEBUG_MODE') && !DEBUG_MODE) {
132
                throw $exception;
133
            } else {
134
                if (CrashPad::getAdminChatId() !== -1) {
135
                    $input = getenv('TG_CURRENT_UPDATE') ?? Telegram::getInput();
136
                    $update = Telegram::processUpdate($input, Telegram::getApiToken());
0 ignored issues
show
Bug introduced by
It seems like TelegramBot\Telegram::getApiToken() can also be of type false; however, parameter $apiKey of TelegramBot\Telegram::processUpdate() does only seem to accept null|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
                    $update = Telegram::processUpdate($input, /** @scrutinizer ignore-type */ Telegram::getApiToken());
Loading history...
Bug introduced by
It seems like $input can also be of type null; however, parameter $input of TelegramBot\Telegram::processUpdate() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

136
                    $update = Telegram::processUpdate(/** @scrutinizer ignore-type */ $input, Telegram::getApiToken());
Loading history...
137
                    CrashPad::report(CrashPad::getAdminChatId(), $exception, json_encode($update));
138
                }
139
            }
140
        });
141
    }
142
143
}