Passed
Push — master ( 2e7a9d...4cf540 )
by MusikAnimal
07:19
created

User::isBlocked()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file contains only the User class.
4
 */
5
6
declare(strict_types = 1);
7
8
namespace AppBundle\Model;
9
10
use DateTime;
11
use Exception;
12
13
/**
14
 * A User is a wiki user who has the same username across all projects in an XTools installation.
15
 */
16
class User extends Model
17
{
18
    /** @var int The user's ID. */
19
    protected $id;
20
21
    /** @var string The user's username. */
22
    protected $username;
23
24
    /** @var DateTime|bool Expiry of the current block of the user. */
25
    protected $blockExpiry;
26
27
    /** @var int Quick cache of edit counts, keyed by project domain. */
28
    protected $editCounts = [];
29
30
    /**
31
     * Create a new User given a username.
32
     * @param string $username
33
     */
34 62
    public function __construct(string $username)
35
    {
36 62
        $this->username = ucfirst(str_replace('_', ' ', trim($username)));
37
38
        // IPv6 address are stored as uppercase in the database.
39 62
        if ($this->isAnon()) {
40 6
            $this->username = strtoupper($this->username);
41
        }
42 62
    }
43
44
    /**
45
     * Get the username.
46
     * @return string
47
     */
48 16
    public function getUsername(): string
49
    {
50 16
        return $this->username;
51
    }
52
53
    /**
54
     * Unique identifier for this User, to be used in cache keys. Use of md5 ensures the cache key does not contain
55
     * reserved characters. You could also use the ID, but that may require an unnecessary DB query.
56
     * @see Repository::getCacheKey()
57
     * @return string
58
     */
59 1
    public function getCacheKey(): string
60
    {
61 1
        return md5($this->username);
62
    }
63
64
    /**
65
     * Get the user's ID on the given project.
66
     * @param Project $project
67
     * @return int
68
     */
69 1
    public function getId(Project $project): int
70
    {
71 1
        $ret = $this->getRepository()->getIdAndRegistration(
0 ignored issues
show
Bug introduced by
The method getIdAndRegistration() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\UserRepository. ( Ignorable by Annotation )

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

71
        $ret = $this->getRepository()->/** @scrutinizer ignore-call */ getIdAndRegistration(
Loading history...
72 1
            $project->getDatabaseName(),
73 1
            $this->getUsername()
74
        );
75
76 1
        return (int)$ret['userId'];
77
    }
78
79
    /**
80
     * Get the user's registration date on the given project.
81
     * @param Project $project
82
     * @return DateTime|null null if no registration date was found.
83
     */
84 1
    public function getRegistrationDate(Project $project): ?DateTime
85
    {
86 1
        $ret = $this->getRepository()->getIdAndRegistration(
87 1
            $project->getDatabaseName(),
88 1
            $this->getUsername()
89
        );
90
91 1
        return null !== $ret['regDate']
92 1
            ? DateTime::createFromFormat('YmdHis', $ret['regDate'])
93 1
            : null;
94
    }
95
96
    /**
97
     * Get a user's local user rights on the given Project.
98
     * @param Project $project
99
     * @return string[]
100
     */
101 3
    public function getUserRights(Project $project): array
102
    {
103 3
        return $this->getRepository()->getUserRights($project, $this);
0 ignored issues
show
Bug introduced by
The method getUserRights() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\UserRepository. ( Ignorable by Annotation )

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

103
        return $this->getRepository()->/** @scrutinizer ignore-call */ getUserRights($project, $this);
Loading history...
104
    }
105
106
    /**
107
     * Get a list of this user's global rights.
108
     * @param Project $project A project to query; if not provided, the default will be used.
109
     * @return string[]
110
     */
111 1
    public function getGlobalUserRights(?Project $project = null): array
112
    {
113 1
        return $this->getRepository()->getGlobalUserRights($this->getUsername(), $project);
0 ignored issues
show
Bug introduced by
The method getGlobalUserRights() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\UserRepository. ( Ignorable by Annotation )

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

113
        return $this->getRepository()->/** @scrutinizer ignore-call */ getGlobalUserRights($this->getUsername(), $project);
Loading history...
114
    }
115
116
    /**
117
     * Get the user's (system) edit count.
118
     * @param Project $project
119
     * @return int
120
     */
121 2
    public function getEditCount(Project $project): int
122
    {
123 2
        $domain = $project->getDomain();
124 2
        if (isset($this->editCounts[$domain])) {
125 1
            return $this->editCounts[$domain];
126
        }
127
128 2
        $this->editCounts[$domain] = (int) $this->getRepository()->getEditCount(
0 ignored issues
show
Bug introduced by
The method getEditCount() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\UserRepository. ( Ignorable by Annotation )

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

128
        $this->editCounts[$domain] = (int) $this->getRepository()->/** @scrutinizer ignore-call */ getEditCount(
Loading history...
129 2
            $project->getDatabaseName(),
130 2
            $this->getUsername()
131
        );
132
133 2
        return $this->editCounts[$domain];
134
    }
135
136
    /**
137
     * Maximum number of edits to process, based on configuration.
138
     * @return int
139
     */
140 1
    public function maxEdits(): int
141
    {
142 1
        return $this->getRepository()->maxEdits();
0 ignored issues
show
Bug introduced by
The method maxEdits() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\UserRepository. ( Ignorable by Annotation )

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

142
        return $this->getRepository()->/** @scrutinizer ignore-call */ maxEdits();
Loading history...
143
    }
144
145
    /**
146
     * Does this user exist on the given project.
147
     * @param Project $project
148
     * @return bool
149
     */
150
    public function existsOnProject(Project $project): bool
151
    {
152
        $id = $this->getId($project);
153
        return $id > 0;
154
    }
155
156
    /**
157
     * Is this user an Administrator on the given project?
158
     * @param Project $project The project.
159
     * @return bool
160
     */
161 2
    public function isAdmin(Project $project): bool
162
    {
163 2
        return false !== array_search('sysop', $this->getUserRights($project));
164
    }
165
166
    /**
167
     * Is this user an anonymous user (IP)?
168
     * @return bool
169
     */
170 62
    public function isAnon(): bool
171
    {
172 62
        return (bool) filter_var($this->username, FILTER_VALIDATE_IP);
173
    }
174
175
    /**
176
     * Get the expiry of the current block on the user
177
     * @param Project $project The project.
178
     * @return DateTime|bool Expiry as DateTime, true if indefinite, or false if they are not blocked.
179
     */
180 2
    public function getBlockExpiry(Project $project)
181
    {
182 2
        if (isset($this->blockExpiry)) {
183
            return $this->blockExpiry;
184
        }
185
186 2
        $expiry = $this->getRepository()->getBlockExpiry(
0 ignored issues
show
Bug introduced by
The method getBlockExpiry() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\UserRepository. ( Ignorable by Annotation )

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

186
        $expiry = $this->getRepository()->/** @scrutinizer ignore-call */ getBlockExpiry(
Loading history...
187 2
            $project->getDatabaseName(),
188 2
            $this->getUsername()
189
        );
190
191 2
        if ('infinity' === $expiry) {
192 1
            $this->blockExpiry = true;
193 1
        } elseif (false === $expiry) {
194
            $this->blockExpiry = false;
195
        } else {
196 1
            $this->blockExpiry = new DateTime($expiry);
197
        }
198
199 2
        return $this->blockExpiry;
200
    }
201
202
    /**
203
     * Is this user currently blocked on the given project?
204
     * @param Project $project The project.
205
     * @return bool
206
     */
207 1
    public function isBlocked(Project $project): bool
208
    {
209 1
        return false !== $this->getBlockExpiry($project);
210
    }
211
212
    /**
213
     * Does the user have more edits than maximum amount allowed for processing?
214
     * @param Project $project
215
     * @return bool
216
     */
217 1
    public function hasTooManyEdits(Project $project): bool
218
    {
219 1
        $editCount = $this->getEditCount($project);
220 1
        return $this->maxEdits() > 0 && $editCount > $this->maxEdits();
221
    }
222
223
    /**
224
     * Get edit count within given timeframe and namespace
225
     * @param Project $project
226
     * @param int|string $namespace Namespace ID or 'all' for all namespaces
227
     * @param string $start Start date in a format accepted by strtotime()
228
     * @param string $end End date in a format accepted by strtotime()
229
     * @return int
230
     */
231 2
    public function countEdits(Project $project, $namespace = 'all', $start = '', $end = ''): int
232
    {
233 2
        return (int) $this->getRepository()->countEdits($project, $this, $namespace, $start, $end);
0 ignored issues
show
Bug introduced by
The method countEdits() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\UserRepository. ( Ignorable by Annotation )

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

233
        return (int) $this->getRepository()->/** @scrutinizer ignore-call */ countEdits($project, $this, $namespace, $start, $end);
Loading history...
234
    }
235
236
    /**
237
     * Is this user the same as the current XTools user?
238
     * @return bool
239
     */
240 2
    public function isCurrentlyLoggedIn(): bool
241
    {
242
        try {
243 2
            $ident = $this->getRepository()->getXtoolsUserInfo();
0 ignored issues
show
Bug introduced by
The method getXtoolsUserInfo() does not exist on AppBundle\Repository\Repository. It seems like you code against a sub-type of AppBundle\Repository\Repository such as AppBundle\Repository\UserRepository. ( Ignorable by Annotation )

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

243
            $ident = $this->getRepository()->/** @scrutinizer ignore-call */ getXtoolsUserInfo();
Loading history...
244 2
        } catch (Exception $exception) {
245 2
            return false;
246
        }
247
        return isset($ident->username) && $ident->username === $this->getUsername();
248
    }
249
}
250