Completed
Branch newinternal (cdd491)
by Simon
04:39
created

PageCustomClose::main()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 3
eloc 13
c 3
b 0
f 0
nc 3
nop 0
dl 0
loc 23
rs 9.0856
ccs 0
cts 18
cp 0
crap 12
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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();
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
		// template
145
		$this->setTemplate('custom-close.tpl');
146
	}
147
148
	/**
149
	 * @param User        $currentUser
150
	 * @param Request     $request
151
	 * @param PdoDatabase $database
152
	 *
153
	 * @throws ApplicationLogicException
154
	 */
155
	protected function doCustomClose(User $currentUser, Request $request, PdoDatabase $database)
156
	{
157
		$messageBody = WebRequest::postString('msgbody');
158
		if ($messageBody === null || trim($messageBody) === '') {
159
			throw new ApplicationLogicException('Message body cannot be blank');
160
		}
161
162
		$ccMailingList = true;
163
		if ($currentUser->isAdmin() || $currentUser->isCheckuser()) {
164
			$ccMailingList = WebRequest::postBoolean('ccMailingList');
165
		}
166
167
		if ($request->getStatus() === 'Closed') {
168
			throw new ApplicationLogicException('Request is already closed');
169
		}
170
171
		if (!(WebRequest::postBoolean('confirmEmailAlreadySent')
172
			&& WebRequest::postBoolean('confirmReserveOverride'))) {
173
			throw new ApplicationLogicException('Not all confirmations checked');
174
		}
175
176
		$action = WebRequest::postString('action');
177
		$availableRequestStates = $this->getSiteConfiguration()->getRequestStates();
178
179
		if ($action === EmailTemplate::CREATED || $action === EmailTemplate::NOT_CREATED) {
180
			// Close request
181
			$this->closeRequest($request, $database, $action, $messageBody);
182
183
			// Send the mail after the save, since save can be rolled back
184
			$this->sendMail($request, $messageBody, $currentUser, $ccMailingList);
185
		}
186
		else {
187
			if (array_key_exists($action, $availableRequestStates)) {
188
				// Defer to other state
189
				$this->deferRequest($request, $database, $action, $availableRequestStates, $messageBody);
190
191
				// Send the mail after the save, since save can be rolled back
192
				$this->sendMail($request, $messageBody, $currentUser, $ccMailingList);
193
			}
194
			else {
195
				$request->setReserved(null);
196
				$request->setUpdateVersion(WebRequest::postInt('updateversion'));
197
				$request->save();
198
199
				// Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE
200
				// and be rolled back.
201
202
				// Send mail
203
				$this->sendMail($request, $messageBody, $currentUser, $ccMailingList);
204
205
				Logger::sentMail($database, $request, $messageBody);
206
				Logger::unreserve($database, $request);
207
208
				$this->getNotificationHelper()->sentMail($request);
209
				SessionAlert::success("Sent mail to Request {$request->getId()}");
210
			}
211
		}
212
	}
213
214
	/**
215
	 * @param Request     $request
216
	 * @param PdoDatabase $database
217
	 * @param string      $action
218
	 * @param string      $messageBody
219
	 *
220
	 * @throws Exception
221
	 * @throws OptimisticLockFailedException
222
	 */
223
	protected function closeRequest(Request $request, PdoDatabase $database, $action, $messageBody)
224
	{
225
		$request->setStatus('Closed');
226
		$request->setReserved(null);
227
		$request->setUpdateVersion(WebRequest::postInt('updateversion'));
228
		$request->save();
229
230
		// Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE and
231
		// be rolled back.
232
233
		if ($action == EmailTemplate::CREATED) {
234
			$logCloseType = 'custom-y';
235
			$notificationCloseType = "Custom, Created";
236
		}
237
		else {
238
			$logCloseType = 'custom-n';
239
			$notificationCloseType = "Custom, Not Created";
240
		}
241
242
		Logger::closeRequest($database, $request, $logCloseType, $messageBody);
243
		$this->getNotificationHelper()->requestClosed($request, $notificationCloseType);
244
245
		$requestName = htmlentities($request->getName(), ENT_COMPAT, 'UTF-8');
246
		SessionAlert::success("Request {$request->getId()} ({$requestName}) marked as 'Done'.");
247
	}
248
249
	/**
250
	 * @param Request     $request
251
	 * @param PdoDatabase $database
252
	 * @param string      $action
253
	 * @param             $availableRequestStates
254
	 * @param string      $messageBody
255
	 *
256
	 * @throws Exception
257
	 * @throws OptimisticLockFailedException
258
	 */
259
	protected function deferRequest(
260
		Request $request,
261
		PdoDatabase $database,
262
		$action,
263
		$availableRequestStates,
264
		$messageBody
265
	) {
266
		$request->setStatus($action);
267
		$request->setReserved(null);
268
		$request->setUpdateVersion(WebRequest::postInt('updateversion'));
269
		$request->save();
270
271
		// Perform the notifications and stuff *after* we've successfully saved, since the save can throw an OLE
272
		// and be rolled back.
273
274
		$deferToLog = $availableRequestStates[$action]['defertolog'];
275
		Logger::sentMail($database, $request, $messageBody);
276
		Logger::deferRequest($database, $request, $deferToLog);
277
278
		$this->getNotificationHelper()->requestDeferredWithMail($request);
279
280
		$deferTo = $availableRequestStates[$action]['deferto'];
281
		SessionAlert::success("Request {$request->getId()} deferred to $deferTo, sending an email.");
282
	}
283
}