/
SourceForgeController.php
240 lines (212 loc) · 7.69 KB
/
SourceForgeController.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
<?php
/* vim: set noexpandtab sw=2 ts=2 sts=2: */
/**
* Sourceforge controller handling source forge ticket submission and creation
*
* phpMyAdmin Error reporting server
* Copyright (c) phpMyAdmin project (http://www.phpmyadmin.net)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) phpMyAdmin project (http://www.phpmyadmin.net)
* @package Server.Controller
* @link http://www.phpmyadmin.net
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Sourceforge controller handling source forge ticket submission and creation
*
* @package Server.Controller
*/
class SourceForgeController extends AppController {
public $helpers = array('Html', 'Form');
public $components = array('SourceForgeApi');
public $uses = array('Report');
public function beforeFilter() {
$this->SourceForgeApi->accessToken =
Configure::read('SourceForgeCredentials');
parent::beforeFilter();
}
public function authorize() {
$requestToken =
$this->SourceForgeApi->getRequestToken('/source_forge/callback');
if ($requestToken) {
$this->Session->write('sourceforge_request_token', serialize($requestToken));
$this->redirect($this->SourceForgeApi->getRedirectUrl($requestToken));
}
$this->autoRender = false;
return json_encode($requestToken);
}
public function callback() {
$requestToken = unserialize($this->Session->read('sourceforge_request_token'));
$accessToken = $this->SourceForgeApi->getAccessToken($requestToken);
$this->autoRender = false;
return json_encode($accessToken);
}
public function create_ticket($reportId) {
if (!$reportId) {
throw new NotFoundException(__('Invalid report'));
}
$report = $this->Report->findById($reportId);
if (!$report) {
throw new NotFoundException(__('Invalid report'));
}
if (empty($this->request->data)) {
return;
}
$data = $this->_getTicketData($reportId);
$response = $this->SourceForgeApi->createTicket(
Configure::read('SourceForgeProjectName'), $data);
if ($this->_handleSFResponse($response, 1, $reportId)) {
$this->redirect(array('controller' => 'reports', 'action' => 'view',
$reportId));
}
}
/**
* Links error report to existing bug ticket on SF.net
*
*/
public function link_ticket($reportId) {
if (!$reportId) {
throw new NotFoundException(__('Invalid reportId'));
}
$report = $this->Report->findById($reportId);
if (!$report) {
throw new NotFoundException(__('Invalid Report'));
}
$ticket_id = $this->request->query['ticket_id'];
if(!$ticket_id) {
throw new NotFoundException(__('Invalid Ticket ID!!'));
}
$incident = $this->Report->Incident->findByReportId($reportId);
$exception_type = ($incident['Incident']['exception_type']) ? ('php') : ('js');
// "formatted" text of the comment.
$commentText = "Param | Value "
. "\n -----------|--------------------"
. "\n Error Type | " . $report['Report']['error_name']
. "\n Error Message |" . $report['Report']['error_message']
. "\n Exception Type |" . $exception_type
. "\n Link | [Report#"
. $reportId
."]("
. Router::url('/reports/view/'.$reportId,true)
.")"
. "\n\n*This comment is posted automatically by phpMyAdmin's "
. "[error-reporting-server](http://reports.phpmyadmin.net).*";
$response = $this->SourceForgeApi->createComment(
Configure::read('SourceForgeProjectName'),
$ticket_id,
array('text' => $commentText)
);
$this->_handleSFResponse($response, 2, $reportId, $ticket_id);
$this->redirect(array('controller' => 'reports', 'action' => 'view',
$reportId));
}
protected function _getTicketData($reportId) {
$data = array(
'ticket_form.summary' => $this->request->data['Ticket']['summary'],
'ticket_form.description' => $this->_augmentDescription(
$this->request->data['Ticket']['description'], $reportId),
'ticket_form.status' => 'open',
'ticket_form.labels' => $this->request->data['Ticket']['labels'],
'ticket_form._milestone' => $this->request->data['Ticket']['milestone'],
);
if (!empty($data['ticket_form.labels'])) {
$data['ticket_form.labels'] .= ',';
}
$data['ticket_form.labels'] .= 'automated-error-report';
return $data;
}
protected function _getErrors($body) {
$errorString = "There were some problems with the ticket submission."
." Returned status is (" . $body["status"] . ")";
$errors = $body["errors"];
if ($body["status"] === "Validation Error") {
$errorString .= '<ul>';
foreach ($errors['ticket_form'] as $field => $message) {
$errorString .= "<li>";
$errorString .= "$field: $message";
$errorString .= "</li>";
}
$errorString .= '</ul>';
} else {
$errorString .= "<br/> Here is the dump for the errors field provided by"
. " sourceforge: <br/>"
. "<pre>"
. print_r($errors, true)
. "</pre>";
}
return $errorString;
}
/**
* Returns the description with the added string to link to the report
* @param String $description the original description submitted by the dev
* @param String $reportId the report id relating to the ticket
*
* @return String augmented description
*/
protected function _augmentDescription($description, $reportId) {
$this->Report->read(null, $reportId);
return "$description\n\n\nThis report is related to user submitted report "
. "[#" . $this->Report->id . "](" . $this->Report->getUrl()
. ") on the phpmyadmin error reporting server.";
}
/**
* Sourceforge Response Handler
* @param Object $response the response returned by sourceforge API
* @param Integer $type type of response. 1 for create_ticket, 2 for link_ticket
* @param Integer $report_id report id.
* @param Integer $ticket_id ticket id, required for link tivket only.
*
* @return Boolean value. True on success. False on any type of failure.
*/
protected function _handleSFResponse($response, $type, $report_id, $ticket_id = 1)
{
if (!in_array($type, array(1,2))) {
throw new InvalidArgumentException('Invalid Argument "$type".');
}
if ($response->code[0] === "3") {
// success
if ($type == 1) {
preg_match("<rest/p/.*/bugs/(\d+)/>",
$response->headers['Location'], $matches);
$ticket_id = $matches[1];
}
$this->Report->read(null, $report_id);
$this->Report->save(array('sourceforge_bug_id' => $ticket_id));
if ($type == 2) {
$msg = 'Source forge ticket has been linked with this report.';
} else {
$msg = 'Source forge ticket has been created for this report.';
}
$this->Session->setFlash($msg, "default", array("class" => "alert alert-success"));
return true;
} else if ($response->code === "403") {
$this->Session->setFlash(
"Unauthorised access to SourceForge ticketing system. SourceForge"
. " credentials may be out of date. Please check and try again"
. " later.", "default", array("class" => "alert alert-error"));
return false;
} else if ($response->code === "404"
&& $type == 2
) {
$this->Session->setFlash(
"Bug Ticket not found on SourceForge."
. " Are you sure the ticket number is correct?!! Please check and try again",
"default", array("class" => "alert alert-error"));
return false;
} else {
//fail
$response->body = json_decode($response->body, true);
CakeLog::write('sourceforge', 'Submission for sourceforge ticket may have failed.',
'sourceforge');
CakeLog::write('sourceforge', 'Response dump:', 'sourceforge');
CakeLog::write('sourceforge', print_r($response["raw"], true), 'sourceforge');
$this->Session->setFlash($this->_getErrors( $response->body), "default",
array("class" => "alert alert-error"));
return false;
}
}
}