Failed Conditions
Push — rbac ( be68b4...52c28b )
by Michael
03:11
created

PageCustomClose::getTemplate()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 14
ccs 0
cts 11
cp 0
rs 10
cc 4
nc 3
nop 1
crap 20
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
    }
0 ignored issues
show
Coding Style introduced by
Expected //end main()
Loading history...
51
52
    /**
53
     * @param $database
54
     *
55
     * @return Request
56
     * @throws ApplicationLogicException
57
     */
58
    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) {
0 ignored issues
show
introduced by
The condition $request === false is always false.
Loading history...
69
            throw new ApplicationLogicException('Request not found');
70
        }
71
72
        return $request;
73
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getRequest()
Loading history...
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
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getTemplate()
Loading history...
95
96
    /**
97
     * @param $database
98
     * @param $request
99
     *
100
     * @throws Exception
101
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag for "AccessDeniedException" exception
Loading history...
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
    }
0 ignored issues
show
Coding Style introduced by
Expected //end showCustomCloseForm()
Loading history...
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()}");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $request instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
213
            }
214
        }
215
    }
0 ignored issues
show
Coding Style introduced by
Expected //end doCustomClose()
Loading history...
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";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Custom, Created does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
239
        }
240
        else {
241
            $logCloseType = 'custom-n';
242
            $notificationCloseType = "Custom, Not Created";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Custom, Not Created does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
243
        }
244
245
        Logger::closeRequest($database, $request, $logCloseType, $messageBody);
0 ignored issues
show
Bug introduced by
$logCloseType of type string is incompatible with the type integer expected by parameter $target of Waca\Helpers\Logger::closeRequest(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

245
        Logger::closeRequest($database, $request, /** @scrutinizer ignore-type */ $logCloseType, $messageBody);
Loading history...
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'.");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $request instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $requestName instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
250
    }
0 ignored issues
show
Coding Style introduced by
Expected //end closeRequest()
Loading history...
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.");
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $request instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $deferTo instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
285
    }
0 ignored issues
show
Coding Style introduced by
Expected //end deferRequest()
Loading history...
286
}
0 ignored issues
show
Coding Style introduced by
Expected //end class
Loading history...
287