Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 72 |
|
0.00% |
0 / 28 |
CRAP | |
0.00% |
0 / 1 |
GlobalRenameRequest | |
0.00% |
0 / 72 |
|
0.00% |
0 / 28 |
1482 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getWiki | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getNewName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getReason | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRequested | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getStatus | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getCompleted | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getDeleted | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getPerformer | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getComments | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setId | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
setName | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setWiki | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setNewName | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
setReason | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setRequested | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setStatus | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setCompleted | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setDeleted | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setPerformer | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setComments | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
exists | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isPending | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
userIsGlobal | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
importRow | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
2 | |||
isNameAvailable | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
90 |
1 | <?php |
2 | /** |
3 | * @section LICENSE |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License along |
15 | * with this program; if not, write to the Free Software Foundation, Inc., |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
17 | * http://www.gnu.org/copyleft/gpl.html |
18 | * |
19 | * @file |
20 | */ |
21 | |
22 | namespace MediaWiki\Extension\CentralAuth\GlobalRename; |
23 | |
24 | use BadMethodCallException; |
25 | use IDBAccessObject; |
26 | use InvalidArgumentException; |
27 | use MediaWiki\Extension\CentralAuth\CentralAuthServices; |
28 | use MediaWiki\Extension\CentralAuth\User\CentralAuthUser; |
29 | use MediaWiki\MediaWikiServices; |
30 | use MediaWiki\Status\Status; |
31 | use MediaWiki\User\UserNameUtils; |
32 | use stdClass; |
33 | |
34 | /** |
35 | * Data access object for global rename requests. |
36 | * |
37 | * @author Bryan Davis <bd808@wikimedia.org> |
38 | * @copyright © 2014 Bryan Davis and Wikimedia Foundation. |
39 | */ |
40 | class GlobalRenameRequest { |
41 | |
42 | /** @var UserNameUtils */ |
43 | private $userNameUtils; |
44 | |
45 | public const PENDING = 'pending'; |
46 | public const APPROVED = 'approved'; |
47 | public const REJECTED = 'rejected'; |
48 | |
49 | /** @var int|null */ |
50 | protected $id; |
51 | /** @var string|null */ |
52 | protected $name; |
53 | /** @var string|null */ |
54 | protected $wiki; |
55 | /** @var string|null */ |
56 | protected $newName; |
57 | /** @var string|null */ |
58 | protected $reason; |
59 | /** @var string|null */ |
60 | protected $requested; |
61 | /** @var string|null */ |
62 | protected $status; |
63 | /** @var string|null */ |
64 | protected $completed; |
65 | /** @var int */ |
66 | protected $deleted = 0; |
67 | /** @var int|null */ |
68 | protected $performer; |
69 | /** @var string|null */ |
70 | protected $comments; |
71 | |
72 | /** |
73 | * @internal Use GlobalRenameRequestStore::newBlankRequest instead |
74 | * @param UserNameUtils $userNameUtils |
75 | */ |
76 | public function __construct( UserNameUtils $userNameUtils ) { |
77 | $this->userNameUtils = $userNameUtils; |
78 | } |
79 | |
80 | /** |
81 | * @return int |
82 | */ |
83 | public function getId() { |
84 | return $this->id; |
85 | } |
86 | |
87 | /** |
88 | * @return string Requesting user's name |
89 | */ |
90 | public function getName() { |
91 | return $this->name; |
92 | } |
93 | |
94 | /** |
95 | * @return string Requesting user's home wiki or null if CentralAuth user |
96 | */ |
97 | public function getWiki() { |
98 | return $this->wiki; |
99 | } |
100 | |
101 | /** |
102 | * @return string |
103 | */ |
104 | public function getNewName() { |
105 | return $this->newName; |
106 | } |
107 | |
108 | /** |
109 | * @return string User's reason for requesting rename |
110 | */ |
111 | public function getReason() { |
112 | return $this->reason; |
113 | } |
114 | |
115 | /** |
116 | * @return string MW timestamp that request was made |
117 | */ |
118 | public function getRequested() { |
119 | return $this->requested; |
120 | } |
121 | |
122 | /** |
123 | * @return string |
124 | */ |
125 | public function getStatus() { |
126 | return $this->status; |
127 | } |
128 | |
129 | /** |
130 | * @return string MW timestamp that request was processed |
131 | */ |
132 | public function getCompleted() { |
133 | return $this->completed; |
134 | } |
135 | |
136 | /** |
137 | * @return int Protection flags |
138 | */ |
139 | public function getDeleted() { |
140 | return $this->deleted; |
141 | } |
142 | |
143 | /** |
144 | * @return int CentralAuth user id of the user who processed the request |
145 | */ |
146 | public function getPerformer() { |
147 | return $this->performer; |
148 | } |
149 | |
150 | /** |
151 | * @return string |
152 | */ |
153 | public function getComments() { |
154 | return $this->comments; |
155 | } |
156 | |
157 | /** |
158 | * @param int $id |
159 | */ |
160 | public function setId( int $id ) { |
161 | if ( $this->id !== null ) { |
162 | throw new BadMethodCallException( "Can't replace id when already set" ); |
163 | } |
164 | |
165 | $this->id = $id; |
166 | } |
167 | |
168 | /** |
169 | * @param string $name |
170 | * @return GlobalRenameRequest self, for message chaining |
171 | */ |
172 | public function setName( $name ) { |
173 | $this->name = $name; |
174 | return $this; |
175 | } |
176 | |
177 | /** |
178 | * @param string $wiki |
179 | * @return GlobalRenameRequest self, for message chaining |
180 | */ |
181 | public function setWiki( $wiki ) { |
182 | $this->wiki = $wiki; |
183 | return $this; |
184 | } |
185 | |
186 | /** |
187 | * @param string $newName |
188 | * @return GlobalRenameRequest self, for message chaining |
189 | */ |
190 | public function setNewName( $newName ) { |
191 | $canonicalName = $this->userNameUtils->getCanonical( $newName, UserNameUtils::RIGOR_CREATABLE ); |
192 | if ( $canonicalName === false ) { |
193 | throw new InvalidArgumentException( "Invalid username '{$newName}'" ); |
194 | } |
195 | $this->newName = $canonicalName; |
196 | return $this; |
197 | } |
198 | |
199 | /** |
200 | * @param string $reason |
201 | * @return GlobalRenameRequest self, for message chaining |
202 | */ |
203 | public function setReason( $reason ) { |
204 | $this->reason = $reason; |
205 | return $this; |
206 | } |
207 | |
208 | /** |
209 | * @param string|null $requested MW timestamp, null for now |
210 | * @return GlobalRenameRequest self, for message chaining |
211 | */ |
212 | public function setRequested( $requested = null ) { |
213 | $this->requested = $requested ?? wfTimestampNow(); |
214 | return $this; |
215 | } |
216 | |
217 | /** |
218 | * @param string $status |
219 | * @return GlobalRenameRequest self, for message chaining |
220 | */ |
221 | public function setStatus( $status ) { |
222 | $this->status = $status; |
223 | return $this; |
224 | } |
225 | |
226 | /** |
227 | * @param string|null $completed MW timestamp, null for now |
228 | * @return GlobalRenameRequest self, for message chaining |
229 | */ |
230 | public function setCompleted( $completed = null ) { |
231 | $this->completed = $completed ?? wfTimestampNow(); |
232 | return $this; |
233 | } |
234 | |
235 | /** |
236 | * @param int $deleted Bitmask |
237 | * @return GlobalRenameRequest self, for message chaining |
238 | */ |
239 | public function setDeleted( $deleted ) { |
240 | $this->deleted = $deleted; |
241 | return $this; |
242 | } |
243 | |
244 | /** |
245 | * @param int $performer |
246 | * @return GlobalRenameRequest self, for message chaining |
247 | */ |
248 | public function setPerformer( $performer ) { |
249 | $this->performer = $performer; |
250 | return $this; |
251 | } |
252 | |
253 | /** |
254 | * @param string $comments |
255 | * @return GlobalRenameRequest self, for message chaining |
256 | */ |
257 | public function setComments( $comments ) { |
258 | $this->comments = $comments; |
259 | return $this; |
260 | } |
261 | |
262 | /** |
263 | * @return bool |
264 | */ |
265 | public function exists() { |
266 | return $this->id !== null; |
267 | } |
268 | |
269 | /** |
270 | * @return bool |
271 | */ |
272 | public function isPending() { |
273 | return $this->status === self::PENDING; |
274 | } |
275 | |
276 | /** |
277 | * @return bool |
278 | */ |
279 | public function userIsGlobal() { |
280 | return $this->wiki === null; |
281 | } |
282 | |
283 | /** |
284 | * @internal |
285 | * @param stdClass $row Database row |
286 | */ |
287 | public function importRow( stdClass $row ) { |
288 | $this->id = $row->id; |
289 | $this->name = $row->name; |
290 | $this->wiki = $row->wiki; |
291 | $this->newName = $row->newname; |
292 | $this->reason = $row->reason; |
293 | $this->requested = wfTimestampOrNull( TS_MW, $row->requested ); |
294 | $this->status = $row->status; |
295 | $this->completed = wfTimestampOrNull( TS_MW, $row->completed ); |
296 | $this->deleted = $row->deleted; |
297 | $this->performer = $row->performer; |
298 | $this->comments = $row->comments; |
299 | } |
300 | |
301 | /** |
302 | * Check to see if a given username is available for use via CentralAuth. |
303 | * |
304 | * Note that this is not a definitive check. It does not include checking |
305 | * for AntiSpoof, TitleBlacklist or other AbortNewAccount hook blocks. |
306 | * Unfortunately the only canonical way to validate that an account is |
307 | * available is to make the account and check that it wasn't blocked by |
308 | * something. |
309 | * |
310 | * @param string $name |
311 | * @param int $flags one of IDBAccessObject::READ_* flags |
312 | * @return Status Canonicalized name |
313 | */ |
314 | public static function isNameAvailable( string $name, int $flags = IDBAccessObject::READ_LATEST ) { |
315 | $userNameUtils = MediaWikiServices::getInstance()->getUserNameUtils(); |
316 | $safe = $userNameUtils->getCanonical( $name, UserNameUtils::RIGOR_CREATABLE ); |
317 | $status = Status::newGood( $safe ); |
318 | |
319 | if ( $safe === false || $safe === '' ) { |
320 | $status->fatal( 'globalrenamerequest-newname-err-invalid' ); |
321 | return $status; |
322 | } |
323 | |
324 | if ( CentralAuthServices::getGlobalRenameRequestStore()->nameHasPendingRequest( $safe, $flags ) ) { |
325 | $status->fatal( 'globalrenamerequest-newname-err-taken' ); |
326 | return $status; |
327 | } |
328 | |
329 | // New user creation checks against local wiki only using an API |
330 | // request, but we need to check against the central user table instead |
331 | |
332 | if ( $flags & IDBAccessObject::READ_LATEST ) { |
333 | $centralUser = CentralAuthUser::getPrimaryInstanceByName( $safe ); |
334 | } else { |
335 | $centralUser = CentralAuthUser::getInstanceByName( $safe ); |
336 | } |
337 | |
338 | if ( $centralUser->exists() || $centralUser->listUnattached() ) { |
339 | $status->fatal( 'globalrenamerequest-newname-err-taken' ); |
340 | return $status; |
341 | } |
342 | |
343 | // Check to see if there is an active rename to the desired name. |
344 | $progress = $centralUser->renameInProgress(); |
345 | if ( $progress && $safe == $progress[1] ) { |
346 | $status->fatal( 'globalrenamerequest-newname-err-taken' ); |
347 | return $status; |
348 | } |
349 | |
350 | return $status; |
351 | } |
352 | |
353 | } |