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

Request::getClosureDate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 14
ccs 0
cts 13
cp 0
rs 9.9332
cc 1
nc 1
nop 0
crap 2
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\DataObjects;
10
11
use DateTime;
12
use DateTimeImmutable;
13
use Exception;
14
use Waca\DataObject;
15
use Waca\Exceptions\OptimisticLockFailedException;
16
17
/**
18
 * Request data object
19
 *
20
 * This data object is the main request object.
21
 */
22
class Request extends DataObject
23
{
24
    private $email;
25
    private $ip;
26
    private $name;
27
    /** @var string|null */
28
    private $comment;
29
    private $status = "Open";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Open 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...
30
    private $date;
31
    private $emailsent = 0;
32
    private $emailconfirm;
33
    /** @var int|null */
34
    private $reserved = null;
35
    private $useragent;
36
    private $forwardedip;
37
    private $hasComments = false;
38
    private $hasCommentsResolved = false;
39
40
    /**
41
     * @throws Exception
42
     */
0 ignored issues
show
Coding Style introduced by
Expected 2 @throws tag(s) in function comment; 1 found
Loading history...
43
    public function save()
44
    {
45
        if ($this->isNew()) {
46
            // insert
47
            $statement = $this->dbObject->prepare(<<<SQL
48
INSERT INTO `request` (
49
	email, ip, name, comment, status, date, emailsent,
50
	emailconfirm, reserved, useragent, forwardedip
51
) VALUES (
52
	:email, :ip, :name, :comment, :status, CURRENT_TIMESTAMP(), :emailsent,
53
	:emailconfirm, :reserved, :useragent, :forwardedip
54
);
55
SQL
56
            );
57
            $statement->bindValue(':email', $this->email);
58
            $statement->bindValue(':ip', $this->ip);
59
            $statement->bindValue(':name', $this->name);
60
            $statement->bindValue(':comment', $this->comment);
61
            $statement->bindValue(':status', $this->status);
62
            $statement->bindValue(':emailsent', $this->emailsent);
63
            $statement->bindValue(':emailconfirm', $this->emailconfirm);
64
            $statement->bindValue(':reserved', $this->reserved);
65
            $statement->bindValue(':useragent', $this->useragent);
66
            $statement->bindValue(':forwardedip', $this->forwardedip);
67
68
            if ($statement->execute()) {
69
                $this->id = (int)$this->dbObject->lastInsertId();
70
            }
71
            else {
72
                throw new Exception($statement->errorInfo());
0 ignored issues
show
Bug introduced by
$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

72
                throw new Exception(/** @scrutinizer ignore-type */ $statement->errorInfo());
Loading history...
73
            }
74
        }
75
        else {
76
            // update
77
            $statement = $this->dbObject->prepare(<<<SQL
78
UPDATE `request` SET
79
	status = :status,
80
	emailsent = :emailsent,
81
	emailconfirm = :emailconfirm,
82
	reserved = :reserved,
83
	updateversion = updateversion + 1
84
WHERE id = :id AND updateversion = :updateversion
85
LIMIT 1;
86
SQL
87
            );
88
89
            $statement->bindValue(':id', $this->id);
90
            $statement->bindValue(':updateversion', $this->updateversion);
91
92
            $statement->bindValue(':status', $this->status);
93
            $statement->bindValue(':emailsent', $this->emailsent);
94
            $statement->bindValue(':emailconfirm', $this->emailconfirm);
95
            $statement->bindValue(':reserved', $this->reserved);
96
97
            if (!$statement->execute()) {
98
                throw new Exception($statement->errorInfo());
99
            }
100
101
            if ($statement->rowCount() !== 1) {
102
                throw new OptimisticLockFailedException();
103
            }
104
105
            $this->updateversion++;
106
        }
107
    }
0 ignored issues
show
Coding Style introduced by
Expected //end save()
Loading history...
108
109
    /**
110
     * @return string
111
     */
112
    public function getIp()
113
    {
114
        return $this->ip;
115
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getIp()
Loading history...
116
117
    /**
118
     * @param string $ip
119
     */
120
    public function setIp($ip)
121
    {
122
        $this->ip = $ip;
123
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setIp()
Loading history...
124
125
    /**
126
     * @return string
127
     */
128
    public function getName()
129
    {
130
        return $this->name;
131
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getName()
Loading history...
132
133
    /**
134
     * @param string $name
135
     */
136
    public function setName($name)
137
    {
138
        $this->name = $name;
139
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setName()
Loading history...
140
141
    /**
142
     * @return string|null
143
     */
144
    public function getComment()
145
    {
146
        return $this->comment;
147
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getComment()
Loading history...
148
149
    /**
150
     * @param string $comment
151
     */
152
    public function setComment($comment)
153
    {
154
        $this->comment = $comment;
155
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setComment()
Loading history...
156
157
    /**
158
     * @return string
159
     */
160
    public function getStatus()
161
    {
162
        return $this->status;
163
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getStatus()
Loading history...
164
165
    /**
166
     * @param string $status
167
     */
168
    public function setStatus($status)
169
    {
170
        $this->status = $status;
171
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setStatus()
Loading history...
172
173
    /**
174
     * Returns the time the request was first submitted
175
     *
176
     * @return DateTimeImmutable
177
     */
178
    public function getDate()
179
    {
180
        return new DateTimeImmutable($this->date);
181
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getDate()
Loading history...
182
183
    /**
184
     * @return bool
185
     */
186
    public function getEmailSent()
187
    {
188
        return $this->emailsent == "1";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal 1 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...
189
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getEmailSent()
Loading history...
190
191
    /**
192
     * @param bool $emailSent
193
     */
194
    public function setEmailSent($emailSent)
195
    {
196
        $this->emailsent = $emailSent ? 1 : 0;
197
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setEmailSent()
Loading history...
198
199
    /**
200
     * @return int|null
201
     */
202
    public function getReserved()
203
    {
204
        return $this->reserved;
205
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getReserved()
Loading history...
206
207
    /**
208
     * @param int|null $reserved
209
     */
210
    public function setReserved($reserved)
211
    {
212
        $this->reserved = $reserved;
213
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setReserved()
Loading history...
214
215
    /**
216
     * @return string
217
     */
218
    public function getUserAgent()
219
    {
220
        return $this->useragent;
221
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getUserAgent()
Loading history...
222
223
    /**
224
     * @param string $useragent
225
     */
226
    public function setUserAgent($useragent)
227
    {
228
        $this->useragent = $useragent;
229
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setUserAgent()
Loading history...
230
231
    /**
232
     * @return string|null
233
     */
234
    public function getForwardedIp()
235
    {
236
        return $this->forwardedip;
237
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getForwardedIp()
Loading history...
238
239
    /**
240
     * @param string|null $forwardedip
241
     */
242
    public function setForwardedIp($forwardedip)
243
    {
244
        $this->forwardedip = $forwardedip;
245
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setForwardedIp()
Loading history...
246
247
    /**
248
     * @return bool
249
     */
250
    public function hasComments()
251
    {
252
        if ($this->hasCommentsResolved) {
253
            return $this->hasComments;
254
        }
255
256
        if ($this->comment != "") {
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal 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...
257
            $this->hasComments = true;
258
            $this->hasCommentsResolved = true;
259
260
            return true;
261
        }
262
263
        $commentsQuery = $this->dbObject->prepare("SELECT COUNT(*) AS num FROM comment WHERE request = :id;");
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal SELECT COUNT(*) AS num F...nt WHERE request = :id; 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...
264
        $commentsQuery->bindValue(":id", $this->id);
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal :id 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...
265
266
        $commentsQuery->execute();
267
268
        $this->hasComments = ($commentsQuery->fetchColumn() != 0);
269
        $this->hasCommentsResolved = true;
270
271
        return $this->hasComments;
272
    }
0 ignored issues
show
Coding Style introduced by
Expected //end hasComments()
Loading history...
273
274
    /**
275
     * @return string
276
     */
277
    public function getEmailConfirm()
278
    {
279
        return $this->emailconfirm;
280
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getEmailConfirm()
Loading history...
281
282
    /**
283
     * @param string $emailconfirm
284
     */
285
    public function setEmailConfirm($emailconfirm)
286
    {
287
        $this->emailconfirm = $emailconfirm;
288
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setEmailConfirm()
Loading history...
289
290
    public function generateEmailConfirmationHash()
291
    {
292
        $this->emailconfirm = bin2hex(openssl_random_pseudo_bytes(16));
293
    }
0 ignored issues
show
Coding Style introduced by
Expected //end generateEmailConfirmationHash()
Loading history...
294
295
    /**
296
     * @return string|null
297
     */
298
    public function getEmail()
299
    {
300
        return $this->email;
301
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getEmail()
Loading history...
302
303
    /**
304
     * @param string|null $email
305
     */
306
    public function setEmail($email)
307
    {
308
        $this->email = $email;
309
    }
0 ignored issues
show
Coding Style introduced by
Expected //end setEmail()
Loading history...
310
311
    /**
312
     * @return string
313
     * @throws Exception
314
     */
315
    public function getClosureReason()
316
    {
317
        if ($this->status != 'Closed') {
318
            throw new Exception("Can't get closure reason for open request.");
319
        }
320
321
        $statement = $this->dbObject->prepare(<<<SQL
322
SELECT closes.mail_desc
323
FROM log
324
INNER JOIN closes ON log.action = closes.closes
325
WHERE log.objecttype = 'Request'
326
AND log.objectid = :requestId
327
AND log.action LIKE 'Closed%'
328
ORDER BY log.timestamp DESC
329
LIMIT 1;
330
SQL
331
        );
332
333
        $statement->bindValue(":requestId", $this->id);
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal :requestId 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...
334
        $statement->execute();
335
        $reason = $statement->fetchColumn();
336
337
        return $reason;
338
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getClosureReason()
Loading history...
339
340
    /**
341
     * Gets a value indicating whether the request was closed as created or not.
342
     */
0 ignored issues
show
Coding Style Documentation introduced by
Missing @throws tag in function comment
Loading history...
343
    public function getWasCreated()
344
    {
345
        if ($this->status != 'Closed') {
346
            throw new Exception("Can't get closure reason for open request.");
347
        }
348
349
        $statement = $this->dbObject->prepare(<<<SQL
350
SELECT emailtemplate.oncreated, log.action
351
FROM log
352
LEFT JOIN emailtemplate ON CONCAT('Closed ', emailtemplate.id) = log.action
353
WHERE log.objecttype = 'Request'
354
AND log.objectid = :requestId
355
AND log.action LIKE 'Closed%'
356
ORDER BY log.timestamp DESC
357
LIMIT 1;
358
SQL
359
        );
360
361
        $statement->bindValue(":requestId", $this->id);
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal :requestId 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...
362
        $statement->execute();
363
        $onCreated = $statement->fetchColumn(0);
364
        $logAction = $statement->fetchColumn(1);
365
        $statement->closeCursor();
366
367
        if ($onCreated === null) {
368
            return $logAction === "Closed custom-y";
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Closed custom-y 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...
369
        }
370
371
        return (bool)$onCreated;
372
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getWasCreated()
Loading history...
373
374
    /**
375
     * @return DateTime
376
     */
377
    public function getClosureDate()
378
    {
379
        $logQuery = $this->dbObject->prepare(<<<SQL
380
SELECT timestamp FROM log
381
WHERE objectid = :request AND objecttype = 'Request' AND action LIKE 'Closed%'
382
ORDER BY timestamp DESC LIMIT 1;
383
SQL
384
        );
385
        $logQuery->bindValue(":request", $this->getId());
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal :request 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...
386
        $logQuery->execute();
387
        $logTime = $logQuery->fetchColumn();
388
        $logQuery->closeCursor();
389
390
        return new DateTime($logTime);
391
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getClosureDate()
Loading history...
392
393
    /**
394
     * Returns a hash based on data within this request which can be generated easily from the data to be used to reveal
395
     * data to unauthorised* users.
396
     *
397
     * *:Not tool admins, check users, or the reserving user.
398
     *
399
     * @return string
400
     *
401
     * @todo future work to make invalidation better. Possibly move to the database and invalidate on relevant events?
402
     *       Maybe depend on the last logged action timestamp?
403
     */
404
    public function getRevealHash()
405
    {
406
        $data = $this->id         // unique per request
407
            . '|' . $this->ip           // }
408
            . '|' . $this->forwardedip  // } private data not known to those without access
409
            . '|' . $this->useragent    // }
410
            . '|' . $this->email        // }
411
            . '|' . $this->status;      // to rudimentarily invalidate the token on status change
412
413
        return hash('sha256', $data);
414
    }
0 ignored issues
show
Coding Style introduced by
Expected //end getRevealHash()
Loading history...
415
}
0 ignored issues
show
Coding Style introduced by
Expected //end class
Loading history...
416