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

IncidentsController::sendNotificationMail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 1
dl 0
loc 18
ccs 14
cts 14
cp 1
crap 1
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Incidents controller handling incident creation and rendering.
5
 *
6
 * phpMyAdmin Error reporting server
7
 * Copyright (c) phpMyAdmin project (https://www.phpmyadmin.net/)
8
 *
9
 * Licensed under The MIT License
10
 * For full copyright and license information, please see the LICENSE.txt
11
 * Redistributions of files must retain the above copyright notice.
12
 *
13
 * @copyright Copyright (c) phpMyAdmin project (https://www.phpmyadmin.net/)
14
 * @license   https://opensource.org/licenses/mit-license.php MIT License
15
 *
16
 * @see      https://www.phpmyadmin.net/
17
 */
18
19
namespace App\Controller;
20
21
use App\Forwarding\Sentry;
22
use App\Model\Table\IncidentsTable;
23
use App\Model\Table\NotificationsTable;
24
use App\Model\Table\ReportsTable;
25
use App\Report;
26
use Cake\Core\Configure;
27
use Cake\Http\Exception\NotFoundException;
28
use Cake\Http\Response;
29
use Cake\ORM\TableRegistry;
30
31
use function __;
32
use function array_merge;
33
use function count;
34
use function in_array;
35
use function json_decode;
36
use function json_encode;
37
38
use const JSON_PRETTY_PRINT;
39
use const JSON_UNESCAPED_SLASHES;
40
41
/**
42
 * Incidents controller handling incident creation and rendering.
43
 *
44
 * @property NotificationsTable $Notifications
45
 * @property IncidentsTable $Incidents
46
 * @property ReportsTable $Reports
47
 */
48
class IncidentsController extends AppController
49
{
50
    /**
51
     * Initialization hook method.
52
     *
53
     * Use this method to add common initialization code like loading components.
54
     *
55
     * @return void Nothing
56
     */
57 21
    public function initialize(): void
58
    {
59 21
        parent::initialize();
60 21
        $this->loadComponent('Mailer');
61 21
        $this->loadModel('Notifications');
62 21
        $this->loadModel('Incidents');
63 21
    }
64
65 7
    public function create(): ?Response
66
    {
67
        // Only allow POST requests
68 7
        $this->request->allowMethod(['post']);
69
70 7
        $requestBody = (string) $this->request->getBody();
71 7
        $bugReport = json_decode($requestBody, true);
72 7
        $result = $this->Incidents->createIncidentFromBugReport($bugReport);
73
74 7
        $sentryConfig = Configure::read('Forwarding.Sentry');
75 7
        if ($sentryConfig !== null) {
76
            $report = Report::fromString($requestBody);
77
            Sentry::process($report);
78
        }
79
80
        if (
81 7
            count($result['incidents']) > 0
82 7
            && ! in_array(false, $result['incidents'])
83
        ) {
84 2
            $response = [
85 7
                'success' => true,
86 7
                'message' => 'Thank you for your submission',
87 7
                'incident_id' => $result['incidents'],        // Return a list of incident ids.
88
            ];
89
        } else {
90 2
            $response = [
91 5
                'success' => false,
92
                'message' => 'There was a problem with your submission.',
93
            ];
94
        }
95
96 7
        $this->disableAutoRender();
97
98 7
        $this->response = $this->response
99 7
            ->withHeader('Content-Type', 'application/json')
100 7
            ->withHeader('X-Content-Type-Options', 'nosniff')
101 7
            ->withStringBody(
102 7
                json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
103
            );
104
105
        // For all the newly added reports,
106
        // send notification emails
107 7
        foreach ($result['reports'] as $report_id) {
108 7
            $this->sendNotificationMail($report_id);
109
        }
110
111 7
        return $this->response;
112
    }
113
114 7
    public function json(?string $id): ?Response
115
    {
116 7
        if (empty($id)) {
117
            throw new NotFoundException(__('Invalid Incident'));
118
        }
119
120 7
        $this->Incidents->recursive = -1;
121 7
        $incident = $this->Incidents->findById($id)->all()->first();
122 7
        if (! $incident) {
123
            throw new NotFoundException(__('The incident does not exist.'));
124
        }
125
126 7
        $incident['full_report'] =
127 7
            json_decode($incident['full_report'], true);
128 7
        $incident['stacktrace'] =
129 7
            json_decode($incident['stacktrace'], true);
130
131 7
        $this->disableAutoRender();
132
133 7
        return $this->response
134 7
            ->withType('application/json')
135 7
            ->withStringBody(json_encode($incident, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
136
    }
137
138 7
    public function view(?string $incidentId): void
139
    {
140 7
        if (empty($incidentId)) {
141
            throw new NotFoundException(__('Invalid Incident'));
142
        }
143
144 7
        $incidentId = (int) $incidentId;
145
146 7
        $incident = $this->Incidents->findById($incidentId)->all()->first();
147 7
        if (! $incident) {
148
            throw new NotFoundException(__('The incident does not exist.'));
149
        }
150
151 7
        $incident['full_report'] =
152 7
            json_decode($incident['full_report'], true);
153 7
        $incident['stacktrace'] =
154 7
            json_decode($incident['stacktrace'], true);
155
156 7
        $this->set('incident', $incident);
157 7
    }
158
159 7
    private function sendNotificationMail(int $reportId): void
160
    {
161 7
        $this->Reports = TableRegistry::getTableLocator()->get('Reports');
162 7
        $report = $this->Reports->findById($reportId)->all()->first()->toArray();
163 7
        $this->Reports->id = $reportId;
164
165 2
        $viewVars = [
166 7
            'report' => $report,
167 7
            'project_name' => Configure::read('GithubRepoPath'),
168 7
            'incidents' => $this->Reports->getIncidents()->toArray(),
169 7
            'incidents_with_description' => $this->Reports->getIncidentsWithDescription(),
170 7
            'incidents_with_stacktrace' => $this->Reports->getIncidentsWithDifferentStacktrace(),
171 7
            'related_reports' => $this->Reports->getRelatedReports(),
172 7
            'status' => $this->Reports->status,
173
        ];
174 7
        $viewVars = array_merge($viewVars, $this->getSimilarFields($reportId));
175
176 7
        $this->Mailer->sendReportMail($viewVars);
177 7
    }
178
179 7
    protected function getSimilarFields(int $id): array
180
    {
181 7
        $this->Reports->id = $id;
182
183 2
        $viewVars = [
184 7
            'columns' => TableRegistry::getTableLocator()->get('Incidents')->summarizableFields,
185
        ];
186 7
        $relatedEntries = [];
187
188 7
        foreach (TableRegistry::getTableLocator()->get('Incidents')->summarizableFields as $field) {
189 2
            [$entriesWithCount, $totalEntries] =
190 7
                    $this->Reports->getRelatedByField($field, 25, true);
191 7
            $relatedEntries[$field] = $entriesWithCount->toArray();
192 7
            $viewVars["${field}_distinct_count"] = $totalEntries;
193
        }
194
195 7
        $viewVars['related_entries'] = $relatedEntries;
196
197 7
        return $viewVars;
198
    }
199
}
200