Passed
Push — multiproject/requestforms ( 675fe5 )
by Simon
08:58 queued 04:51
created

PageRequestAccount::handleFormRefilling()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 12
ccs 0
cts 9
cp 0
rs 10
cc 3
nc 2
nop 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\Request;
10
11
use Exception;
12
use Waca\DataObjects\Comment;
13
use Waca\DataObjects\Domain;
14
use Waca\DataObjects\Request;
15
use Waca\DataObjects\RequestForm;
16
use Waca\DataObjects\RequestQueue;
17
use Waca\Exceptions\ApplicationLogicException;
18
use Waca\Exceptions\OptimisticLockFailedException;
19
use Waca\Helpers\BanHelper;
20
use Waca\Helpers\MarkdownRenderingHelper;
21
use Waca\SessionAlert;
22
use Waca\Tasks\PublicInterfacePageBase;
23
use Waca\Validation\RequestValidationHelper;
24
use Waca\Validation\ValidationError;
25
use Waca\WebRequest;
26
27
class PageRequestAccount extends PublicInterfacePageBase
28
{
29
    /** @var RequestValidationHelper do not use directly. */
30
    private $validationHelper;
31
32
    /**
33
     * Main function for this page, when no specific actions are called.
34
     * @return void
35
     * @throws OptimisticLockFailedException
36
     * @throws Exception
37
     */
38
    protected function main()
39
    {
40
        // dual mode page
41
        if (WebRequest::wasPosted()) {
42
            $request = $this->createNewRequest(null);
43
            $this->handleFormPost($request);
44
        }
45
        else {
46
            $this->handleFormRefilling();
47
48
            $this->setTemplate('request/request-form.tpl');
49
        }
50
    }
51
52
    /**
53
     * Handles dynamic request forms.
54
     * @return void
55
     * @throws OptimisticLockFailedException
56
     * @throws Exception
57
     */
58
    protected function dynamic()
59
    {
60
        $database = $this->getDatabase();
61
62
        $pathInfo = WebRequest::pathInfo();
63
        $domain = Domain::getByShortName($pathInfo[1], $database);
64
        if ($domain === false || !$domain->isEnabled()) {
65
            throw new ApplicationLogicException("This form is not available at this time.");
66
        }
67
68
        $form = RequestForm::getByPublicEndpoint($database, $pathInfo[2], $domain->getId());
69
70
        if ($form === false || !$form->isEnabled()) {
71
            throw new ApplicationLogicException("This form is not available at this time.");
72
        }
73
74
        // dual mode page
75
        if (WebRequest::wasPosted()) {
76
            $request = $this->createNewRequest($form);
77
            $this->handleFormPost($request);
78
        }
79
        else {
80
            $this->handleFormRefilling();
81
82
            $renderer = new MarkdownRenderingHelper();
83
            $this->assign('formPreamble', $renderer->doRender($form->getFormContent()));
84
            $this->assign('formUsernameHelp', $renderer->doRenderInline($form->getUsernameHelp()));
85
            $this->assign('formEmailHelp', $renderer->doRenderInline($form->getEmailHelp()));
86
            $this->assign('formCommentsHelp', $renderer->doRenderInline($form->getCommentHelp()));
87
88
            $this->setTemplate('request/request-form-dynamic.tpl');
89
        }
90
    }
91
92
    /**
93
     * @param RequestForm|null $form
94
     *
95
     * @return Request
96
     * @throws ApplicationLogicException
97
     */
98
    protected function createNewRequest(?RequestForm $form): Request
99
    {
100
        $database = $this->getDatabase();
101
102
        $request = new Request();
103
104
        if ($form === null) {
105
            $domain = 1;
106
        }
107
        else {
108
            $domain = $form->getDomain();
109
            $request->setOriginForm($form->getId());
110
        }
111
112
        $request->setQueue(RequestQueue::getDefaultQueue($database, $domain)->getId());
113
        $request->setDatabase($database);
114
115
        $request->setName(trim(WebRequest::postString('name')));
0 ignored issues
show
Bug introduced by
It seems like Waca\WebRequest::postString('name') can also be of type null; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

115
        $request->setName(trim(/** @scrutinizer ignore-type */ WebRequest::postString('name')));
Loading history...
116
        $request->setEmail(WebRequest::postEmail('email'));
117
118
        $request->setIp(WebRequest::remoteAddress());
119
        $request->setForwardedIp(WebRequest::forwardedAddress());
120
121
        $request->setUserAgent(WebRequest::userAgent());
122
123
        return $request;
124
    }
125
126
    /**
127
     * @return Comment|null
128
     */
129
    private function createComment()
130
    {
131
        $commentText = WebRequest::postString('comments');
132
        if ($commentText === null || trim($commentText) === '') {
133
            return null;
134
        }
135
136
        $comment = new Comment();
137
        $comment->setDatabase($this->getDatabase());
138
139
        $comment->setVisibility('requester');
140
        $comment->setUser(null);
141
        $comment->setComment($commentText);
142
143
        return $comment;
144
    }
145
146
    /**
147
     * @param Request $request
148
     *
149
     * @return ValidationError[]
150
     */
151
    protected function validateRequest($request)
152
    {
153
        $validationHelper = $this->getRequestValidationHelper();
154
155
        // These are arrays of ValidationError.
156
        $nameValidation = $validationHelper->validateName($request);
157
        $emailValidation = $validationHelper->validateEmail($request, WebRequest::postEmail('emailconfirm'));
158
        $otherValidation = $validationHelper->validateOther($request);
159
160
        $validationErrors = array_merge($nameValidation, $emailValidation, $otherValidation);
161
162
        return $validationErrors;
163
    }
164
165
    /**
166
     * @param Request      $request
167
     *
168
     * @param Comment|null $comment
169
     *
170
     * @throws OptimisticLockFailedException
171
     * @throws Exception
172
     */
173
    protected function saveAsEmailConfirmation(Request $request, $comment)
174
    {
175
        $request->generateEmailConfirmationHash();
176
        $request->save();
177
178
        if ($comment !== null) {
179
            $comment->setRequest($request->getId());
180
            $comment->save();
181
        }
182
183
        $trustedIp = $this->getXffTrustProvider()->getTrustedClientIp(
184
            $request->getIp(),
185
            $request->getForwardedIp());
186
187
        $this->assign("ip", $trustedIp);
188
        $this->assign("id", $request->getId());
189
        $this->assign("hash", $request->getEmailConfirm());
190
191
        // Sends the confirmation email to the user.
192
        // FIXME: domains
193
        /** @var Domain $domain */
194
        $domain = Domain::getById(1, $this->getDatabase());
195
        $this->getEmailHelper()->sendMail(
196
            $domain->getEmailSender(),
197
            $request->getEmail(),
198
            "[ACC #{$request->getId()}] English Wikipedia Account Request",
199
            $this->fetchTemplate('request/confirmation-mail.tpl'));
200
201
        $this->redirect('emailConfirmationRequired');
202
    }
203
204
    /**
205
     * @param Request      $request
206
     *
207
     * @param Comment|null $comment
208
     *
209
     * @throws OptimisticLockFailedException
210
     * @throws Exception
211
     */
212
    protected function saveWithoutEmailConfirmation(Request $request, $comment)
213
    {
214
        $request->setEmailConfirm(0); // fixme Since it can't be null
215
        $request->save();
216
217
        if ($comment !== null) {
218
            $comment->setRequest($request->getId());
219
            $comment->save();
220
        }
221
222
        $this->getNotificationHelper()->requestReceived($request);
223
224
        $this->redirect('requestSubmitted');
225
    }
226
227
    /**
228
     * @return RequestValidationHelper
229
     */
230
    protected function getRequestValidationHelper(): RequestValidationHelper
231
    {
232
        $banHelper = new BanHelper($this->getDatabase(), $this->getXffTrustProvider(), null);
233
234
        if ($this->validationHelper === null) {
235
            $this->validationHelper = new RequestValidationHelper(
236
                $banHelper,
237
                $this->getDatabase(),
238
                $this->getAntiSpoofProvider(),
239
                $this->getXffTrustProvider(),
240
                $this->getHttpHelper(),
241
                $this->getTorExitProvider(),
242
                $this->getSiteConfiguration());
243
        }
244
245
        return $this->validationHelper;
246
}
247
248
    /**
249
     * @param Request $request
250
     *
251
     * @return void
252
     * @throws OptimisticLockFailedException
253
     */
254
    protected function handleFormPost(Request $request): void
255
    {
256
        $comment = $this->createComment();
257
258
        $validationErrors = $this->validateRequest($request);
259
260
        if (count($validationErrors) > 0) {
261
            foreach ($validationErrors as $validationError) {
262
                SessionAlert::error($validationError->getErrorMessage());
263
            }
264
265
            // Preserve the data after an error
266
            WebRequest::setSessionContext('accountReq',
267
                array(
268
                    'username' => WebRequest::postString('name'),
269
                    'email'    => WebRequest::postEmail('email'),
270
                    'comments' => WebRequest::postString('comments'),
271
                )
272
            );
273
274
            // Validation error, bomb out early.
275
            $this->redirect();
276
277
            return;
278
        }
279
280
        // actually save the request to the database
281
        if ($this->getSiteConfiguration()->getEmailConfirmationEnabled()) {
282
            $this->saveAsEmailConfirmation($request, $comment);
283
        }
284
        else {
285
            $this->saveWithoutEmailConfirmation($request, $comment);
286
        }
287
288
        $this->getRequestValidationHelper()->postSaveValidations($request);
289
    }
290
291
    /**
292
     * @return void
293
     */
294
    protected function handleFormRefilling(): void
295
    {
296
        // set the form values from the session context
297
        $context = WebRequest::getSessionContext('accountReq');
298
        if ($context !== null && is_array($context)) {
299
            $this->assign('username', $context['username']);
300
            $this->assign('email', $context['email']);
301
            $this->assign('comments', $context['comments']);
302
        }
303
304
        // Clear it for a refresh
305
        WebRequest::setSessionContext('accountReq', null);
306
    }
307
}