1
|
|
|
<?php |
2
|
|
|
/****************************************************************************** |
3
|
|
|
* Wikipedia Account Creation Assistance tool * |
4
|
|
|
* * |
5
|
|
|
* All code in this file is released into the public domain by the ACC * |
6
|
|
|
* Development Team. Please see team.json for a list of contributors. * |
7
|
|
|
******************************************************************************/ |
8
|
|
|
|
9
|
|
|
namespace Waca\Pages\RequestAction; |
10
|
|
|
|
11
|
|
|
use Exception; |
12
|
|
|
use Waca\DataObjects\EmailTemplate; |
13
|
|
|
use Waca\DataObjects\Request; |
14
|
|
|
use Waca\DataObjects\User; |
15
|
|
|
use Waca\Exceptions\AccessDeniedException; |
16
|
|
|
use Waca\Exceptions\ApplicationLogicException; |
17
|
|
|
use Waca\Exceptions\OptimisticLockFailedException; |
18
|
|
|
use Waca\Fragments\RequestData; |
19
|
|
|
use Waca\Helpers\Logger; |
20
|
|
|
use Waca\PdoDatabase; |
21
|
|
|
use Waca\SessionAlert; |
22
|
|
|
use Waca\WebRequest; |
23
|
|
|
|
24
|
|
|
class PageCustomClose extends PageCloseRequest |
25
|
|
|
{ |
26
|
|
|
use RequestData; |
27
|
|
|
|
28
|
|
|
protected function main() |
29
|
|
|
{ |
30
|
|
|
$database = $this->getDatabase(); |
31
|
|
|
|
32
|
|
|
$request = $this->getRequest($database); |
33
|
|
|
$currentUser = User::getCurrent($this->getDatabase()); |
34
|
|
|
|
35
|
|
|
if ($request->getStatus() === 'Closed') { |
36
|
|
|
throw new ApplicationLogicException('Request is already closed'); |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
// Dual-mode page |
40
|
|
|
if (WebRequest::wasPosted()) { |
41
|
|
|
$this->validateCSRFToken(); |
42
|
|
|
$this->doCustomClose($currentUser, $request, $database); |
43
|
|
|
|
44
|
|
|
$this->redirect(); |
45
|
|
|
} |
46
|
|
|
else { |
47
|
|
|
$this->assignCSRFToken(); |
48
|
|
|
$this->showCustomCloseForm($database, $request); |
49
|
|
|
} |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @param $database |
54
|
|
|
* |
55
|
|
|
* @return Request |
56
|
|
|
* @throws ApplicationLogicException |
57
|
|
|
*/ |
58
|
|
View Code Duplication |
protected function getRequest(PdoDatabase $database) |
|
|
|
|
59
|
|
|
{ |
60
|
|
|
$requestId = WebRequest::getInt('request'); |
61
|
|
|
if ($requestId === null) { |
62
|
|
|
throw new ApplicationLogicException('Request ID not found'); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** @var Request $request */ |
66
|
|
|
$request = Request::getById($requestId, $database); |
67
|
|
|
|
68
|
|
|
if ($request === false) { |
69
|
|
|
throw new ApplicationLogicException('Request not found'); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
return $request; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* @param PdoDatabase $database |
77
|
|
|
* |
78
|
|
|
* @return EmailTemplate|null |
79
|
|
|
*/ |
80
|
|
|
protected function getTemplate(PdoDatabase $database) |
81
|
|
|
{ |
82
|
|
|
$templateId = WebRequest::getInt('template'); |
83
|
|
|
if ($templateId === null) { |
84
|
|
|
return null; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** @var EmailTemplate $template */ |
88
|
|
|
$template = EmailTemplate::getById($templateId, $database); |
89
|
|
|
if ($template === false || !$template->getActive()) { |
90
|
|
|
return null; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
return $template; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @param $database |
98
|
|
|
* @param $request |
99
|
|
|
* |
100
|
|
|
* @throws Exception |
101
|
|
|
*/ |
102
|
|
|
protected function showCustomCloseForm(PdoDatabase $database, Request $request) |
103
|
|
|
{ |
104
|
|
|
$currentUser = User::getCurrent($database); |
105
|
|
|
$config = $this->getSiteConfiguration(); |
106
|
|
|
|
107
|
|
|
$allowedPrivateData = $this->isAllowedPrivateData($request, $currentUser); |
108
|
|
|
if (!$allowedPrivateData) { |
109
|
|
|
// we probably shouldn't be showing the user this form if they're not allowed to access private data... |
110
|
|
|
throw new AccessDeniedException($this->getSecurityManager()); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
$template = $this->getTemplate($database); |
114
|
|
|
|
115
|
|
|
// Preload data |
116
|
|
|
$this->assign('defaultAction', ''); |
117
|
|
|
$this->assign('preloadText', ''); |
118
|
|
|
$this->assign('preloadTitle', ''); |
119
|
|
|
|
120
|
|
|
if ($template !== null) { |
121
|
|
|
$this->assign('defaultAction', $template->getDefaultAction()); |
122
|
|
|
$this->assign('preloadText', $template->getText()); |
123
|
|
|
$this->assign('preloadTitle', $template->getName()); |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
// Static data |
127
|
|
|
$this->assign('requeststates', $config->getRequestStates()); |
128
|
|
|
|
129
|
|
|
// request data |
130
|
|
|
$this->assign('requestId', $request->getIp()); |
131
|
|
|
$this->assign('updateVersion', $request->getUpdateVersion()); |
132
|
|
|
$this->setupBasicData($request, $config); |
133
|
|
|
$this->setupReservationDetails($request->getReserved(), $database, $currentUser); |
134
|
|
|
$this->setupPrivateData($request, $currentUser, $this->getSiteConfiguration(), $database); |
135
|
|
|
|
136
|
|
|
// IP location |
137
|
|
|
$trustedIp = $this->getXffTrustProvider()->getTrustedClientIp($request->getIp(), $request->getForwardedIp()); |
138
|
|
|
$this->assign('iplocation', $this->getLocationProvider()->getIpLocation($trustedIp)); |
139
|
|
|
|
140
|
|
|
// Confirmations |
141
|
|
|
$this->assign('confirmEmailAlreadySent', $this->checkEmailAlreadySent($request)); |
142
|
|
|
$this->assign('confirmReserveOverride', $this->checkReserveOverride($request, $currentUser)); |
143
|
|
|
|
144
|
|
|
$this->assign('canSkipCcMailingList', $this->barrierTest('skipCcMailingList', $currentUser)); |
145
|
|
|
|
146
|
|
|
// template |
147
|
|
|
$this->setTemplate('custom-close.tpl'); |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* @param User $currentUser |
152
|
|
|
* @param Request $request |
153
|
|
|
* @param PdoDatabase $database |
154
|
|
|
* |
155
|
|
|
* @throws ApplicationLogicException |
156
|
|
|
*/ |
157
|
|
|
protected function doCustomClose(User $currentUser, Request $request, PdoDatabase $database) |
158
|
|
|
{ |
159
|
|
|
$messageBody = WebRequest::postString('msgbody'); |
160
|
|
|
if ($messageBody === null || trim($messageBody) === '') { |
161
|
|
|
throw new ApplicationLogicException('Message body cannot be blank'); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$ccMailingList = true; |
165
|
|
|
if ($this->barrierTest('skipCcMailingList', $currentUser)) { |
166
|
|
|
$ccMailingList = WebRequest::postBoolean('ccMailingList'); |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
if ($request->getStatus() === 'Closed') { |
170
|
|
|
throw new ApplicationLogicException('Request is already closed'); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
if (!(WebRequest::postBoolean('confirmEmailAlreadySent') |
174
|
|
|
&& WebRequest::postBoolean('confirmReserveOverride')) |
175
|
|
|
) { |
176
|
|
|
throw new ApplicationLogicException('Not all confirmations checked'); |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
$action = WebRequest::postString('action'); |
180
|
|
|
$availableRequestStates = $this->getSiteConfiguration()->getRequestStates(); |
181
|
|
|
|
182
|
|
|
if ($action === EmailTemplate::CREATED || $action === EmailTemplate::NOT_CREATED) { |
183
|
|
|
// Close request |
184
|
|
|
$this->closeRequest($request, $database, $action, $messageBody); |
185
|
|
|
|
186
|
|
|
// Send the mail after the save, since save can be rolled back |
187
|
|
|
$this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
188
|
|
|
} |
189
|
|
|
else { |
190
|
|
|
if (array_key_exists($action, $availableRequestStates)) { |
191
|
|
|
// Defer to other state |
192
|
|
|
$this->deferRequest($request, $database, $action, $availableRequestStates, $messageBody); |
193
|
|
|
|
194
|
|
|
// Send the mail after the save, since save can be rolled back |
195
|
|
|
$this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
196
|
|
|
} |
197
|
|
|
else { |
198
|
|
|
$request->setReserved(null); |
199
|
|
|
$request->setUpdateVersion(WebRequest::postInt('updateversion')); |
200
|
|
|
$request->save(); |
201
|
|
|
|
202
|
|
|
// Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE |
203
|
|
|
// and be rolled back. |
204
|
|
|
|
205
|
|
|
// Send mail |
206
|
|
|
$this->sendMail($request, $messageBody, $currentUser, $ccMailingList); |
207
|
|
|
|
208
|
|
|
Logger::sentMail($database, $request, $messageBody); |
209
|
|
|
Logger::unreserve($database, $request); |
210
|
|
|
|
211
|
|
|
$this->getNotificationHelper()->sentMail($request); |
212
|
|
|
SessionAlert::success("Sent mail to Request {$request->getId()}"); |
213
|
|
|
} |
214
|
|
|
} |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @param Request $request |
219
|
|
|
* @param PdoDatabase $database |
220
|
|
|
* @param string $action |
221
|
|
|
* @param string $messageBody |
222
|
|
|
* |
223
|
|
|
* @throws Exception |
224
|
|
|
* @throws OptimisticLockFailedException |
225
|
|
|
*/ |
226
|
|
|
protected function closeRequest(Request $request, PdoDatabase $database, $action, $messageBody) |
227
|
|
|
{ |
228
|
|
|
$request->setStatus('Closed'); |
229
|
|
|
$request->setReserved(null); |
230
|
|
|
$request->setUpdateVersion(WebRequest::postInt('updateversion')); |
231
|
|
|
$request->save(); |
232
|
|
|
|
233
|
|
|
// Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE and |
234
|
|
|
// be rolled back. |
235
|
|
|
|
236
|
|
|
if ($action == EmailTemplate::CREATED) { |
237
|
|
|
$logCloseType = 'custom-y'; |
238
|
|
|
$notificationCloseType = "Custom, Created"; |
239
|
|
|
} |
240
|
|
|
else { |
241
|
|
|
$logCloseType = 'custom-n'; |
242
|
|
|
$notificationCloseType = "Custom, Not Created"; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
Logger::closeRequest($database, $request, $logCloseType, $messageBody); |
246
|
|
|
$this->getNotificationHelper()->requestClosed($request, $notificationCloseType); |
247
|
|
|
|
248
|
|
|
$requestName = htmlentities($request->getName(), ENT_COMPAT, 'UTF-8'); |
249
|
|
|
SessionAlert::success("Request {$request->getId()} ({$requestName}) marked as 'Done'."); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
/** |
253
|
|
|
* @param Request $request |
254
|
|
|
* @param PdoDatabase $database |
255
|
|
|
* @param string $action |
256
|
|
|
* @param $availableRequestStates |
257
|
|
|
* @param string $messageBody |
258
|
|
|
* |
259
|
|
|
* @throws Exception |
260
|
|
|
* @throws OptimisticLockFailedException |
261
|
|
|
*/ |
262
|
|
|
protected function deferRequest( |
263
|
|
|
Request $request, |
264
|
|
|
PdoDatabase $database, |
265
|
|
|
$action, |
266
|
|
|
$availableRequestStates, |
267
|
|
|
$messageBody |
268
|
|
|
) { |
269
|
|
|
$request->setStatus($action); |
270
|
|
|
$request->setReserved(null); |
271
|
|
|
$request->setUpdateVersion(WebRequest::postInt('updateversion')); |
272
|
|
|
$request->save(); |
273
|
|
|
|
274
|
|
|
// Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE |
275
|
|
|
// and be rolled back. |
276
|
|
|
|
277
|
|
|
$deferToLog = $availableRequestStates[$action]['defertolog']; |
278
|
|
|
Logger::sentMail($database, $request, $messageBody); |
279
|
|
|
Logger::deferRequest($database, $request, $deferToLog); |
280
|
|
|
|
281
|
|
|
$this->getNotificationHelper()->requestDeferredWithMail($request); |
282
|
|
|
|
283
|
|
|
$deferTo = $availableRequestStates[$action]['deferto']; |
284
|
|
|
SessionAlert::success("Request {$request->getId()} deferred to $deferTo, sending an email."); |
285
|
|
|
} |
286
|
|
|
} |
287
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.