Passed
Push — master ( 627320...920c75 )
by William
04:16
created

Sentry   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 54
c 1
b 0
f 0
dl 0
loc 110
ccs 0
cts 76
cp 0
rs 10
wmc 13

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getSentryTimestamp() 0 5 1
A sendFeedback() 0 25 3
A process() 0 9 3
B sendReport() 0 48 6
1
<?php
2
3
namespace App\Forwarding;
4
5
use App\Report;
6
use Cake\Core\Configure;
7
use Cake\Log\Log;
8
use Exception;
9
10
use function curl_exec;
11
use function curl_init;
12
use function curl_setopt;
13
use function date_default_timezone_set;
14
use function http_build_query;
15
use function is_array;
16
use function is_string;
17
use function json_decode;
18
use function json_encode;
19
use function time;
20
21
use const CURLOPT_HTTPHEADER;
22
use const CURLOPT_POST;
23
use const CURLOPT_POSTFIELDS;
24
use const CURLOPT_RETURNTRANSFER;
25
use const CURLOPT_USERPWD;
26
27
class Sentry
28
{
29
    public static function getSentryTimestamp(): int
30
    {
31
        date_default_timezone_set('UTC');
32
33
        return time();
34
    }
35
36
    /**
37
     * Send report and get ID
38
     *
39
     * @param array<string,mixed> $report The report as an array
40
     * @return string The event ID
41
     *
42
     * @see https://develop.sentry.dev/sdk/store/
43
     */
44
    public static function sendReport(array $report): string
45
    {
46
        $sentryConfig = Configure::read('Forwarding.Sentry');
47
        if ($sentryConfig === null) {
48
            throw new Exception('Missing Sentry config');
49
        }
50
51
        $data = json_encode($report);
52
        $ch = curl_init($sentryConfig['base_url'] . '/api/' . $sentryConfig['project_id'] . '/store/');
53
        if ($ch === false) {
54
            throw new Exception('Could not init cURL');
55
        }
56
57
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
58
        curl_setopt($ch, CURLOPT_USERPWD, $sentryConfig['key'] . ':');
59
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
60
            'Content-type: application/json',
61
            'X-Sentry-Auth: Sentry sentry_version=7, sentry_timestamp=' . self::getSentryTimestamp()
62
            . ', sentry_key=' . $sentryConfig['key'] . ', sentry_client=phpmyadmin-proxy/0.1'
63
            . ', sentry_secret=' . $sentryConfig['secret'],
64
        ]);
65
        curl_setopt($ch, CURLOPT_POST, 1);
66
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
67
68
        $output = curl_exec($ch);
69
        if (! is_string($output)) {
70
            $error = 'Creating the report failed: ' . json_encode($output);
71
            Log::error($error);
72
73
            throw new Exception($error);
74
        }
75
76
        $response = json_decode((string) $output, true);
77
        if (! is_array($response)) {
78
            $error = 'Invalid JSON response: ' . json_encode($output);
79
            Log::error($error);
80
81
            throw new Exception($error);
82
        }
83
84
        if (! isset($response['id'])) {
85
            $error = 'Invalid response Id: ' . json_encode($response);
86
            Log::error($error);
87
88
            throw new Exception($error);
89
        }
90
91
        return (string) $response['id'];
92
    }
93
94
    /**
95
     * Set user feedback to Sentry API
96
     *
97
     * @param string $eventId  The event ID
98
     * @param string $comments The comment sent by the user
99
     * @return void nothing
100
     */
101
    public static function sendFeedback(string $eventId, string $comments): void
102
    {
103
        $sentryConfig = Configure::read('Forwarding.Sentry');
104
        if ($sentryConfig === null) {
105
            throw new Exception('Missing Sentry config');
106
        }
107
108
        $data = [
109
            'comments' => $comments,
110
            'email' => '[email protected]',
111
            'name' => 'phpMyAdmin User',
112
        ];
113
        $ch = curl_init(
114
            $sentryConfig['base_url'] . '/api/embed/error-page/?dsn=' . $sentryConfig['dsn_url'] . '&eventId=' . $eventId
115
        );
116
        if ($ch === false) {
117
            throw new Exception('Could not init cURL');
118
        }
119
120
        curl_setopt($ch, CURLOPT_USERPWD, $sentryConfig['key'] . ':');
121
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
122
        curl_setopt($ch, CURLOPT_POST, 1);
123
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
124
125
        curl_exec($ch);
126
    }
127
128
    public static function process(Report $report): void
129
    {
130
        foreach ($report->getReports() as $reportData) {
131
            $eventId = self::sendReport($reportData);
132
            if (! $report->hasUserFeedback()) {
133
                continue;
134
            }
135
136
            self::sendFeedback($eventId, $report->getUserFeedback());
137
        }
138
    }
139
}
140