Passed
Push — master ( 083ff7...c84473 )
by William
03:02
created

IncidentsController::create()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 38
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 4

Importance

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