Failed Conditions
Push — rbac ( 1ec5d5 )
by Simon
18:18 queued 05:15
created

PageCustomClose::showCustomCloseForm()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 47
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 26
nc 3
nop 2
dl 0
loc 47
ccs 0
cts 30
cp 0
crap 12
rs 9.0303
c 0
b 0
f 0
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($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