Completed
Pull Request — master (#221)
by Maximilian
10:25 queued 07:13
created

users.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 523 and the first side effect is on line 16.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**************************************************************************
3
**********      English Wikipedia Account Request Interface      **********
4
***************************************************************************
5
** Wikipedia Account Request Graphic Design by Charles Melbye,           **
6
** which is licensed under a Creative Commons                            **
7
** Attribution-Noncommercial-Share Alike 3.0 United States License.      **
8
**                                                                       **
9
** All other code are released under the Public Domain                   **
10
** by the ACC Development Team.                                          **
11
**                                                                       **
12
** See CREDITS for the list of developers.                               **
13
***************************************************************************/
14
15
// load the configuration
16
require_once 'config.inc.php';
17
18
// Initialize the session data.
19
session_start();
20
21
// Get all the classes.
22
require_once 'functions.php';
23
require_once 'includes/PdoDatabase.php';
24
require_once 'includes/SmartyInit.php';
25
require_once 'includes/session.php';
26
27
// Check to see if the database is unavailable.
28
// Uses the false variable as its the internal interface.
29
if (Offline::isOffline()) {
30
	echo Offline::getOfflineMessage(false);
31
	die();
32
}
33
34
// Initialize the class objects.
35
$session = new session();
36
37
#region User search
38
39
if (isset($_GET['usersearch'])) {
40
	$user = User::getByUsername($_GET['usersearch'], gGetDb());
41
42
	if ($user != false) {
43
		header("Location: $baseurl/statistics.php?page=Users&user={$user->getId()}");
44
		die();
45
	}
46
}
47
48
#endregion
49
50
// Display the header of the interface.
51
BootstrapSkin::displayInternalHeader();
52
53
// A content block is created if the action is none of the above.
54
// This block would later be used to keep all the HTML except the header and footer.
55
$out = "<div class=\"row-fluid\"><div id=\"span12\">";
56
BootstrapSkin::pushTagStack("</div>");
57
BootstrapSkin::pushTagStack("</div>");
58
echo $out;
59
60
#region Checks if the current user has admin rights.
61
62
if (User::getCurrent()->isCommunityUser()) {
63
	showlogin();
64
	BootstrapSkin::displayInternalFooter();
65
	die();
66
}
67
68
if (!User::getCurrent()->isAdmin()) {
69
	// Displays both the error message and the footer of the interface.
70
	BootstrapSkin::displayAlertBox(
71
			"I'm sorry, but, this page is restricted to administrators only.", 
72
			"alert-error", 
73
			"Access Denied",
74
			true,
75
			false);
76
	BootstrapSkin::displayInternalFooter();
77
	die();
78
}
79
#endregion
80
81
#region user access actions
82
83 View Code Duplication
if (isset ($_GET['approve'])) {
84
	$user = User::getById($_GET['approve'], gGetDb());
85
86
	if ($user == false) {
87
		BootstrapSkin::displayAlertBox(
88
			"Sorry, the user you are trying to approve could not be found.", 
89
			"alert-error", 
90
			"Error",
91
			true,
92
			false);
93
		BootstrapSkin::displayInternalFooter();
94
		die();
95
	}
96
97
	if ($user->isUser() || $user->isAdmin()) {
98
		BootstrapSkin::displayAlertBox(
99
			"Sorry, the user you are trying to approve has already been approved.", 
100
			"alert-error", 
101
			"Error",
102
			true,
103
			false);
104
		BootstrapSkin::displayInternalFooter();
105
		die();
106
	}
107
108
	$user->approve();
109
110
	BootstrapSkin::displayAlertBox(
111
		"Approved user " . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8'), 
112
		"alert-info", 
113
		"", 
114
		false);
115
116
	Notification::userApproved($user);
117
118
	$headers = 'From: [email protected]';
119
	// TODO: move to template?
120
	mail($user->getEmail(), "ACC Account Approved", "Dear " . $user->getOnWikiName() . ",\nYour account " . $user->getUsername() . " has been approved by " . User::getCurrent()->getUsername() . ". To login please go to $baseurl/acc.php.\n- The English Wikipedia Account Creation Team", $headers);
121
	BootstrapSkin::displayInternalFooter();
122
	die();
123
}
124
125 View Code Duplication
if (isset ($_GET['demote'])) {
126
	$user = User::getById($_GET['demote'], gGetDb());
127
128
	if ($user == false) {
129
		BootstrapSkin::displayAlertBox(
130
			"Sorry, the user you are trying to demote could not be found.", 
131
			"alert-error", 
132
			"Error",
133
			true,
134
			false);
135
		BootstrapSkin::displayInternalFooter();
136
		die();
137
	}
138
139
	if (!$user->isAdmin()) {
140
		BootstrapSkin::displayAlertBox(
141
			"Sorry, the user you are trying to demote is not an admin.", 
142
			"alert-error", 
143
			"Error",
144
			true,
145
			false);
146
		BootstrapSkin::displayInternalFooter();
147
		die();
148
	}
149
150
	if (!isset($_POST['reason'])) {
151
152
		global $smarty;
153
		$smarty->assign("user", $user);
154
		$smarty->assign("status", "User");
155
		$smarty->assign("action", "demote");
156
		$smarty->display("usermanagement/changelevel-reason.tpl");
157
		BootstrapSkin::displayInternalFooter();
158
		die();
159
	}
160
	else {
161
		$user->demote($_POST['reason']);
162
163
		BootstrapSkin::displayAlertBox( 
164
			"Changed " . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8') . "'s access to 'User'", 
165
			"alert-info", 
166
			"", 
167
			false);
168
169
		Notification::userDemoted($user, $_POST['reason']);
170
171
		$headers = 'From: [email protected]';
172
        
173
		// TODO: move to template?
174
		mail($user->getEmail(), "ACC Account Demoted", "Dear " . $user->getOnWikiName() . ",\nYour account " . $user->getUsername() . " has been demoted by " . User::getCurrent()->getUsername() . " because " . User::getCurrent()->getUsername() . ". To contest this demotion please email [email protected].\n- The English Wikipedia Account Creation Team", $headers);
175
		BootstrapSkin::displayInternalFooter();
176
		die();
177
	}
178
}
179
180 View Code Duplication
if (isset ($_GET['suspend'])) {
181
	$user = User::getById($_GET['suspend'], gGetDb());
182
183
	if ($user == false) {
184
		BootstrapSkin::displayAlertBox(
185
			"Sorry, the user you are trying to suspend could not be found.", 
186
			"alert-error", 
187
			"Error",
188
			true,
189
			false);
190
		BootstrapSkin::displayInternalFooter();
191
		die();
192
	}
193
194
	if ($user->isSuspended()) {
195
		BootstrapSkin::displayAlertBox(
196
			"Sorry, the user you are trying to suspend is already suspended.", 
197
			"alert-error", 
198
			"Error",
199
			true,
200
			false);
201
		BootstrapSkin::displayInternalFooter();
202
		die();
203
	}
204
	elseif (!isset($_POST['reason'])) {
205
		global $smarty;
206
		$smarty->assign("user", $user);
207
		$smarty->assign("status", "Suspended");
208
		$smarty->assign("action", "suspend");
209
		$smarty->display("usermanagement/changelevel-reason.tpl");
210
		BootstrapSkin::displayInternalFooter();
211
		die();
212
	}
213
	else {
214
		$user->suspend($_POST['reason']);
215
216
		Notification::userSuspended($user, $_POST['reason']);
217
		BootstrapSkin::displayAlertBox(
218
			"Suspended user " . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8'), 
219
			"alert-info", 
220
			"", 
221
			false);
222
223
		$headers = 'From: [email protected]';
224
        
225
		// TODO: move to template?
226
		mail($user->getEmail(), "ACC Account Suspended", "Dear " . $user->getOnWikiName() . ",\nYour account " . $user->getUsername() . " has been suspended by " . User::getCurrent()->getUsername() . " because " . $_POST['reason'] . ". To contest this suspension please email [email protected].\n- The English Wikipedia Account Creation Team", $headers);
227
		BootstrapSkin::displayInternalFooter();
228
		die();
229
	}
230
}
231
232 View Code Duplication
if (isset ($_GET['promote'])) {
233
	$user = User::getById($_GET['promote'], gGetDb());
234
235
	if ($user == false) {
236
		BootstrapSkin::displayAlertBox(
237
			"Sorry, the user you are trying to promote could not be found.", 
238
			"alert-error", 
239
			"Error",
240
			true,
241
			false);
242
		BootstrapSkin::displayInternalFooter();
243
		die();
244
	}
245
246
	if ($user->isAdmin()) {
247
		BootstrapSkin::displayAlertBox(
248
			"Sorry, the user you are trying to promote has Administrator access.",
249
			"alert-error", 
250
			"Error", 
251
			true, 
252
			false);
253
		BootstrapSkin::displayInternalFooter();
254
		die();
255
	}
256
257
	$user->promote();
258
259
	Notification::userPromoted($user);
260
261
	BootstrapSkin::displayAlertBox(
262
		htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8') . " promoted to 'Admin'", 
263
		"alert-info", 
264
		"", 
265
		false);
266
267
	$headers = 'From: [email protected]';
268
    
269
	// TODO: move to template?
270
	mail($user->getEmail(), "ACC Account Promoted", "Dear " . $user->getOnWikiName() . ",\nYour account " . $user->getUsername() . " has been promted to admin status by " . User::getCurrent()->getUsername() . ".\n- The English Wikipedia Account Creation Team", $headers);
271
	die();
272
}
273
274 View Code Duplication
if (isset ($_GET['decline'])) {
275
	$user = User::getById($_GET['decline'], gGetDb());
276
277
	if ($user == false) {
278
		BootstrapSkin::displayAlertBox(
279
			"Sorry, the user you are trying to decline could not be found.", 
280
			"alert-error", 
281
			"Error",
282
			true,
283
			false);
284
		BootstrapSkin::displayInternalFooter();
285
		die();
286
	}
287
288
	if ($user->isAdmin()) {
289
		BootstrapSkin::displayAlertBox("Sorry, the user you are trying to decline is not new.", 
290
			"alert-error", 
291
			"Error", 
292
			true, 
293
			false);
294
		BootstrapSkin::displayInternalFooter();
295
		die();
296
	}
297
298
	if (!isset($_POST['reason'])) {
299
		global $smarty;
300
		$smarty->assign("user", $user);
301
		$smarty->assign("status", "Declined");
302
		$smarty->assign("action", "decline");
303
		$smarty->display("usermanagement/changelevel-reason.tpl");
304
		BootstrapSkin::displayInternalFooter();
305
		die();
306
	}
307
	else {
308
		$user->decline($_POST['reason']);
309
310
		Notification::userDeclined($user, $_POST['reason']);
311
312
		BootstrapSkin::displayAlertBox(
313
			"Declined user " . htmlentities($user->getUsername(), ENT_COMPAT, 'UTF-8'), 
314
			"alert-info", 
315
			"", 
316
			false);
317
318
		$headers = 'From: [email protected]';
319
        
320
		// TODO: move to template?
321
		mail($user->getEmail(), "ACC Account Declined", "Dear " . $user->getOnWikiName() . ",\nYour account " . $user->getUsername() . " has been declined access to the account creation tool by " . User::getCurrent()->getUsername() . " because " . $_POST['reason'] . ". For more infomation please email [email protected].\n- The English Wikipedia Account Creation Team", $headers);
322
		BootstrapSkin::displayInternalFooter();
323
		die();
324
	}
325
}
326
327
#endregion
328
329
#region renaming
330
331
if (isset ($_GET['rename'])) {
332
	$user = User::getById($_GET['rename'], gGetDb());
333
334
	if ($user == false) {
335
		BootstrapSkin::displayAlertBox(
336
			"Sorry, the user you are trying to rename could not be found.", 
337
			"alert-error", 
338
			"Error", 
339
			true, 
340
			false);
341
		BootstrapSkin::displayInternalFooter();
342
		die();
343
	}
344
345
	if (!isset($_POST['newname'])) {
346
		global $smarty;
347
		$smarty->assign("user", $user);
348
		$smarty->display("usermanagement/renameuser.tpl");
349
		BootstrapSkin::displayInternalFooter();
350
		die();
351
	}
352
	else {
353
		if (!isset($_POST['newname']) || trim($_POST['newname']) == "") {
354
			BootstrapSkin::displayAlertBox("The new username cannot be empty.", "alert-error", "Error", true, false);
355
			BootstrapSkin::displayInternalFooter();
356
			die();
357
		}
358
359 View Code Duplication
		if (User::getByUsername($_POST['newname'], gGetDb()) != false) {
360
			BootstrapSkin::displayAlertBox("Username already exists.", "alert-error", "Error", true, false);
361
			BootstrapSkin::displayInternalFooter();
362
			die();
363
		}
364
365
		$database = gGetDb();
366
367
		if (!$database->beginTransaction()) {
368
			BootstrapSkin::displayAlertBox(
369
				"Database transaction could not be started.", 
370
				"alert-error", 
371
				"Error", 
372
				true, 
373
				false);
374
			BootstrapSkin::displayInternalFooter();
375
			die();
376
		}
377
378
		try {
379
			$oldname = $user->getUsername();
380
381
			$user->setUsername($_POST['newname']);
382
			$user->save();
383
384
			$logentry = serialize(array('old' => $oldname, 'new' => $_POST['newname']));
385
			Logger::renamedUser($database, $user, $logentry);
386
           
387
			BootstrapSkin::displayAlertBox(
388
				"Changed User " 
389
					. htmlentities($oldname, ENT_COMPAT, 'UTF-8') 
390
					. " name to "
391
					. htmlentities($_POST['newname'], ENT_COMPAT, 'UTF-8'), 
392
				"alert-info",
393
				"",
394
				false);
395
		}
396
		catch (Exception $ex) {
397
			$database->rollBack();
398
			BootstrapSkin::displayAlertBox($ex->getMessage(), "alert-error", "Error", true, false);
399
			BootstrapSkin::displayInternalFooter();
400
			die();
401
		}
402
403
		$database->commit();
404
405
		Notification::userRenamed($user, $oldname);
406
407
		BootstrapSkin::displayInternalFooter();
408
		die();
409
	}
410
}
411
412
#endregion
413
414
#region edit user
415
416
if (isset ($_GET['edituser']) && $enableRenames == 1) {
417
	$user = User::getById($_GET['edituser'], gGetDb());
418
419
	if ($user == false) {
420
		BootstrapSkin::displayAlertBox(
421
			"Sorry, the user you are trying to rename could not be found.", 
422
			"alert-error", 
423
			"Error", 
424
			true, 
425
			false);
426
		BootstrapSkin::displayInternalFooter();
427
		die();
428
	}
429
430
	if ($_SERVER['REQUEST_METHOD'] != "POST") {
431
		global $smarty;
432
		$smarty->assign("user", $user);
433
		$smarty->display("usermanagement/edituser.tpl");
434
	}
435
	else {
436
		$database = gGetDb();
437
		if (!$database->beginTransaction()) {
438
			BootstrapSkin::displayAlertBox(
439
				"Database transaction could not be started.", 
440
				"alert-error", 
441
				"Error", 
442
				true, 
443
				false);
444
			BootstrapSkin::displayInternalFooter();
445
			die();
446
		}
447
448
		try {
449
			$user->setEmail($_POST['user_email']);
450
451
			if (!$user->isOAuthLinked()) {
452
				$user->setOnWikiName($_POST['user_onwikiname']);
453
			}
454
455
			$user->save();
456
457
			Logger::userPreferencesChange($database, $user);
458
            
459
			Notification::userPrefChange($user);
460
			BootstrapSkin::displayAlertBox("Changes saved.", "alert-info");
461
		}
462
		catch (Exception $ex) {
463
			$database->rollBack();
464
			BootstrapSkin::displayAlertBox($ex->getMessage(), "alert-error", "Error", true, false);
465
			BootstrapSkin::displayInternalFooter();
466
			die();
467
		}
468
469
		$database->commit();
470
	}
471
	BootstrapSkin::displayInternalFooter();
472
	die();
473
}
474
475
#endregion
476
477
// ---------------------   USER MANAGEMENT MAIN PAGE -----------------------------------------
478
479
echo <<<HTML
480
<div class="page-header">
481
  <h1>User Management<small> Approve, suspend, promote, demote, etc.&nbsp;<a class="btn btn-primary" href="?showall"><i class="icon-white icon-eye-open"></i>&nbsp;Show all</a></small></h1>
482
</div>
483
HTML;
484
485
BootstrapSkin::displayAlertBox(
486
	"If it says you can do it, you can do it. Please use this responsibly.", 
487
	"alert-warning",
488
	"This interface is NOT a toy.",
489
	true,
490
	false);
491
492
// assign to user
493
$tailscript = getTypeaheadSource(User::getAllUsernames(gGetDb()));
494
495
echo <<<HTML
496
<div class="row-fluid">
497
    <form class="form-search">
498
        <input type="text" class="input-large username-typeahead" placeholder="Jump to user" data-provide="typeahead" data-items="10" name="usersearch">
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 152 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
499
        <button type="submit" class="btn">Search</button>
500
    </form>
501
</div>
502
HTML;
503
504
/**
505
 * CURRENTLY UNUSED!!
506
 *
507
 * Shows A list of users in a table with the relevant buttons for that access level.
508
 *
509
 * Uses smarty
510
 *
511
 * Different levels may require the use of different data attributes.
512
 *
513
 * @param $data An array of arrays (see example)
514
 * @param $level The user access level
515
 * @example showUserList( array(
516
 *          1 => array(
517
 *              "username" => "foo",
518
 *              "onwikiname" => "foo",
519
 *              ),
520
 *          )
521
 *
522
 */
523
function showUserList($data, $level)
524
{
525
	   global $smarty;
526
	   $smarty->assign("listuserlevel", $level);
527
	   $smarty->assign("listuserdata", $data);
528
	   $smarty->display("usermanagement-userlist.tpl");
529
}
530
531
global $smarty;
532
echo '<div class="row-fluid"><div class="span12"><div class="accordion" id="accordion2">';
533
BootstrapSkin::pushTagStack("</div>");
534
BootstrapSkin::pushTagStack("</div>");
535
BootstrapSkin::pushTagStack("</div>");
536
537
$database = gGetDb();
538
539
$result = User::getAllWithStatus("New", $database);
540
541
if ($result != false && count($result) != 0) {
542
	echo <<<HTML
543
<div class="accordion-group">
544
<div class="accordion-heading">
545
    <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseOne">Open requests</a>
546
</div>
547
<div id="collapseOne" class="accordion-body collapse in"><div class="accordion-inner">
548
HTML;
549
550
	$smarty->assign("userlist", $result);
551
	$smarty->display("usermanagement/userlist.tpl");
552
	echo "</div></div></div>\n";
553
}
554
echo <<<HTML
555
<div class="accordion-group">
556
<div class="accordion-heading">
557
    <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseTwo">Users</a>
558
</div>
559
<div id="collapseTwo" class="accordion-body collapse"><div class="accordion-inner">
560
HTML;
561
562
$result = User::getAllWithStatus("User", $database);
563
$smarty->assign("userlist", $result);
564
$smarty->display("usermanagement/userlist.tpl");
565
echo <<<HTML
566
</div>
567
</div></div>
568
569
<div class="accordion-group">
570
<div class="accordion-heading">
571
    <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseThree">Admins</a>
572
</div>
573
<div id="collapseThree" class="accordion-body collapse"><div class="accordion-inner">
574
<p class="muted">
575
Please note: Users marked as checkusers automatically get administrative rights, even if they do 
576
not appear in the tool administrators section.
577
</p>
578
HTML;
579
580
$result = User::getAllWithStatus("Admin", $database);
581
$smarty->assign("userlist", $result);
582
$smarty->display("usermanagement/userlist.tpl");
583
echo <<<HTML
584
</div>
585
</div></div>
586
587
<div class="accordion-group">
588
<div class="accordion-heading">
589
    <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseFour">Tool Checkuser access</a>
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 127 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
590
</div>
591
<div id="collapseFour" class="accordion-body collapse"><div class="accordion-inner">
592
<p class="muted">
593
Please note: Users marked as checkusers automatically get administrative rights, even if they do
594
not appear in the tool administrators section.
595
</p>
596
HTML;
597
598
$result = User::getAllCheckusers($database);
599
$smarty->assign("userlist", $result);
600
$smarty->display("usermanagement/userlist.tpl");
601
echo '</div></div></div>';
602
603
if (isset($_GET['showall'])) {
604
	echo <<<HTML
605
<div class="accordion-group">
606
<div class="accordion-heading">
607
    <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseFive">Suspended accounts</a>
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 124 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
608
</div>
609
<div id="collapseFive" class="accordion-body collapse"><div class="accordion-inner">
610
HTML;
611
612
	$result = User::getAllWithStatus("Suspended", $database);
613
	$smarty->assign("userlist", $result);
614
	$smarty->display("usermanagement/userlist.tpl");
615
	echo <<<HTML
616
</div>
617
</div></div>
618
619
<div class="accordion-group">
620
<div class="accordion-heading">
621
    <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion2" href="#collapseSix">Declined accounts</a>
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 122 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
622
</div>
623
<div id="collapseSix" class="accordion-body collapse"><div class="accordion-inner">
624
HTML;
625
626
	$result = User::getAllWithStatus("Declined", $database);
627
	$smarty->assign("userlist", $result);
628
	$smarty->display("usermanagement/userlist.tpl");
629
	echo "</div></div></div>";
630
}
631
632
BootstrapSkin::displayInternalFooter($tailscript);
633
die();
634