Issues (186)

Branch: manual-account-multidomain

includes/DataObjects/Ban.php (2 issues)

1
<?php
2
/******************************************************************************
3
 * Wikipedia Account Creation Assistance tool                                 *
4
 * ACC Development Team. Please see team.json for a list of contributors.     *
5
 *                                                                            *
6
 * This is free and unencumbered software released into the public domain.    *
7
 * Please see LICENSE.md for the full licencing statement.                    *
8
 ******************************************************************************/
9
10
namespace Waca\DataObjects;
11
12
use Exception;
13
use PDO;
14
use Waca\DataObject;
15
use Waca\Exceptions\OptimisticLockFailedException;
16
use Waca\PdoDatabase;
17
18
/**
19
 * Ban data object
20
 */
21
class Ban extends DataObject
22
{
23
    const ACTION_BLOCK = 'block';
24
    const ACTION_DROP = 'drop';
25
    const ACTION_DEFER = 'defer';
26
    const ACTION_NONE = 'none';
27
28
    /** @var string|null */
29
    private $name;
30
    /** @var string|null */
31
    private $ip;
32
    /** @var int|null */
33
    private $ipmask;
34
    /** @var string|null */
35
    private $email;
36
    /** @var string|null */
37
    private $useragent;
38
39
    private $user;
40
    private $reason;
41
    private $date;
42
    private $duration;
43
    private $active;
44
    private $action = self::ACTION_BLOCK;
45
    private $targetqueue;
46
    private $visibility = 'user';
47
    private ?int $domain;
48
49
    /**
50
     * Gets all active bans, filtered by the optional target.
51
     *
52
     * @return Ban[]
53
     */
54
    public static function getActiveBans(PdoDatabase $database, int $domain)
55
    {
56
        $query = <<<SQL
57
SELECT * FROM ban 
58
WHERE (duration > UNIX_TIMESTAMP() OR duration is null) 
59
    AND active = 1
60
    AND (domain IS NULL OR domain = :domain);
61
SQL;
62
        $statement = $database->prepare($query);
63
        $statement->execute([':domain' => $domain]);
64
        $result = array();
65
66
        /** @var Ban $v */
67
        foreach ($statement->fetchAll(PDO::FETCH_CLASS, get_called_class()) as $v) {
68
            $v->setDatabase($database);
69
            $result[] = $v;
70
        }
71
72
        return $result;
73
    }
74
75
    /**
76
     * Gets a ban by its ID if it's currently active.
77
     *
78
     * @return Ban|false
79
     */
80
    public static function getActiveId($id, PdoDatabase $database, int $domain)
81
    {
82
        $statement = $database->prepare(<<<SQL
83
SELECT *
84
FROM ban
85
WHERE id = :id  
86
  AND (domain IS NULL OR domain = :domain)
87
  AND (duration > UNIX_TIMESTAMP() OR duration is null) 
88
  AND active = 1;
89
SQL
90
        );
91
        $statement->bindValue(":id", $id);
92
        $statement->bindValue(":domain", $domain);
93
94
        $statement->execute();
95
96
        $resultObject = $statement->fetchObject(get_called_class());
97
98
        if ($resultObject !== false) {
99
            $resultObject->setDatabase($database);
100
        }
101
102
        return $resultObject;
103
    }
104
105
    public static function getByIdList($values, PdoDatabase $database, int $domain): array
106
    {
107
        if (count($values) === 0) {
108
            return [];
109
        }
110
111
        // use the provided array to produce a list of question marks of the same length as the array.
112
        $valueCount = count($values);
113
        $inSection = str_repeat('?,', $valueCount - 1) . '?';
114
115
        // this is still parameterised! It's using positional parameters instead of named ones.
116
        $query = 'SELECT * FROM ban WHERE id IN (' . $inSection . ')';
117
118
        $query .= ' AND (domain IS NULL OR domain = ?)';
119
        $values[] = $domain;
120
121
        $statement = $database->prepare($query);
122
123
        // execute the statement with the provided parameter list.
124
        $statement->execute($values);
125
126
        $result = [];
127
        foreach ($statement->fetchAll(PDO::FETCH_CLASS, get_called_class()) as $v) {
128
            $v->setDatabase($database);
129
            $result[] = $v;
130
        }
131
132
        return $result;
133
    }
134
135
    /**
136
     * @throws Exception
137
     */
138
    public function save()
139
    {
140
        if ($this->isNew()) {
141
            // insert
142
            $statement = $this->dbObject->prepare(<<<SQL
143
INSERT INTO `ban` (name, email, ip, ipmask, useragent, user, reason, date, duration, active, action, targetqueue, visibility, domain)
144
VALUES (:name, :email, :ip, :ipmask, :useragent, :user, :reason, CURRENT_TIMESTAMP(), :duration, :active, :action, :targetqueue, :visibility, :domain);
145
SQL
146
            );
147
148
            $statement->bindValue(":name", $this->name);
149
            $statement->bindValue(":email", $this->email);
150
            $statement->bindValue(":ip", $this->ip);
151
            $statement->bindValue(":ipmask", $this->ipmask);
152
            $statement->bindValue(":useragent", $this->useragent);
153
154
            $statement->bindValue(":user", $this->user);
155
            $statement->bindValue(":reason", $this->reason);
156
            $statement->bindValue(":duration", $this->duration);
157
            $statement->bindValue(":active", $this->active);
158
            $statement->bindValue(":action", $this->action);
159
            $statement->bindValue(":targetqueue", $this->targetqueue);
160
            $statement->bindValue(":visibility", $this->visibility);
161
            $statement->bindValue(":domain", $this->domain);
162
163
            if ($statement->execute()) {
164
                $this->id = (int)$this->dbObject->lastInsertId();
165
            }
166
            else {
167
                throw new Exception($statement->errorInfo());
0 ignored issues
show
$statement->errorInfo() of type array is incompatible with the type string expected by parameter $message of Exception::__construct(). ( Ignorable by Annotation )

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

167
                throw new Exception(/** @scrutinizer ignore-type */ $statement->errorInfo());
Loading history...
168
            }
169
        }
170
        else {
171
            // update
172
            $statement = $this->dbObject->prepare(<<<SQL
173
UPDATE `ban`
174
SET active = :active, updateversion = updateversion + 1
175
WHERE id = :id AND updateversion = :updateversion;
176
SQL
177
            );
178
            $statement->bindValue(':id', $this->id);
179
            $statement->bindValue(':updateversion', $this->updateversion);
180
181
            $statement->bindValue(':active', $this->active);
182
183
            if (!$statement->execute()) {
184
                throw new Exception($statement->errorInfo());
185
            }
186
187
            if ($statement->rowCount() !== 1) {
188
                throw new OptimisticLockFailedException();
189
            }
190
191
            $this->updateversion++;
192
        }
193
    }
194
195
    /**
196
     * @return string
197
     */
198
    public function getReason()
199
    {
200
        return $this->reason;
201
    }
202
203
    /**
204
     * @param string $reason
205
     */
206
    public function setReason($reason)
207
    {
208
        $this->reason = $reason;
209
    }
210
211
    /**
212
     * @return mixed
213
     */
214
    public function getDate()
215
    {
216
        return $this->date;
217
    }
218
219
    /**
220
     * @return mixed
221
     */
222
    public function getDuration()
223
    {
224
        return $this->duration;
225
    }
226
227
    /**
228
     * @param mixed $duration
229
     */
230
    public function setDuration($duration)
231
    {
232
        $this->duration = $duration;
233
    }
234
235
    /**
236
     * @return bool
237
     */
238
    public function isActive()
239
    {
240
        return $this->active == 1;
241
    }
242
243
    /**
244
     * @param bool $active
245
     */
246
    public function setActive($active)
247
    {
248
        $this->active = $active ? 1 : 0;
249
    }
250
251
    /**
252
     * @return int
253
     */
254
    public function getUser()
255
    {
256
        return $this->user;
257
    }
258
259
    /**
260
     * @param int $user UserID of user who is setting the ban
261
     */
262
    public function setUser($user)
263
    {
264
        $this->user = $user;
265
    }
266
267
    /**
268
     * @return string
269
     */
270
    public function getAction(): string
271
    {
272
        return $this->action;
273
    }
274
275
    /**
276
     * @param string $action
277
     */
278
    public function setAction(string $action): void
279
    {
280
        $this->action = $action;
281
    }
282
283
    /**
284
     * @return string
285
     */
286
    public function getVisibility() : string
287
    {
288
        return $this->visibility;
289
    }
290
291
    /**
292
     * @param string $visibility
293
     */
294
    public function setVisibility(string $visibility): void
295
    {
296
        $this->visibility = $visibility;
297
    }
298
299
    /**
300
     * @return string|null
301
     */
302
    public function getName(): ?string
303
    {
304
        return $this->name;
305
    }
306
307
    /**
308
     * @param string|null $name
309
     */
310
    public function setName(?string $name): void
311
    {
312
        $this->name = $name;
313
    }
314
315
    /**
316
     * @return string|null
317
     */
318
    public function getIp(): ?string
319
    {
320
        if ($this->ip === null) {
321
            return null;
322
        }
323
324
        return inet_ntop($this->ip);
325
    }
326
327
    /**
328
     * @return int|null
329
     */
330
    public function getIpMask(): ?int
331
    {
332
        return $this->ipmask;
333
    }
334
335
    /**
336
     * @param string|null $ip
337
     * @param int|null    $mask
338
     */
339
    public function setIp(?string $ip, ?int $mask): void
340
    {
341
        if ($ip === null) {
342
            $this->ip = null;
343
        }
344
        else {
345
            $this->ip = inet_pton($ip);
346
        }
347
348
        $this->ipmask = $mask;
349
    }
350
351
    /**
352
     * @return string|null
353
     */
354
    public function getEmail(): ?string
355
    {
356
        return $this->email;
357
    }
358
359
    /**
360
     * @param string|null $email
361
     */
362
    public function setEmail(?string $email): void
363
    {
364
        $this->email = $email;
365
    }
366
367
    /**
368
     * @return string|null
369
     */
370
    public function getUseragent(): ?string
371
    {
372
        return $this->useragent;
373
    }
374
375
    /**
376
     * @param string|null $useragent
377
     */
378
    public function setUseragent(?string $useragent): void
379
    {
380
        $this->useragent = $useragent;
381
    }
382
383
    /**
384
     * @return int|null
385
     */
386
    public function getTargetQueue(): ?int
387
    {
388
        return $this->targetqueue;
389
    }
390
391
    /**
392
     * @return RequestQueue|null
393
     */
394
    public function getTargetQueueObject(): ?RequestQueue
395
    {
396
        /** @var RequestQueue $queue */
397
        $queue = RequestQueue::getById($this->targetqueue, $this->getDatabase());
398
        return $queue === false ? null : $queue;
0 ignored issues
show
The condition $queue === false is always false.
Loading history...
399
    }
400
401
    /**
402
     * @param int|null $targetQueue
403
     */
404
    public function setTargetQueue(?int $targetQueue): void
405
    {
406
        $this->targetqueue = $targetQueue;
407
    }
408
409
    public function setDomain(?int $domain): void
410
    {
411
        $this->domain = $domain;
412
    }
413
414
    public function getDomain(): ?int
415
    {
416
        return $this->domain;
417
    }
418
}
419