Failed Conditions
Pull Request — bugsquish (#573)
by Simon
03:02 queued 49s
created

RequestValidationHelper::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 22
ccs 0
cts 22
cp 0
rs 9.9332
cc 1
nc 1
nop 10
crap 2

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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\Validation;
10
11
use Exception;
12
use Waca\DataObjects\Request;
13
use Waca\Helpers\HttpHelper;
14
use Waca\Helpers\Interfaces\IBanHelper;
15
use Waca\PdoDatabase;
16
use Waca\Providers\Interfaces\IAntiSpoofProvider;
17
use Waca\Providers\Interfaces\IXffTrustProvider;
18
use Waca\Providers\TorExitProvider;
19
20
/**
21
 * Performs the validation of an incoming request.
22
 */
23
class RequestValidationHelper
24
{
25
    /** @var IBanHelper */
26
    private $banHelper;
27
    /** @var Request */
28
    private $request;
29
    private $emailConfirmation;
30
    /** @var PdoDatabase */
31
    private $database;
32
    /** @var IAntiSpoofProvider */
33
    private $antiSpoofProvider;
34
    /** @var IXffTrustProvider */
35
    private $xffTrustProvider;
36
    /** @var HttpHelper */
37
    private $httpHelper;
38
    /**
39
     * @var string
40
     */
41
    private $mediawikiApiEndpoint;
42
    private $titleBlacklistEnabled;
43
    /**
44
     * @var TorExitProvider
45
     */
46
    private $torExitProvider;
47
48
    /**
49
     * Summary of __construct
50
     *
51
     * @param IBanHelper         $banHelper
52
     * @param Request            $request
53
     * @param string             $emailConfirmation
54
     * @param PdoDatabase        $database
55
     * @param IAntiSpoofProvider $antiSpoofProvider
56
     * @param IXffTrustProvider  $xffTrustProvider
57
     * @param HttpHelper         $httpHelper
58
     * @param string             $mediawikiApiEndpoint
59
     * @param boolean            $titleBlacklistEnabled
60
     * @param TorExitProvider    $torExitProvider
61
     */
62
    public function __construct(
63
        IBanHelper $banHelper,
64
        Request $request,
65
        $emailConfirmation,
66
        PdoDatabase $database,
67
        IAntiSpoofProvider $antiSpoofProvider,
68
        IXffTrustProvider $xffTrustProvider,
69
        HttpHelper $httpHelper,
70
        $mediawikiApiEndpoint,
71
        $titleBlacklistEnabled,
72
        TorExitProvider $torExitProvider
73
    ) {
74
        $this->banHelper = $banHelper;
75
        $this->request = $request;
76
        $this->emailConfirmation = $emailConfirmation;
77
        $this->database = $database;
78
        $this->antiSpoofProvider = $antiSpoofProvider;
79
        $this->xffTrustProvider = $xffTrustProvider;
80
        $this->httpHelper = $httpHelper;
81
        $this->mediawikiApiEndpoint = $mediawikiApiEndpoint;
82
        $this->titleBlacklistEnabled = $titleBlacklistEnabled;
83
        $this->torExitProvider = $torExitProvider;
84
    }
85
86
    /**
87
     * Summary of validateName
88
     * @return ValidationError[]
89
     */
90
    public function validateName()
91
    {
92
        $errorList = array();
93
94
        // ERRORS
95
        // name is empty
96
        if (trim($this->request->getName()) == "") {
97
            $errorList[ValidationError::NAME_EMPTY] = new ValidationError(ValidationError::NAME_EMPTY);
98
        }
99
100
        // username already exists
101
        if ($this->userExists()) {
102
            $errorList[ValidationError::NAME_EXISTS] = new ValidationError(ValidationError::NAME_EXISTS);
103
        }
104
105
        // username part of SUL account
106
        if ($this->userSulExists()) {
107
            // using same error slot as name exists - it's the same sort of error, and we probably only want to show one.
108
            $errorList[ValidationError::NAME_EXISTS] = new ValidationError(ValidationError::NAME_EXISTS_SUL);
109
        }
110
111
        // username is numbers
112
        if (preg_match("/^[0-9]+$/", $this->request->getName()) === 1) {
113
            $errorList[ValidationError::NAME_NUMONLY] = new ValidationError(ValidationError::NAME_NUMONLY);
114
        }
115
116
        // username can't contain #@/<>[]|{}
117
        if (preg_match("/[" . preg_quote("#@/<>[]|{}", "/") . "]/", $this->request->getName()) === 1) {
118
            $errorList[ValidationError::NAME_INVALIDCHAR] = new ValidationError(ValidationError::NAME_INVALIDCHAR);
119
        }
120
121
        // existing non-closed request for this name
122
        if ($this->nameRequestExists()) {
123
            $errorList[ValidationError::OPEN_REQUEST_NAME] = new ValidationError(ValidationError::OPEN_REQUEST_NAME);
124
        }
125
126
        return $errorList;
127
    }
128
129
    /**
130
     * Summary of validateEmail
131
     * @return ValidationError[]
132
     */
133
    public function validateEmail()
134
    {
135
        $errorList = array();
136
137
        // ERRORS
138
139
        // email addresses must match
140
        if ($this->request->getEmail() != $this->emailConfirmation) {
141
            $errorList[ValidationError::EMAIL_MISMATCH] = new ValidationError(ValidationError::EMAIL_MISMATCH);
142
        }
143
144
        // email address must be validly formed
145
        if (trim($this->request->getEmail()) == "") {
146
            $errorList[ValidationError::EMAIL_EMPTY] = new ValidationError(ValidationError::EMAIL_EMPTY);
147
        }
148
149
        // email address must be validly formed
150
        if (!filter_var($this->request->getEmail(), FILTER_VALIDATE_EMAIL)) {
151
            if (trim($this->request->getEmail()) != "") {
152
                $errorList[ValidationError::EMAIL_INVALID] = new ValidationError(ValidationError::EMAIL_INVALID);
153
            }
154
        }
155
156
        // email address can't be wikimedia/wikipedia .com/org
157
        if (preg_match('/.*@.*wiki(m.dia|p.dia)\.(org|com)/i', $this->request->getEmail()) === 1) {
158
            $errorList[ValidationError::EMAIL_WIKIMEDIA] = new ValidationError(ValidationError::EMAIL_WIKIMEDIA);
159
        }
160
161
        // WARNINGS
162
163
        return $errorList;
164
    }
165
166
    /**
167
     * Summary of validateOther
168
     * @return ValidationError[]
169
     */
170
    public function validateOther()
171
    {
172
        $errorList = array();
173
174
        $trustedIp = $this->xffTrustProvider->getTrustedClientIp($this->request->getIp(),
175
            $this->request->getForwardedIp());
176
177
        // ERRORS
178
179
        // TOR nodes
180
        if ($this->torExitProvider->isTorExit($trustedIp)) {
181
            $errorList[ValidationError::BANNED] = new ValidationError(ValidationError::BANNED_TOR);
182
        }
183
184
        // Bans
185
        if ($this->banHelper->isBanned($this->request)) {
186
            $errorList[ValidationError::BANNED] = new ValidationError(ValidationError::BANNED);
187
        }
188
189
        // WARNINGS
190
191
        // Antispoof check
192
        $this->checkAntiSpoof();
193
194
        // Blacklist check
195
        $this->checkTitleBlacklist();
196
197
        return $errorList;
198
    }
199
200
    private function checkAntiSpoof()
201
    {
202
        try {
203
            if (count($this->antiSpoofProvider->getSpoofs($this->request->getName())) > 0) {
204
                // If there were spoofs an Admin should handle the request.
205
                $this->request->setStatus("Flagged users");
206
            }
207
        }
208
        catch (Exception $ex) {
209
            // logme
210
        }
211
    }
212
213
    private function checkTitleBlacklist()
214
    {
215
        if ($this->titleBlacklistEnabled == 1) {
216
            $apiResult = $this->httpHelper->get(
217
                $this->mediawikiApiEndpoint,
218
                array(
219
                    'action'       => 'titleblacklist',
220
                    'tbtitle'      => $this->request->getName(),
221
                    'tbaction'     => 'new-account',
222
                    'tbnooverride' => true,
223
                    'format'       => 'php',
224
                )
225
            );
226
227
            $data = unserialize($apiResult);
228
229
            $requestIsOk = $data['titleblacklist']['result'] == "ok";
230
231
            if (!$requestIsOk) {
232
                $this->request->setStatus("Flagged users");
233
            }
234
        }
235
    }
236
237
    private function userExists()
238
    {
239
        $userExists = $this->httpHelper->get(
240
            $this->mediawikiApiEndpoint,
241
            array(
242
                'action'  => 'query',
243
                'list'    => 'users',
244
                'ususers' => $this->request->getName(),
245
                'format'  => 'php',
246
            )
247
        );
248
249
        $ue = unserialize($userExists);
250
        if (!isset ($ue['query']['users']['0']['missing']) && isset ($ue['query']['users']['0']['userid'])) {
251
            return true;
252
        }
253
254
        return false;
255
    }
256
257
    private function userSulExists()
258
    {
259
        $requestName = $this->request->getName();
260
261
        $userExists = $this->httpHelper->get(
262
            $this->mediawikiApiEndpoint,
263
            array(
264
                'action'  => 'query',
265
                'meta'    => 'globaluserinfo',
266
                'guiuser' => $requestName,
267
                'format'  => 'php',
268
            )
269
        );
270
271
        $ue = unserialize($userExists);
272
        if (isset ($ue['query']['globaluserinfo']['id'])) {
273
            return true;
274
        }
275
276
        return false;
277
    }
278
279
    /**
280
     * Checks if a request with this name is currently open
281
     *
282
     * @return bool
283
     */
284
    private function nameRequestExists()
285
    {
286
        $query = "SELECT COUNT(id) FROM request WHERE status != 'Closed' AND name = :name;";
287
        $statement = $this->database->prepare($query);
288
        $statement->execute(array(':name' => $this->request->getName()));
289
290
        if (!$statement) {
291
            return false;
292
        }
293
294
        return $statement->fetchColumn() > 0;
295
    }
296
}
297