2
// $Id: user.module,v 1.745.2.1 2007/01/29 19:08:46 dries Exp $
6
* Enables the user registration and login system.
9
define('USERNAME_MAX_LENGTH', 60);
10
define('EMAIL_MAX_LENGTH', 64);
13
* Invokes hook_user() in every module.
15
* We cannot use module_invoke() for this, because the arguments need to
16
* be passed by reference.
18
function user_module_invoke($type, &$array, &$user, $category = NULL) {
19
foreach (module_list() as $module) {
20
$function = $module .'_user';
21
if (function_exists($function)) {
22
$function($type, $array, $user, $category);
27
function user_external_load($authname) {
28
$result = db_query("SELECT uid FROM {authmap} WHERE authname = '%s'", $authname);
30
if ($user = db_fetch_array($result)) {
31
return user_load($user);
39
* Fetch a user object.
42
* An associative array of attributes to search for in selecting the
43
* user, such as user name or e-mail address.
46
* A fully-loaded $user object upon successful user load or FALSE if user cannot be loaded.
48
function user_load($array = array()) {
49
// Dynamically compose a SQL query:
53
foreach ($array as $key => $value) {
54
if ($key == 'uid' || $key == 'status') {
55
$query[] = "$key = %d";
58
else if ($key == 'pass') {
59
$query[] = "pass = '%s'";
60
$params[] = md5($value);
63
$query[]= "LOWER($key) = LOWER('%s')";
67
$result = db_query('SELECT * FROM {users} u WHERE '. implode(' AND ', $query), $params);
69
if (db_num_rows($result)) {
70
$user = db_fetch_object($result);
71
$user = drupal_unpack($user);
73
$user->roles = array();
75
$user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
78
$user->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user';
80
$result = db_query('SELECT r.rid, r.name FROM {role} r INNER JOIN {users_roles} ur ON ur.rid = r.rid WHERE ur.uid = %d', $user->uid);
81
while ($role = db_fetch_object($result)) {
82
$user->roles[$role->rid] = $role->name;
84
user_module_invoke('load', $array, $user);
94
* Save changes to a user account or add a new user.
97
* The $user object for the user to modify or add. If $user->uid is
98
* omitted, a new user will be added.
101
* An array of fields and values to save. For example array('name' => 'My name');
102
* Setting a field to NULL deletes it from the data column.
105
* (optional) The category for storing profile information in.
107
function user_save($account, $array = array(), $category = 'account') {
108
// Dynamically compose a SQL query:
109
$user_fields = user_fields();
111
user_module_invoke('update', $array, $account, $category);
113
$data = unserialize(db_result(db_query('SELECT data FROM {users} WHERE uid = %d', $account->uid)));
114
foreach ($array as $key => $value) {
115
if ($key == 'pass' && !empty($value)) {
116
$query .= "$key = '%s', ";
119
else if ((substr($key, 0, 4) !== 'auth') && ($key != 'pass')) {
120
if (in_array($key, $user_fields)) {
121
// Save standard fields
122
$query .= "$key = '%s', ";
125
else if ($key != 'roles') {
126
// Roles is a special case: it used below.
127
if ($value === NULL) {
131
$data[$key] = $value;
136
$query .= "data = '%s' ";
137
$v[] = serialize($data);
139
db_query("UPDATE {users} SET $query WHERE uid = %d", array_merge($v, array($account->uid)));
141
// Reload user roles if provided
142
if (is_array($array['roles'])) {
143
db_query('DELETE FROM {users_roles} WHERE uid = %d', $account->uid);
145
foreach (array_keys($array['roles']) as $rid) {
146
if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
147
db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $account->uid, $rid);
152
// Delete a blocked user's sessions to kick them if they are online.
153
if (isset($array['status']) && $array['status'] == 0) {
154
sess_destroy_uid($account->uid);
157
// Refresh user object
158
$user = user_load(array('uid' => $account->uid));
159
user_module_invoke('after_update', $array, $user, $category);
162
$array['uid'] = db_next_id('{users}_uid');
164
if (!isset($array['created'])) { // Allow 'created' to be set by hook_auth
165
$array['created'] = time();
168
// Note, we wait with saving the data column to prevent module-handled
169
// fields from being saved there. We cannot invoke hook_user('insert') here
170
// because we don't have a fully initialized user object yet.
171
foreach ($array as $key => $value) {
175
$values[] = md5($value);
178
case 'uid': case 'mode': case 'sort':
179
case 'threshold': case 'created': case 'access':
180
case 'login': case 'status':
186
if (substr($key, 0, 4) !== 'auth' && in_array($key, $user_fields)) {
194
db_query('INSERT INTO {users} ('. implode(', ', $fields) .') VALUES ('. implode(', ', $s) .')', $values);
196
// Build the initial user object.
197
$user = user_load(array('uid' => $array['uid']));
199
user_module_invoke('insert', $array, $user, $category);
201
// Build and save the serialized data field now
203
foreach ($array as $key => $value) {
204
if ((substr($key, 0, 4) !== 'auth') && ($key != 'roles') && (!in_array($key, $user_fields)) && ($value !== NULL)) {
205
$data[$key] = $value;
208
db_query("UPDATE {users} SET data = '%s' WHERE uid = %d", serialize($data), $user->uid);
210
// Save user roles (delete just to be safe).
211
if (is_array($array['roles'])) {
212
db_query('DELETE FROM {users_roles} WHERE uid = %d', $array['uid']);
213
foreach (array_keys($array['roles']) as $rid) {
214
if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
215
db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', $array['uid'], $rid);
220
// Build the finished user object.
221
$user = user_load(array('uid' => $array['uid']));
224
// Save distributed authentication mappings
226
foreach ($array as $key => $value) {
227
if (substr($key, 0, 4) == 'auth') {
228
$authmaps[$key] = $value;
231
if (sizeof($authmaps) > 0) {
232
user_set_authmaps($user, $authmaps);
239
* Verify the syntax of the given name.
241
function user_validate_name($name) {
242
if (!strlen($name)) return t('You must enter a username.');
243
if (substr($name, 0, 1) == ' ') return t('The username cannot begin with a space.');
244
if (substr($name, -1) == ' ') return t('The username cannot end with a space.');
245
if (strpos($name, ' ') !== FALSE) return t('The username cannot contain multiple spaces in a row.');
246
if (ereg("[^\x80-\xF7 [:alnum:]@_.-]", $name)) return t('The username contains an illegal character.');
247
if (preg_match('/[\x{80}-\x{A0}'. // Non-printable ISO-8859-1 + NBSP
248
'\x{AD}'. // Soft-hyphen
249
'\x{2000}-\x{200F}'. // Various space characters
250
'\x{2028}-\x{202F}'. // Bidirectional text overrides
251
'\x{205F}-\x{206F}'. // Various text hinting characters
252
'\x{FEFF}'. // Byte order mark
253
'\x{FF01}-\x{FF60}'. // Full-width latin
254
'\x{FFF9}-\x{FFFD}'. // Replacement characters
255
'\x{0}]/u', // NULL byte
257
return t('The username contains an illegal character.');
259
if (strpos($name, '@') !== FALSE && !eregi('@([0-9a-z](-?[0-9a-z])*.)+[a-z]{2}([zmuvtg]|fo|me)?$', $name)) return t('The username is not a valid authentication ID.');
260
if (strlen($name) > USERNAME_MAX_LENGTH) return t('The username %name is too long: it must be %max characters or less.', array('%name' => $name, '%max' => USERNAME_MAX_LENGTH));
263
function user_validate_mail($mail) {
264
if (!$mail) return t('You must enter an e-mail address.');
265
if (!valid_email_address($mail)) {
266
return t('The e-mail address %mail is not valid.', array('%mail' => $mail));
270
function user_validate_picture($file, &$edit, $user) {
272
// Initialize the picture:
273
$form_values['picture'] = $user->picture;
275
// Check that uploaded file is an image, with a maximum file size
276
// and maximum height/width.
277
$info = image_get_info($file->filepath);
278
list($maxwidth, $maxheight) = explode('x', variable_get('user_picture_dimensions', '85x85'));
280
if (!$info || !$info['extension']) {
281
form_set_error('picture_upload', t('The uploaded file was not an image.'));
283
else if (image_get_toolkit()) {
284
image_scale($file->filepath, $file->filepath, $maxwidth, $maxheight);
286
else if (filesize($file->filepath) > (variable_get('user_picture_file_size', '30') * 1000)) {
287
form_set_error('picture_upload', t('The uploaded image is too large; the maximum file size is %size kB.', array('%size' => variable_get('user_picture_file_size', '30'))));
289
else if ($info['width'] > $maxwidth || $info['height'] > $maxheight) {
290
form_set_error('picture_upload', t('The uploaded image is too large; the maximum dimensions are %dimensions pixels.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'))));
293
if (!form_get_errors()) {
294
if ($file = file_save_upload('picture_upload', variable_get('user_picture_path', 'pictures') .'/picture-'. $user->uid .'.'. $info['extension'], 1)) {
295
$form_values['picture'] = $file->filepath;
298
form_set_error('picture_upload', t("Failed to upload the picture image; the %directory directory doesn't exist.", array('%directory' => variable_get('user_picture_path', 'pictures'))));
304
* Generate a random alphanumeric password.
306
function user_password($length = 10) {
307
// This variable contains the list of allowable characters for the
308
// password. Note that the number 0 and the letter 'O' have been
309
// removed to avoid confusion between the two. The same is true
311
$allowable_characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
313
// Zero-based count of characters in the allowable list:
314
$len = strlen($allowable_characters) - 1;
316
// Declare the password as a blank string.
319
// Loop the number of times specified by $length.
320
for ($i = 0; $i < $length; $i++) {
322
// Each iteration, pick a random character from the
323
// allowable string and append it to the password:
324
$pass .= $allowable_characters[mt_rand(0, $len)];
331
* Determine whether the user has a given privilege.
334
* The permission, such as "administer nodes", being checked for.
336
* (optional) The account to check, if not given use currently logged in user.
339
* boolean TRUE if the current user has the requested permission.
341
* All permission checks in Drupal should go through this function. This
342
* way, we guarantee consistent behavior, and ensure that the superuser
343
* can perform all actions.
345
function user_access($string, $account = NULL) {
347
static $perm = array();
349
if (is_null($account)) {
353
// User #1 has all privileges:
354
if ($account->uid == 1) {
358
// To reduce the number of SQL queries, we cache the user's permissions
359
// in a static variable.
360
if (!isset($perm[$account->uid])) {
361
$result = db_query("SELECT DISTINCT(p.perm) FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (%s)", implode(',', array_keys($account->roles)));
363
$perm[$account->uid] = '';
364
while ($row = db_fetch_object($result)) {
365
$perm[$account->uid] .= "$row->perm, ";
369
if (isset($perm[$account->uid])) {
370
return strpos($perm[$account->uid], "$string, ") !== FALSE;
377
* Checks for usernames blocked by user administration
379
* @return boolean TRUE for blocked users, FALSE for active
381
function user_is_blocked($name) {
382
$deny = db_fetch_object(db_query("SELECT name FROM {users} WHERE status = 0 AND name = LOWER('%s')", $name));
387
function user_fields() {
391
$result = db_query('SELECT * FROM {users} WHERE uid = 1');
392
if (db_num_rows($result)) {
393
$fields = array_keys(db_fetch_array($result));
396
// Make sure we return the default fields at least
397
$fields = array('uid', 'name', 'pass', 'mail', 'picture', 'mode', 'sort', 'threshold', 'theme', 'signature', 'created', 'access', 'login', 'status', 'timezone', 'language', 'init', 'data');
405
* Implementation of hook_perm().
407
function user_perm() {
408
return array('administer access control', 'administer users', 'access user profiles', 'change own username');
412
* Implementation of hook_file_download().
414
* Ensure that user pictures (avatars) are always downloadable.
416
function user_file_download($file) {
417
if (strpos($file, variable_get('user_picture_path', 'pictures') .'/picture-') === 0) {
418
$info = image_get_info(file_create_path($file));
419
return array('Content-type: '. $info['mime_type']);
424
* Implementation of hook_search().
426
function user_search($op = 'search', $keys = NULL) {
429
if (user_access('access user profiles')) {
433
if (user_access('access user profiles')) {
435
// Replace wildcards with MySQL/PostgreSQL wildcards.
436
$keys = preg_replace('!\*+!', '%', $keys);
437
$result = pager_query("SELECT * FROM {users} WHERE LOWER(name) LIKE LOWER('%%%s%%')", 15, 0, NULL, $keys);
438
while ($account = db_fetch_object($result)) {
439
$find[] = array('title' => $account->name, 'link' => url('user/'. $account->uid, NULL, NULL, TRUE));
447
* Implementation of hook_user().
449
function user_user($type, &$edit, &$user, $category = NULL) {
450
if ($type == 'view') {
451
$items['history'] = array('title' => t('Member for'),
452
'value' => format_interval(time() - $user->created),
456
return array(t('History') => $items);
458
if ($type == 'form' && $category == 'account') {
459
return user_edit_form(arg(1), $edit);
462
if ($type == 'validate' && $category == 'account') {
463
return _user_edit_validate(arg(1), $edit);
466
if ($type == 'submit' && $category == 'account') {
467
return _user_edit_submit(arg(1), $edit);
470
if ($type == 'categories') {
471
return array(array('name' => 'account', 'title' => t('Account settings'), 'weight' => 1));
475
function user_login_block() {
477
'#action' => url($_GET['q'], drupal_get_destination()),
478
'#id' => 'user-login-form',
479
'#base' => 'user_login',
481
$form['name'] = array('#type' => 'textfield',
482
'#title' => t('Username'),
483
'#maxlength' => USERNAME_MAX_LENGTH,
487
$form['pass'] = array('#type' => 'password',
488
'#title' => t('Password'),
493
$form['submit'] = array('#type' => 'submit',
494
'#value' => t('Log in'),
497
if (variable_get('user_register', 1)) {
498
$items[] = l(t('Create new account'), 'user/register', array('title' => t('Create a new user account.')));
500
$items[] = l(t('Request new password'), 'user/password', array('title' => t('Request new password via e-mail.')));
501
$form['links'] = array('#value' => theme('item_list', $items));
506
* Implementation of hook_block().
508
function user_block($op = 'list', $delta = 0, $edit = array()) {
512
$blocks[0]['info'] = t('User login');
513
$blocks[1]['info'] = t('Navigation');
514
$blocks[2]['info'] = t('Who\'s new');
515
$blocks[3]['info'] = t('Who\'s online');
519
else if ($op == 'configure' && $delta == 2) {
520
$form['user_block_whois_new_count'] = array(
522
'#title' => t('Number of users to display'),
523
'#default_value' => variable_get('user_block_whois_new_count', 5),
524
'#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)),
528
else if ($op == 'configure' && $delta == 3) {
529
$period = drupal_map_assoc(array(30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, 10800, 21600, 43200, 86400), 'format_interval');
530
$form['user_block_seconds_online'] = array('#type' => 'select', '#title' => t('User activity'), '#default_value' => variable_get('user_block_seconds_online', 900), '#options' => $period, '#description' => t('A user is considered online for this long after they have last viewed a page.'));
531
$form['user_block_max_list_count'] = array('#type' => 'select', '#title' => t('User list length'), '#default_value' => variable_get('user_block_max_list_count', 10), '#options' => drupal_map_assoc(array(0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), '#description' => t('Maximum number of currently online users to display.'));
535
else if ($op == 'save' && $delta == 2) {
536
variable_set('user_block_whois_new_count', $edit['user_block_whois_new_count']);
538
else if ($op == 'save' && $delta == 3) {
539
variable_set('user_block_seconds_online', $edit['user_block_seconds_online']);
540
variable_set('user_block_max_list_count', $edit['user_block_max_list_count']);
542
else if ($op == 'view') {
547
// For usability's sake, avoid showing two login forms on one page.
548
if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) {
550
$block['subject'] = t('User login');
551
$block['content'] = drupal_get_form('user_login_block');
556
if ($menu = theme('menu_tree')) {
557
$block['subject'] = $user->uid ? check_plain($user->name) : t('Navigation');
558
$block['content'] = $menu;
563
if (user_access('access content')) {
564
// Retrieve a list of new users who have subsequently accessed the site successfully.
565
$result = db_query_range('SELECT uid, name FROM {users} WHERE status != 0 AND access != 0 ORDER BY created DESC', 0, variable_get('user_block_whois_new_count', 5));
566
while ($account = db_fetch_object($result)) {
569
$output = theme('user_list', $items);
571
$block['subject'] = t('Who\'s new');
572
$block['content'] = $output;
577
if (user_access('access content')) {
578
// Count users with activity in the past defined period.
579
$interval = time() - variable_get('user_block_seconds_online', 900);
581
// Perform database queries to gather online user lists. We use s.timestamp
582
// rather than u.access because it is much faster is much faster..
583
$anonymous_count = sess_count($interval);
584
$authenticated_users = db_query('SELECT u.uid, u.name FROM {users} u INNER JOIN {sessions} s ON u.uid = s.uid WHERE s.timestamp >= %d AND s.uid > 0 ORDER BY s.timestamp DESC', $interval);
585
$authenticated_count = db_num_rows($authenticated_users);
587
// Format the output with proper grammar.
588
if ($anonymous_count == 1 && $authenticated_count == 1) {
589
$output = t('There is currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests')));
592
$output = t('There are currently %members and %visitors online.', array('%members' => format_plural($authenticated_count, '1 user', '@count users'), '%visitors' => format_plural($anonymous_count, '1 guest', '@count guests')));
595
// Display a list of currently online users.
596
$max_users = variable_get('user_block_max_list_count', 10);
597
if ($authenticated_count && $max_users) {
600
while ($max_users-- && $account = db_fetch_object($authenticated_users)) {
604
$output .= theme('user_list', $items, t('Online users'));
607
$block['subject'] = t('Who\'s online');
608
$block['content'] = $output;
615
function theme_user_picture($account) {
616
if (variable_get('user_pictures', 0)) {
617
if ($account->picture && file_exists($account->picture)) {
618
$picture = file_create_url($account->picture);
620
else if (variable_get('user_picture_default', '')) {
621
$picture = variable_get('user_picture_default', '');
624
if (isset($picture)) {
625
$alt = t("@user's picture", array('@user' => $account->name ? $account->name : variable_get('anonymous', t('Anonymous'))));
626
$picture = theme('image', $picture, $alt, $alt, '', FALSE);
627
if (!empty($account->uid) && user_access('access user profiles')) {
628
$picture = l($picture, "user/$account->uid", array('title' => t('View user profile.')), NULL, NULL, FALSE, TRUE);
631
return "<div class=\"picture\">$picture</div>";
638
* @param $account the user object
639
* @param $fields a multidimensional array for the fields, in the form of array (
640
* 'category1' => array(item_array1, item_array2), 'category2' => array(item_array3,
641
* .. etc.). Item arrays are formatted as array(array('title' => 'item title',
642
* 'value' => 'item value', 'class' => 'class-name'), ... etc.). Module names are incorporated
643
* into the CSS class.
647
function theme_user_profile($account, $fields) {
648
$output = '<div class="profile">';
649
$output .= theme('user_picture', $account);
650
foreach ($fields as $category => $items) {
651
if (strlen($category) > 0) {
652
$output .= '<h2 class="title">'. $category .'</h2>';
655
foreach ($items as $item) {
656
if (isset($item['title'])) {
657
$output .= '<dt class="'. $item['class'] .'">'. $item['title'] .'</dt>';
659
$output .= '<dd class="'. $item['class'] .'">'. $item['value'] .'</dd>';
669
* Make a list of users.
670
* @param $items an array with user objects. Should contain at least the name and uid
674
function theme_user_list($users, $title = NULL) {
675
if (!empty($users)) {
676
foreach ($users as $user) {
677
$items[] = theme('username', $user);
680
return theme('item_list', $items, $title);
684
* Implementation of hook_menu().
686
function user_menu($may_cache) {
691
$admin_access = user_access('administer users');
692
$access_access = user_access('administer access control');
693
$view_access = user_access('access user profiles');
696
$items[] = array('path' => 'user', 'title' => t('User account'),
697
'callback' => 'drupal_get_form', 'callback arguments' => array('user_login'),
698
'access' => !$user->uid, 'type' => MENU_CALLBACK);
700
$items[] = array('path' => 'user/autocomplete', 'title' => t('User autocomplete'),
701
'callback' => 'user_autocomplete', 'access' => $view_access, 'type' => MENU_CALLBACK);
703
// Registration and login pages.
704
$items[] = array('path' => 'user/login', 'title' => t('Log in'),
705
'callback' => 'drupal_get_form', 'callback arguments' => array('user_login'),
706
'access' => !$user->uid, 'type' => MENU_DEFAULT_LOCAL_TASK);
707
$items[] = array('path' => 'user/register', 'title' => t('Create new account'),
708
'callback' => 'drupal_get_form', 'callback arguments' => array('user_register'), 'access' => !$user->uid && variable_get('user_register', 1), 'type' => MENU_LOCAL_TASK);
709
$items[] = array('path' => 'user/password', 'title' => t('Request new password'),
710
'callback' => 'drupal_get_form', 'callback arguments' => array('user_pass'), 'access' => !$user->uid, 'type' => MENU_LOCAL_TASK);
711
$items[] = array('path' => 'user/reset', 'title' => t('Reset password'),
712
'callback' => 'drupal_get_form', 'callback arguments' => array('user_pass_reset'), 'access' => TRUE, 'type' => MENU_CALLBACK);
713
$items[] = array('path' => 'user/help', 'title' => t('Help'),
714
'callback' => 'user_help_page', 'type' => MENU_CALLBACK);
717
$items[] = array('path' => 'admin/user',
718
'title' => t('User management'),
719
'description' => t('Manage your site\'s users, groups and access to site features.'),
720
'position' => 'left',
721
'callback' => 'system_admin_menu_block_page',
722
'access' => user_access('administer site configuration'),
724
$items[] = array('path' => 'admin/user/user', 'title' => t('Users'),
725
'description' => t('List, add, and edit users.'),
726
'callback' => 'user_admin', 'callback arguments' => array('list'), 'access' => $admin_access);
727
$items[] = array('path' => 'admin/user/user/list', 'title' => t('List'),
728
'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
729
$items[] = array('path' => 'admin/user/user/create', 'title' => t('Add user'),
730
'callback' => 'user_admin', 'callback arguments' => array('create'), 'access' => $admin_access,
731
'type' => MENU_LOCAL_TASK);
732
$items[] = array('path' => 'admin/user/settings', 'title' => t('User settings'),
733
'description' => t('Configure default behavior of users, including registration requirements, e-mails, and user pictures.'),
734
'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_settings'));
736
// Admin access pages
737
$items[] = array('path' => 'admin/user/access', 'title' => t('Access control'),
738
'description' => t('Determine access to features by selecting permissions for roles.'),
739
'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_perm'), 'access' => $access_access);
740
$items[] = array('path' => 'admin/user/roles', 'title' => t('Roles'),
741
'description' => t('List, edit, or add user roles.'),
742
'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_new_role'), 'access' => $access_access,
743
'type' => MENU_NORMAL_ITEM);
744
$items[] = array('path' => 'admin/user/roles/edit', 'title' => t('Edit role'),
745
'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_role'), 'access' => $access_access,
746
'type' => MENU_CALLBACK);
747
$items[] = array('path' => 'admin/user/rules', 'title' => t('Access rules'),
748
'description' => t('List and create rules to disallow usernames, e-mail addresses, and IP addresses.'),
749
'callback' => 'user_admin_access', 'access' => $access_access);
750
$items[] = array('path' => 'admin/user/rules/list', 'title' => t('List'),
751
'access' => $access_access, 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
752
$items[] = array('path' => 'admin/user/rules/add', 'title' => t('Add rule'),
753
'callback' => 'user_admin_access_add', 'access' => $access_access,
754
'type' => MENU_LOCAL_TASK);
755
$items[] = array('path' => 'admin/user/rules/check', 'title' => t('Check rules'),
756
'callback' => 'user_admin_access_check', 'access' => $access_access,
757
'type' => MENU_LOCAL_TASK);
758
$items[] = array('path' => 'admin/user/rules/edit', 'title' => t('Edit rule'),
759
'callback' => 'user_admin_access_edit', 'access' => $access_access,
760
'type' => MENU_CALLBACK);
761
$items[] = array('path' => 'admin/user/rules/delete', 'title' => t('Delete rule'),
762
'callback' => 'drupal_get_form', 'callback arguments' => array('user_admin_access_delete_confirm'),
763
'access' => $access_access, 'type' => MENU_CALLBACK);
765
if (module_exists('search')) {
766
$items[] = array('path' => 'admin/user/search', 'title' => t('Search users'),
767
'description' => t('Search users by name.'),
768
'callback' => 'user_admin', 'callback arguments' => array('search'), 'access' => $admin_access,
769
'type' => MENU_NORMAL_ITEM);
772
// Your personal page
774
$items[] = array('path' => 'user/'. $user->uid, 'title' => t('My account'),
775
'callback' => 'user_view', 'callback arguments' => array(arg(1)), 'access' => TRUE,
776
'type' => MENU_DYNAMIC_ITEM);
779
$items[] = array('path' => 'logout', 'title' => t('Log out'),
780
'access' => $user->uid,
781
'callback' => 'user_logout',
785
// Add the CSS for this module. We put this in !$may_cache so it is only
786
// added once per request.
787
drupal_add_css(drupal_get_path('module', 'user') .'/user.css', 'module');
788
if ($_GET['q'] == 'user' && $user->uid) {
789
// We want to make the current user's profile accessible without knowing
790
// their uid, so just linking to /user is enough.
791
drupal_goto('user/'. $user->uid);
794
if (arg(0) == 'user' && is_numeric(arg(1)) && arg(1) > 0) {
795
$account = user_load(array('uid' => arg(1)));
797
if ($user !== FALSE) {
798
// Always let a user view their own account
799
$view_access |= $user->uid == arg(1);
800
// Only admins can view blocked accounts
801
$view_access &= $account->status || $admin_access;
803
$items[] = array('path' => 'user/'. arg(1), 'title' => t('User'),
804
'type' => MENU_CALLBACK, 'callback' => 'user_view',
805
'callback arguments' => array(arg(1)), 'access' => $view_access);
807
$items[] = array('path' => 'user/'. arg(1) .'/view', 'title' => t('View'),
808
'access' => $view_access, 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10);
810
$items[] = array('path' => 'user/'. arg(1) .'/edit', 'title' => t('Edit'),
811
'callback' => 'drupal_get_form', 'callback arguments' => array('user_edit'),
812
'access' => $admin_access || $user->uid == arg(1), 'type' => MENU_LOCAL_TASK);
813
$items[] = array('path' => 'user/'. arg(1) .'/delete', 'title' => t('Delete'),
814
'callback' => 'user_edit', 'access' => $admin_access,
815
'type' => MENU_CALLBACK);
817
if (arg(2) == 'edit') {
818
if (($categories = _user_categories($account)) && (count($categories) > 1)) {
819
foreach ($categories as $key => $category) {
821
'path' => 'user/'. arg(1) .'/edit/'. $category['name'],
822
'title' => $category['title'],
823
'type' => $category['name'] == 'account' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
824
'weight' => $category['weight'],
825
'access' => ($admin_access || $user->uid == arg(1)));
837
* Accepts an user object, $account, or a DA name and returns an associative
838
* array of modules and DA names. Called at external login.
840
function user_get_authmaps($authname = NULL) {
841
$result = db_query("SELECT authname, module FROM {authmap} WHERE authname = '%s'", $authname);
842
if (db_num_rows($result) > 0) {
843
while ($authmap = db_fetch_object($result)) {
844
$authmaps[$authmap->module] = $authmap->authname;
853
function user_set_authmaps($account, $authmaps) {
854
foreach ($authmaps as $key => $value) {
855
$module = explode('_', $key, 2);
857
db_query("UPDATE {authmap} SET authname = '%s' WHERE uid = %d AND module = '%s'", $value, $account->uid, $module[1]);
858
if (!db_affected_rows()) {
859
db_query("INSERT INTO {authmap} (authname, uid, module) VALUES ('%s', %d, '%s')", $value, $account->uid, $module[1]);
863
db_query("DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", $account->uid, $module[1]);
868
function user_auth_help_links() {
870
foreach (module_list() as $module) {
871
if (module_hook($module, 'auth')) {
872
$links[] = l(module_invoke($module, 'info', 'name'), 'user/help', array(), NULL, $module);
878
/*** User features *********************************************************/
882
function user_login($msg = '') {
885
// If we are already logged on, go to the user page instead.
887
drupal_goto('user/'. $user->uid);
890
// Display login form:
892
$form['message'] = array('#value' => '<p>'. check_plain($msg) .'</p>');
894
$form['name'] = array('#type' => 'textfield',
895
'#title' => t('Username'),
897
'#maxlength' => USERNAME_MAX_LENGTH,
899
'#attributes' => array('tabindex' => '1'),
901
if (variable_get('drupal_authentication_service', FALSE) && count(user_auth_help_links()) > 0) {
902
$form['name']['#description'] = t('Enter your @s username, or an ID from one of our affiliates: !a.', array('@s' => variable_get('site_name', 'Drupal'), '!a' => implode(', ', user_auth_help_links())));
905
$form['name']['#description'] = t('Enter your @s username.', array('@s' => variable_get('site_name', 'Drupal')));
907
$form['pass'] = array('#type' => 'password',
908
'#title' => t('Password'),
909
'#description' => t('Enter the password that accompanies your username.'),
911
'#attributes' => array('tabindex' => '2'),
913
$form['submit'] = array('#type' => 'submit', '#value' => t('Log in'), '#weight' => 2, '#attributes' => array('tabindex' => '3'));
918
function user_login_validate($form_id, $form_values) {
919
if ($form_values['name']) {
920
if (user_is_blocked($form_values['name'])) {
921
// blocked in user administration
922
form_set_error('login', t('The username %name has not been activated or is blocked.', array('%name' => $form_values['name'])));
924
else if (drupal_is_denied('user', $form_values['name'])) {
925
// denied by access controls
926
form_set_error('login', t('The name %name is a reserved username.', array('%name' => $form_values['name'])));
928
else if ($form_values['pass']) {
929
$user = user_authenticate($form_values['name'], trim($form_values['pass']));
932
form_set_error('login', t('Sorry, unrecognized username or password. <a href="@password">Have you forgotten your password?</a>', array('@password' => url('user/password'))));
933
watchdog('user', t('Login attempt failed for %user.', array('%user' => $form_values['name'])));
939
function user_login_submit($form_id, $form_values) {
942
// To handle the edge case where this function is called during a
943
// bootstrap, check for the existence of t().
944
if (function_exists('t')) {
945
$message = t('Session opened for %name.', array('%name' => $user->name));
948
$message = "Session opened for ". check_plain($user->name);
950
watchdog('user', $message);
952
// Update the user table timestamp noting user has logged in.
953
db_query("UPDATE {users} SET login = %d WHERE uid = %d", time(), $user->uid);
955
user_module_invoke('login', $form_values, $user);
958
return 'user/'. $user->uid;
962
function user_authenticate($name, $pass) {
965
// Try to log in the user locally. Don't set $user unless successful.
966
if ($account = user_load(array('name' => $name, 'pass' => $pass, 'status' => 1))) {
971
// Strip name and server from ID:
972
if ($server = strrchr($name, '@')) {
973
$name = substr($name, 0, strlen($name) - strlen($server));
974
$server = substr($server, 1);
977
// When possible, determine corresponding external auth source. Invoke
978
// source, and log in user if successful:
979
if ($server && ($result = user_get_authmaps("$name@$server"))) {
980
if (module_invoke(key($result), 'auth', $name, $pass, $server)) {
981
$user = user_external_load("$name@$server");
982
watchdog('user', t('External load by %user using module %module.', array('%user' => $name .'@'. $server, '%module' => key($result))));
986
// Try each external authentication source in series. Register user if
989
foreach (module_implements('auth') as $module) {
990
if (module_invoke($module, 'auth', $name, $pass, $server)) {
992
$name .= '@'. $server;
994
$user = user_load(array('name' => $name));
995
if (!$user->uid) { // Register this new user.
996
$userinfo = array('name' => $name, 'pass' => user_password(), 'init' => $name, 'status' => 1);
998
$userinfo["authname_$module"] = $name;
1000
$user = user_save('', $userinfo);
1001
watchdog('user', t('New external user: %user using module %module.', array('%user' => $name, '%module' => $module)), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $user->uid .'/edit'));
1011
* Menu callback; logs the current user out, and redirects to the home page.
1013
function user_logout() {
1016
watchdog('user', t('Session closed for %name.', array('%name' => $user->name)));
1018
// Destroy the current session:
1020
module_invoke_all('user', 'logout', NULL, $user);
1022
// Load the anonymous user
1023
$user = drupal_anonymous_user();
1028
function user_pass() {
1031
$form['name'] = array('#type' => 'textfield',
1032
'#title' => t('Username or e-mail address'),
1034
'#maxlength' => max(USERNAME_MAX_LENGTH, EMAIL_MAX_LENGTH),
1035
'#required' => TRUE,
1037
$form['submit'] = array('#type' => 'submit',
1038
'#value' => t('E-mail new password'),
1044
function user_pass_validate($form_id, $form_values) {
1045
$name = $form_values['name'];
1046
$account = user_load(array('mail' => $name, 'status' => 1));
1048
$account = user_load(array('name' => $name, 'status' => 1));
1050
if ($account->uid) {
1051
form_set_value(array('#parents' => array('account')), $account);
1054
form_set_error('name', t('Sorry, %name is not recognized as a user name or an email address.', array('%name' => $name)));
1058
function user_pass_submit($form_id, $form_values) {
1061
$account = $form_values['account'];
1062
$from = variable_get('site_mail', ini_get('sendmail_from'));
1064
// Mail one time login URL and instructions.
1065
$variables = array('!username' => $account->name, '!site' => variable_get('site_name', 'Drupal'), '!login_url' => user_pass_reset_url($account), '!uri' => $base_url, '!uri_brief' => substr($base_url, strlen('http://')), '!mailto' => $account->mail, '!date' => format_date(time()), '!login_uri' => url('user', NULL, NULL, TRUE), '!edit_uri' => url('user/'. $account->uid .'/edit', NULL, NULL, TRUE));
1066
$subject = _user_mail_text('pass_subject', $variables);
1067
$body = _user_mail_text('pass_body', $variables);
1068
$mail_success = drupal_mail('user-pass', $account->mail, $subject, $body, $from);
1070
if ($mail_success) {
1071
watchdog('user', t('Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail)));
1072
drupal_set_message(t('Further instructions have been sent to your e-mail address.'));
1075
watchdog('user', t('Error mailing password reset instructions to %name at %email.', array('%name' => $account->name, '%email' => $account->mail)), WATCHDOG_ERROR);
1076
drupal_set_message(t('Unable to send mail. Please contact the site admin.'));
1082
* Menu callback; process one time login link and redirects to the user page on success.
1084
function user_pass_reset($uid, $timestamp, $hashed_pass, $action = NULL) {
1087
// Check if the user is already logged in. The back button is often the culprit here.
1089
drupal_set_message(t('You have already used this one-time login link. It is not necessary to use this link to login anymore. You are already logged in.'));
1093
// Time out, in seconds, until login URL expires. 24 hours = 86400 seconds.
1096
// Some redundant checks for extra security ?
1097
if ($timestamp < $current && $account = user_load(array('uid' => $uid, 'status' => 1)) ) {
1098
// No time out for first time login.
1099
if ($account->login && $current - $timestamp > $timeout) {
1100
drupal_set_message(t('You have tried to use a one-time login link that has expired. Please request a new one using the form below.'));
1101
drupal_goto('user/password');
1103
else if ($account->uid && $timestamp > $account->login && $timestamp < $current && $hashed_pass == user_pass_rehash($account->pass, $timestamp, $account->login)) {
1104
// First stage is a confirmation form, then login
1105
if ($action == 'login') {
1106
watchdog('user', t('User %name used one-time login link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp)));
1107
// Update the user table noting user has logged in.
1108
// And this also makes this hashed password a one-time-only login.
1109
db_query("UPDATE {users} SET login = %d WHERE uid = %d", time(), $account->uid);
1110
// Now we can set the new user.
1112
// And proceed with normal login, going to user page.
1114
user_module_invoke('login', $edit, $user);
1115
drupal_set_message(t('You have just used your one-time login link. It is no longer necessary to use this link to login. Please change your password.'));
1116
drupal_goto('user/'. $user->uid .'/edit');
1119
$form['message'] = array('#value' => t('<p>This is a one-time login for %user_name and will expire on %expiration_date</p><p>Click on this button to login to the site and change your password.</p>', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout))));
1120
$form['help'] = array('#value' => '<p>'. t('This login can be used only once.') .'</p>');
1121
$form['submit'] = array('#type' => 'submit', '#value' => t('Log in'));
1122
$form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login");
1127
drupal_set_message(t('You have tried to use a one-time login link which has either been used or is no longer valid. Please request a new one using the form below.'));
1128
drupal_goto('user/password');
1132
// Deny access, no more clues.
1133
// Everything will be in the watchdog's URL for the administrator to check.
1134
drupal_access_denied();
1139
function user_pass_reset_url($account) {
1140
$timestamp = time();
1141
return url("user/reset/$account->uid/$timestamp/".user_pass_rehash($account->pass, $timestamp, $account->login), NULL, NULL, TRUE);
1144
function user_pass_rehash($password, $timestamp, $login) {
1145
return md5($timestamp . $password . $login);
1148
function user_register() {
1151
$admin = user_access('administer users');
1153
// If we aren't admin but already logged on, go to the user page instead.
1154
if (!$admin && $user->uid) {
1155
drupal_goto('user/'. $user->uid);
1160
// Display the registration form.
1162
$form['user_registration_help'] = array('#value' => filter_xss_admin(variable_get('user_registration_help', '')));
1164
$affiliates = user_auth_help_links();
1165
if (!$admin && count($affiliates) > 0) {
1166
$affiliates = implode(', ', $affiliates);
1167
$form['affiliates'] = array('#value' => '<p>'. t('Note: if you have an account with one of our affiliates (!s), you may <a href="@login_uri">login now</a> instead of registering.', array('!s' => $affiliates, '@login_uri' => url('user'))) .'</p>');
1169
// Merge in the default user edit fields.
1170
$form = array_merge($form, user_edit_form(NULL, NULL, TRUE));
1172
$form['account']['notify'] = array(
1173
'#type' => 'checkbox',
1174
'#title' => t('Notify user of new account')
1176
// Redirect back to page which initiated the create request; usually admin/user/user/create
1177
$form['destination'] = array('#type' => 'hidden', '#value' => $_GET['q']);
1180
// Create a dummy variable for pass-by-reference parameters.
1182
$extra = _user_forms($null, NULL, NULL, 'register');
1184
// Remove form_group around default fields if there are no other groups.
1186
$form['name'] = $form['account']['name'];
1187
$form['mail'] = $form['account']['mail'];
1188
$form['pass'] = $form['account']['pass'];
1189
$form['status'] = $form['account']['status'];
1190
$form['roles'] = $form['account']['roles'];
1191
$form['notify'] = $form['account']['notify'];
1192
unset($form['account']);
1195
$form = array_merge($form, $extra);
1197
$form['submit'] = array('#type' => 'submit', '#value' => t('Create new account'), '#weight' => 30);
1202
function user_register_validate($form_id, $form_values) {
1203
user_module_invoke('validate', $form_values, $form_values, 'account');
1206
function user_register_submit($form_id, $form_values) {
1208
$admin = user_access('administer users');
1210
$mail = $form_values['mail'];
1211
$name = $form_values['name'];
1212
if (!variable_get('user_email_verification', TRUE) || $admin) {
1213
$pass = $form_values['pass'];
1216
$pass = user_password();
1218
$notify = $form_values['notify'];
1219
$from = variable_get('site_mail', ini_get('sendmail_from'));
1220
if (isset($form_values['roles'])) {
1221
$roles = array_filter($form_values['roles']); // Remove unset roles
1224
if (!$admin && array_intersect(array_keys($form_values), array('uid', 'roles', 'init', 'session', 'status'))) {
1225
watchdog('security', t('Detected malicious attempt to alter protected user fields.'), WATCHDOG_WARNING);
1226
return 'user/register';
1228
//the unset below is needed to prevent these form values from being saved as user data
1229
unset($form_values['form_token'], $form_values['submit'], $form_values['op'], $form_values['notify'], $form_values['form_id'], $form_values['affiliates'], $form_values['destination']);
1231
$merge_data = array('pass' => $pass, 'init' => $mail, 'roles' => $roles);
1233
// Set the user's status because it was not displayed in the form.
1234
$merge_data['status'] = variable_get('user_register', 1) == 1;
1236
$account = user_save('', array_merge($form_values, $merge_data));
1237
watchdog('user', t('New user: %name %email.', array('%name' => $name, '%email' => '<'. $mail .'>')), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit'));
1239
$variables = array('!username' => $name, '!site' => variable_get('site_name', 'Drupal'), '!password' => $pass, '!uri' => $base_url, '!uri_brief' => substr($base_url, strlen('http://')), '!mailto' => $mail, '!date' => format_date(time()), '!login_uri' => url('user', NULL, NULL, TRUE), '!edit_uri' => url('user/'. $account->uid .'/edit', NULL, NULL, TRUE), '!login_url' => user_pass_reset_url($account));
1241
// The first user may login immediately, and receives a customized welcome e-mail.
1242
if ($account->uid == 1) {
1243
drupal_mail('user-register-admin', $mail, t('Drupal user account details for !s', array('!s' => $name)), strtr(t("!username,\n\nYou may now login to !uri using the following username and password:\n\n username: !username\n password: !password\n\n!edit_uri\n\n--drupal"), $variables), $from);
1244
drupal_set_message(t('<p>Welcome to Drupal. You are user #1, which gives you full and immediate access. All future registrants will receive their passwords via e-mail, so please make sure your website e-mail address is set properly under the general settings on the <a href="@settings">site information settings page</a>.</p><p> Your password is <strong>%pass</strong>. You may change your password below.</p>', array('%pass' => $pass, '@settings' => url('admin/settings/site-information'))));
1245
user_authenticate($account->name, trim($pass));
1247
return 'user/1/edit';
1250
if ($admin && !$notify) {
1251
drupal_set_message(t('Created a new user account. No e-mail has been sent.'));
1253
else if (!variable_get('user_email_verification', TRUE) && $account->status && !$admin) {
1254
// No e-mail verification is required, create new user account, and login user immediately.
1255
$subject = _user_mail_text('welcome_subject', $variables);
1256
$body = _user_mail_text('welcome_body', $variables);
1257
drupal_mail('user-register-welcome', $mail, $subject, $body, $from);
1258
user_authenticate($account->name, trim($pass));
1261
else if ($account->status || $notify) {
1262
// Create new user account, no administrator approval required.
1263
$subject = $notify ? _user_mail_text('admin_subject', $variables) : _user_mail_text('welcome_subject', $variables);
1264
$body = $notify ? _user_mail_text('admin_body', $variables) : _user_mail_text('welcome_body', $variables);
1266
drupal_mail(($notify ? 'user-register-notify' : 'user-register-welcome'), $mail, $subject, $body, $from);
1269
drupal_set_message(t('Password and further instructions have been e-mailed to the new user %user.', array('%user' => $name)));
1272
drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.'));
1277
// Create new user account, administrator approval required.
1278
$subject = _user_mail_text('approval_subject', $variables);
1279
$body = _user_mail_text('approval_body', $variables);
1281
drupal_mail('user-register-approval-user', $mail, $subject, $body, $from);
1282
drupal_mail('user-register-approval-admin', $from, $subject, t("!username has applied for an account.\n\n!edit_uri", $variables), $from);
1283
drupal_set_message(t('Thank you for applying for an account. Your account is currently pending approval by the site administrator.<br />In the meantime, your password and further instructions have been sent to your e-mail address.'));
1289
function user_edit_form($uid, $edit, $register = FALSE) {
1290
$admin = user_access('administer users');
1292
// Account information:
1293
$form['account'] = array('#type' => 'fieldset',
1294
'#title' => t('Account information'),
1296
if (user_access('change own username') || $admin || $register) {
1297
$form['account']['name'] = array('#type' => 'textfield',
1298
'#title' => t('Username'),
1299
'#default_value' => $edit['name'],
1300
'#maxlength' => USERNAME_MAX_LENGTH,
1301
'#description' => t('Your preferred username; punctuation is not allowed except for periods, hyphens, and underscores.'),
1302
'#required' => TRUE,
1305
$form['account']['mail'] = array('#type' => 'textfield',
1306
'#title' => t('E-mail address'),
1307
'#default_value' => $edit['mail'],
1308
'#maxlength' => EMAIL_MAX_LENGTH,
1309
'#description' => t('A valid e-mail address. All e-mails from the system will be sent to this address. The e-mail address is not made public and will only be used if you wish to receive a new password or wish to receive certain news or notifications by e-mail.'),
1310
'#required' => TRUE,
1313
$form['account']['pass'] = array('#type' => 'password_confirm',
1314
'#description' => t('To change the current user password, enter the new password in both fields.'),
1318
elseif (!variable_get('user_email_verification', TRUE) || $admin) {
1319
$form['account']['pass'] = array(
1320
'#type' => 'password_confirm',
1321
'#description' => t('Provide a password for the new account in both fields.'),
1322
'#required' => TRUE,
1327
$form['account']['status'] = array('#type' => 'radios', '#title' => t('Status'), '#default_value' => isset($edit['status']) ? $edit['status'] : 1, '#options' => array(t('Blocked'), t('Active')));
1329
if (user_access('administer access control')) {
1330
$roles = user_roles(1);
1331
unset($roles[DRUPAL_AUTHENTICATED_RID]);
1333
$form['account']['roles'] = array('#type' => 'checkboxes', '#title' => t('Roles'), '#default_value' => array_keys((array)$edit['roles']), '#options' => $roles, '#description' => t('The user receives the combined permissions of the %au role, and all roles selected here.', array('%au' => t('authenticated user'))));
1338
if (variable_get('user_pictures', 0) && !$register) {
1339
$form['picture'] = array('#type' => 'fieldset', '#title' => t('Picture'), '#weight' => 1);
1340
$picture = theme('user_picture', (object)$edit);
1342
$form['picture']['current_picture'] = array('#value' => $picture);
1343
$form['picture']['picture_delete'] = array('#type' => 'checkbox', '#title' => t('Delete picture'), '#description' => t('Check this box to delete your current picture.'));
1346
$form['picture']['picture_delete'] = array('#type' => 'hidden');
1348
$form['picture']['picture_upload'] = array('#type' => 'file', '#title' => t('Upload picture'), '#size' => 48, '#description' => t('Your virtual face or picture. Maximum dimensions are %dimensions and the maximum size is %size kB.', array('%dimensions' => variable_get('user_picture_dimensions', '85x85'), '%size' => variable_get('user_picture_file_size', '30'))) .' '. variable_get('user_picture_guidelines', ''));
1354
function _user_edit_validate($uid, &$edit) {
1355
$user = user_load(array('uid' => $uid));
1356
// Validate the username:
1357
if (user_access('change own username') || user_access('administer users') || arg(1) == 'register') {
1358
if ($error = user_validate_name($edit['name'])) {
1359
form_set_error('name', $error);
1361
else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(name) = LOWER('%s')", $uid, $edit['name'])) > 0) {
1362
form_set_error('name', t('The name %name is already taken.', array('%name' => $edit['name'])));
1364
else if (drupal_is_denied('user', $edit['name'])) {
1365
form_set_error('name', t('The name %name has been denied access.', array('%name' => $edit['name'])));
1369
// Validate the e-mail address:
1370
if ($error = user_validate_mail($edit['mail'])) {
1371
form_set_error('mail', $error);
1373
else if (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != %d AND LOWER(mail) = LOWER('%s')", $uid, $edit['mail'])) > 0) {
1374
form_set_error('mail', t('The e-mail address %email is already registered. <a href="@password">Have you forgotten your password?</a>', array('%email' => $edit['mail'], '@password' => url('user/password'))));
1376
else if (drupal_is_denied('mail', $edit['mail'])) {
1377
form_set_error('mail', t('The e-mail address %email has been denied access.', array('%email' => $edit['mail'])));
1380
// If required, validate the uploaded picture.
1381
if ($file = file_check_upload('picture_upload')) {
1382
user_validate_picture($file, $edit, $user);
1386
function _user_edit_submit($uid, &$edit) {
1387
$user = user_load(array('uid' => $uid));
1388
// Delete picture if requested, and if no replacement picture was given.
1389
if ($edit['picture_delete']) {
1390
if ($user->picture && file_exists($user->picture)) {
1391
file_delete($user->picture);
1393
$edit['picture'] = '';
1395
if (isset($edit['roles'])) {
1396
$edit['roles'] = array_filter($edit['roles']);
1400
function user_edit($category = 'account') {
1403
$account = user_load(array('uid' => arg(1)));
1404
if ($account === FALSE) {
1405
drupal_set_message(t('The account does not exist or has already been deleted.'));
1406
drupal_goto('admin/user/user');
1408
$edit = $_POST['op'] ? $_POST : (array)$account;
1410
if (arg(2) == 'delete') {
1411
if ($edit['confirm']) {
1412
user_delete($edit, $account->uid);
1413
drupal_goto('admin/user/user');
1416
return drupal_get_form('user_confirm_delete', $account->name, $account->uid);
1419
else if ($_POST['op'] == t('Delete')) {
1420
if ($_REQUEST['destination']) {
1421
$destination = drupal_get_destination();
1422
unset($_REQUEST['destination']);
1424
// Note: we redirect from user/uid/edit to user/uid/delete to make the tabs disappear.
1425
drupal_goto("user/$account->uid/delete", $destination);
1428
$form = _user_forms($edit, $account, $category);
1429
$form['_category'] = array('#type' => 'value', '#value' => $category);
1430
$form['_account'] = array('#type' => 'value', '#value' => $account);
1431
$form['submit'] = array('#type' => 'submit', '#value' => t('Submit'), '#weight' => 30);
1432
if (user_access('administer users')) {
1433
$form['delete'] = array('#type' => 'submit', '#value' => t('Delete'), '#weight' => 31);
1435
$form['#attributes']['enctype'] = 'multipart/form-data';
1437
drupal_set_title(check_plain($account->name));
1441
function user_confirm_delete($name, $uid) {
1442
return confirm_form(array(),
1443
t('Are you sure you want to delete the account %name?', array('%name' => $name)),
1445
t('All submissions made by this user will be attributed to the anonymous account. This action cannot be undone.'),
1446
t('Delete'), t('Cancel'));
1452
* @param $edit An array of submitted form values.
1453
* @param $uid The user ID of the user to delete.
1455
function user_delete($edit, $uid) {
1456
$account = user_load(array('uid' => $uid));
1457
sess_destroy_uid($uid);
1458
db_query('DELETE FROM {users} WHERE uid = %d', $uid);
1459
db_query('DELETE FROM {users_roles} WHERE uid = %d', $uid);
1460
db_query('DELETE FROM {authmap} WHERE uid = %d', $uid);
1461
$array = array('%name' => $account->name, '%email' => '<'. $account->mail .'>');
1462
watchdog('user', t('Deleted user: %name %email.', $array), WATCHDOG_NOTICE);
1463
drupal_set_message(t('%name has been deleted.', $array));
1464
module_invoke_all('user', 'delete', $edit, $account);
1467
function user_edit_validate($form_id, $form_values) {
1468
user_module_invoke('validate', $form_values, $form_values['_account'], $form_values['_category']);
1469
// Validate input to ensure that non-privileged users can't alter protected data.
1470
if ((!user_access('administer users') && array_intersect(array_keys($form_values), array('uid', 'init', 'session'))) || (!user_access('administer access control') && isset($form_values['roles']))) {
1471
$message = t('Detected malicious attempt to alter protected user fields.');
1472
watchdog('security', $message, WATCHDOG_WARNING);
1473
// set this to a value type field
1474
form_set_error('category', $message);
1478
function user_edit_submit($form_id, $form_values) {
1479
$account = $form_values['_account'];
1480
$category = $form_values['_category'];
1481
unset($form_values['_account'], $form_values['op'], $form_values['submit'], $form_values['delete'], $form_values['form_token'], $form_values['form_id'], $form_values['_category']);
1482
user_module_invoke('submit', $form_values, $account, $category);
1483
user_save($account, $form_values, $category);
1485
// Delete that user's menu cache:
1486
cache_clear_all($account->uid .':', 'cache_menu', TRUE);
1488
// Clear the page cache because pages can contain usernames and/or profile information:
1491
drupal_set_message(t('The changes have been saved.'));
1492
return 'user/'. $account->uid;
1495
function user_view($uid = 0) {
1498
$account = user_load(array('uid' => $uid));
1499
if ($account === FALSE || ($account->access == 0 && !user_access('administer users'))) {
1500
return drupal_not_found();
1502
// Retrieve and merge all profile fields:
1504
foreach (module_list() as $module) {
1505
if ($data = module_invoke($module, 'user', 'view', '', $account)) {
1506
foreach ($data as $category => $items) {
1507
foreach ($items as $key => $item) {
1508
$item['class'] = "$module-". $item['class'];
1509
$fields[$category][$key] = $item;
1515
// Let modules change the returned fields - useful for personal privacy
1516
// controls. Since modules communicate changes by reference, we cannot use
1517
// module_invoke_all().
1518
foreach (module_implements('profile_alter') as $module) {
1519
$function = $module .'_profile_alter';
1520
$function($account, $fields);
1523
drupal_set_title(check_plain($account->name));
1524
return theme('user_profile', $account, $fields);
1527
/*** Administrative features ***********************************************/
1529
function _user_mail_text($messageid, $variables = array()) {
1531
// Check if an admin setting overrides the default string.
1532
if ($admin_setting = variable_get('user_mail_'. $messageid, FALSE)) {
1533
return strtr($admin_setting, $variables);
1535
// No override, return with default strings.
1537
switch ($messageid) {
1538
case 'welcome_subject':
1539
return t('Account details for !username at !site', $variables);
1540
case 'welcome_body':
1541
return t("!username,\n\nThank you for registering at !site. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n-- !site team", $variables);
1542
case 'admin_subject':
1543
return t('An administrator created an account for you at !site', $variables);
1545
return t("!username,\n\nA site administrator at !site has created an account for you. You may now log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.\n\n\n-- !site team", $variables);
1546
case 'approval_subject':
1547
return t('Account details for !username at !site (pending admin approval)', $variables);
1548
case 'approval_body':
1549
return t("!username,\n\nThank you for registering at !site. Your application for an account is currently pending approval. Once it has been granted, you may log in to !login_uri using the following username and password:\n\nusername: !username\npassword: !password\n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you may wish to change your password at !edit_uri\n\n\n-- !site team", $variables);
1550
case 'pass_subject':
1551
return t('Replacement login information for !username at !site', $variables);
1553
return t("!username,\n\nA request to reset the password for your account has been made at !site.\n\nYou may now log in to !uri_brief clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.", $variables);
1558
function user_admin_check_user() {
1559
$form['user'] = array('#type' => 'fieldset', '#title' => t('Username'));
1560
$form['user']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a username to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => USERNAME_MAX_LENGTH);
1561
$form['user']['type'] = array('#type' => 'hidden', '#value' => 'user');
1562
$form['user']['submit'] = array('#type' => 'submit', '#value' => t('Check username'));
1563
$form['#base'] = 'user_admin_access_check';
1567
function user_admin_check_mail() {
1568
$form['mail'] = array('#type' => 'fieldset', '#title' => t('E-mail'));
1569
$form['mail']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter an e-mail address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => EMAIL_MAX_LENGTH);
1570
$form['mail']['type'] = array('#type' => 'hidden', '#value' => 'mail');
1571
$form['mail']['submit'] = array('#type' => 'submit', '#value' => t('Check e-mail'));
1572
$form['#base'] = 'user_admin_access_check';
1576
function user_admin_check_host() {
1577
$form['host'] = array('#type' => 'fieldset', '#title' => t('Hostname'));
1578
$form['host']['test'] = array('#type' => 'textfield', '#title' => '', '#description' => t('Enter a hostname or IP address to check if it will be denied or allowed.'), '#size' => 30, '#maxlength' => 64);
1579
$form['host']['type'] = array('#type' => 'hidden', '#value' => 'host');
1580
$form['host']['submit'] = array('#type' => 'submit', '#value' => t('Check hostname'));
1581
$form['#base'] = 'user_admin_access_check';
1586
* Menu callback: check an access rule
1588
function user_admin_access_check() {
1589
$output = drupal_get_form('user_admin_check_user');
1590
$output .= drupal_get_form('user_admin_check_mail');
1591
$output .= drupal_get_form('user_admin_check_host');
1595
function user_admin_access_check_validate($form_id, $form_values) {
1596
if (empty($form_values['test'])) {
1597
form_set_error($form_values['type'], t('No value entered. Please enter a test string and try again.'));
1601
function user_admin_access_check_submit($form_id, $form_values) {
1602
switch ($form_values['type']) {
1604
if (drupal_is_denied('user', $form_values['test'])) {
1605
drupal_set_message(t('The username %name is not allowed.', array('%name' => $form_values['test'])));
1608
drupal_set_message(t('The username %name is allowed.', array('%name' => $form_values['test'])));
1612
if (drupal_is_denied('mail', $form_values['test'])) {
1613
drupal_set_message(t('The e-mail address %mail is not allowed.', array('%mail' => $form_values['test'])));
1616
drupal_set_message(t('The e-mail address %mail is allowed.', array('%mail' => $form_values['test'])));
1620
if (drupal_is_denied('host', $form_values['test'])) {
1621
drupal_set_message(t('The hostname %host is not allowed.', array('%host' => $form_values['test'])));
1624
drupal_set_message(t('The hostname %host is allowed.', array('%host' => $form_values['test'])));
1633
* Menu callback: add an access rule
1635
function user_admin_access_add($mask = NULL, $type = NULL) {
1636
if ($edit = $_POST) {
1637
if (!$edit['mask']) {
1638
form_set_error('mask', t('You must enter a mask.'));
1641
$aid = db_next_id('{access}_aid');
1642
db_query("INSERT INTO {access} (aid, mask, type, status) VALUES ('%s', '%s', '%s', %d)", $aid, $edit['mask'], $edit['type'], $edit['status']);
1643
drupal_set_message(t('The access rule has been added.'));
1644
drupal_goto('admin/user/rules');
1648
$edit['mask'] = $mask;
1649
$edit['type'] = $type;
1651
return drupal_get_form('user_admin_access_add_form', $edit, t('Add rule'));
1655
* Menu callback: delete an access rule
1657
function user_admin_access_delete_confirm($aid = 0) {
1658
$access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host'));
1659
$edit = db_fetch_object(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid));
1662
$form['aid'] = array('#type' => 'hidden', '#value' => $aid);
1663
$output = confirm_form($form,
1664
t('Are you sure you want to delete the @type rule for %rule?', array('@type' => $access_types[$edit->type], '%rule' => $edit->mask)),
1666
t('This action cannot be undone.'),
1672
function user_admin_access_delete_confirm_submit($form_id, $form_values) {
1673
db_query('DELETE FROM {access} WHERE aid = %d', $form_values['aid']);
1674
drupal_set_message(t('The access rule has been deleted.'));
1675
return 'admin/user/rules';
1679
* Menu callback: edit an access rule
1681
function user_admin_access_edit($aid = 0) {
1682
if ($edit = $_POST) {
1683
if (!$edit['mask']) {
1684
form_set_error('mask', t('You must enter a mask.'));
1687
db_query("UPDATE {access} SET mask = '%s', type = '%s', status = '%s' WHERE aid = %d", $edit['mask'], $edit['type'], $edit['status'], $aid);
1688
drupal_set_message(t('The access rule has been saved.'));
1689
drupal_goto('admin/user/rules');
1693
$edit = db_fetch_array(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid));
1695
return drupal_get_form('user_admin_access_edit_form', $edit, t('Save rule'));
1698
function user_admin_access_form($edit, $submit) {
1699
$form['status'] = array(
1700
'#type' => 'radios',
1701
'#title' => t('Access type'),
1702
'#default_value' => $edit['status'],
1703
'#options' => array('1' => t('Allow'), '0' => t('Deny')),
1705
$type_options = array('user' => t('Username'), 'mail' => t('E-mail'), 'host' => t('Host'));
1706
$form['type'] = array(
1707
'#type' => 'radios',
1708
'#title' => t('Rule type'),
1709
'#default_value' => (isset($type_options[$edit['type']]) ? $edit['type'] : 'user'),
1710
'#options' => $type_options,
1712
$form['mask'] = array(
1713
'#type' => 'textfield',
1714
'#title' => t('Mask'),
1717
'#default_value' => $edit['mask'],
1718
'#description' => '%: '. t('Matches any number of characters, even zero characters') .'.<br />_: '. t('Matches exactly one character.'),
1719
'#required' => TRUE,
1721
$form['submit'] = array('#type' => 'submit', '#value' => $submit);
1727
* Menu callback: list all access rules
1729
function user_admin_access() {
1730
$header = array(array('data' => t('Access type'), 'field' => 'status'), array('data' => t('Rule type'), 'field' => 'type'), array('data' => t('Mask'), 'field' => 'mask'), array('data' => t('Operations'), 'colspan' => 2));
1731
$result = db_query("SELECT aid, type, status, mask FROM {access}". tablesort_sql($header));
1732
$access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host'));
1734
while ($rule = db_fetch_object($result)) {
1735
$rows[] = array($rule->status ? t('allow') : t('deny'), $access_types[$rule->type], $rule->mask, l(t('edit'), 'admin/user/rules/edit/'. $rule->aid), l(t('delete'), 'admin/user/rules/delete/'. $rule->aid));
1737
if (count($rows) == 0) {
1738
$rows[] = array(array('data' => '<em>'. t('There are currently no access rules.') .'</em>', 'colspan' => 5));
1740
$output .= theme('table', $header, $rows);
1746
* Retrieve an array of roles matching specified conditions.
1748
* @param $membersonly
1749
* Set this to TRUE to exclude the 'anonymous' role.
1750
* @param $permission
1751
* A string containing a permission. If set, only roles containing that permission are returned.
1754
* An associative array with the role id as the key and the role name as value.
1756
function user_roles($membersonly = 0, $permission = 0) {
1760
$result = db_query("SELECT r.* FROM {role} r INNER JOIN {permission} p ON r.rid = p.rid WHERE p.perm LIKE '%%%s%%' ORDER BY r.name", $permission);
1763
$result = db_query('SELECT * FROM {role} ORDER BY name');
1765
while ($role = db_fetch_object($result)) {
1766
if (!$membersonly || ($membersonly && $role->rid != DRUPAL_ANONYMOUS_RID)) {
1767
$roles[$role->rid] = $role->name;
1774
* Menu callback: administer permissions.
1776
function user_admin_perm($rid = NULL) {
1777
if (is_numeric($rid)) {
1778
$result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid WHERE r.rid = %d', $rid);
1781
$result = db_query('SELECT r.rid, p.perm FROM {role} r LEFT JOIN {permission} p ON r.rid = p.rid ORDER BY name');
1784
// Compile role array:
1785
// Add a comma at the end so when searching for a permission, we can
1786
// always search for "$perm," to make sure we do not confuse
1787
// permissions that are substrings of each other.
1788
while ($role = db_fetch_object($result)) {
1789
$role_permissions[$role->rid] = $role->perm .',';
1792
if (is_numeric($rid)) {
1793
$result = db_query('SELECT rid, name FROM {role} r WHERE r.rid = %d ORDER BY name', $rid);
1796
$result = db_query('SELECT rid, name FROM {role} ORDER BY name');
1799
$role_names = array();
1800
while ($role = db_fetch_object($result)) {
1801
$role_names[$role->rid] = $role->name;
1804
// Render role/permission overview:
1806
foreach (module_list(FALSE, FALSE, TRUE) as $module) {
1807
if ($permissions = module_invoke($module, 'perm')) {
1808
$form['permission'][] = array(
1809
'#value' => $module,
1811
asort($permissions);
1812
foreach ($permissions as $perm) {
1813
$options[$perm] = '';
1814
$form['permission'][$perm] = array('#value' => t($perm));
1815
foreach ($role_names as $rid => $name) {
1816
// Builds arrays for checked boxes for each role
1817
if (strpos($role_permissions[$rid], $perm .',') !== FALSE) {
1818
$status[$rid][] = $perm;
1825
// Have to build checkboxes here after checkbox arrays are built
1826
foreach ($role_names as $rid => $name) {
1827
$form['checkboxes'][$rid] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => $status[$rid]);
1828
$form['role_names'][$rid] = array('#value' => $name, '#tree' => TRUE);
1830
$form['submit'] = array('#type' => 'submit', '#value' => t('Save permissions'));
1835
function theme_user_admin_perm($form) {
1836
foreach (element_children($form['permission']) as $key) {
1837
// Don't take form control structures
1838
if (is_array($form['permission'][$key])) {
1841
if (is_numeric($key)) {
1842
$row[] = array('data' => t('@module module', array('@module' => drupal_render($form['permission'][$key]))), 'class' => 'module', 'id' => 'module-'. $form['permission'][$key]['#value'], 'colspan' => count($form['role_names']) + 1);
1845
$row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => 'permission');
1846
foreach (element_children($form['checkboxes']) as $rid) {
1847
if (is_array($form['checkboxes'][$rid])) {
1848
$row[] = array('data' => drupal_render($form['checkboxes'][$rid][$key]), 'align' => 'center', 'title' => t($key));
1855
$header[] = (t('Permission'));
1856
foreach (element_children($form['role_names']) as $rid) {
1857
if (is_array($form['role_names'][$rid])) {
1858
$header[] = drupal_render($form['role_names'][$rid]);
1861
$output = theme('table', $header, $rows, array('id' => 'permissions'));
1862
$output .= drupal_render($form);
1866
function user_admin_perm_submit($form_id, $form_values) {
1867
// Save permissions:
1868
$result = db_query('SELECT * FROM {role}');
1869
while ($role = db_fetch_object($result)) {
1870
if (isset($form_values[$role->rid])) {
1871
// Delete, so if we clear every checkbox we reset that role;
1872
// otherwise permissions are active and denied everywhere.
1873
db_query('DELETE FROM {permission} WHERE rid = %d', $role->rid);
1874
$form_values[$role->rid] = array_filter($form_values[$role->rid]);
1875
if (count($form_values[$role->rid])) {
1876
db_query("INSERT INTO {permission} (rid, perm) VALUES (%d, '%s')", $role->rid, implode(', ', array_keys($form_values[$role->rid])));
1881
drupal_set_message(t('The changes have been saved.'));
1883
// Clear the cached pages and menus:
1889
* Menu callback: administer roles.
1891
function user_admin_role() {
1894
if (DRUPAL_ANONYMOUS_RID == $id || DRUPAL_AUTHENTICATED_RID == $id) {
1895
drupal_goto('admin/user/roles');
1897
// Display the edit role form.
1898
$role = db_fetch_object(db_query('SELECT * FROM {role} WHERE rid = %d', $id));
1899
$form['name'] = array(
1900
'#type' => 'textfield',
1901
'#title' => t('Role name'),
1902
'#default_value' => $role->name,
1904
'#required' => TRUE,
1906
'#description' => t('The name for this role. Example: "moderator", "editorial board", "site architect".'),
1908
$form['rid'] = array(
1912
$form['submit'] = array(
1913
'#type' => 'submit',
1914
'#value' => t('Save role'),
1916
$form['delete'] = array(
1917
'#type' => 'submit',
1918
'#value' => t('Delete role'),
1922
$form['name'] = array(
1923
'#type' => 'textfield',
1927
$form['submit'] = array(
1928
'#type' => 'submit',
1929
'#value' => t('Add role'),
1931
$form['#base'] = 'user_admin_role';
1936
function user_admin_role_validate($form_id, $form_values) {
1937
if ($form_values['name']) {
1938
if ($form_values['op'] == t('Save role')) {
1939
if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s' AND rid != %d", $form_values['name'], $form_values['rid']))) {
1940
form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_values['name'])));
1943
else if ($form_values['op'] == t('Add role')) {
1944
if (db_result(db_query("SELECT COUNT(*) FROM {role} WHERE name = '%s'", $form_values['name']))) {
1945
form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_values['name'])));
1950
form_set_error('name', t('You must specify a valid role name.'));
1954
function user_admin_role_submit($form_id, $form_values) {
1955
if ($form_values['op'] == t('Save role')) {
1956
db_query("UPDATE {role} SET name = '%s' WHERE rid = %d", $form_values['name'], $form_values['rid']);
1957
drupal_set_message(t('The role has been renamed.'));
1959
else if ($form_values['op'] == t('Delete role')) {
1960
db_query('DELETE FROM {role} WHERE rid = %d', $form_values['rid']);
1961
db_query('DELETE FROM {permission} WHERE rid = %d', $form_values['rid']);
1962
// Update the users who have this role set:
1963
db_query('DELETE FROM {users_roles} WHERE rid = %d', $form_values['rid']);
1965
drupal_set_message(t('The role has been deleted.'));
1967
else if ($form_values['op'] == t('Add role')) {
1968
db_query("INSERT INTO {role} (name) VALUES ('%s')", $form_values['name']);
1969
drupal_set_message(t('The role has been added.'));
1971
return 'admin/user/roles';
1974
function theme_user_admin_new_role($form) {
1975
$header = array(t('Name'), array('data' => t('Operations'), 'colspan' => 2));
1976
foreach (user_roles() as $rid => $name) {
1977
$edit_permissions = l(t('edit permissions'), 'admin/user/access/'. $rid);
1978
if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
1979
$rows[] = array($name, l(t('edit role'), 'admin/user/roles/edit/'. $rid), $edit_permissions);
1982
$rows[] = array($name, t('locked'), $edit_permissions);
1985
$rows[] = array(drupal_render($form['name']), array('data' => drupal_render($form['submit']), colspan => 2));
1987
$output = drupal_render($form);
1988
$output .= theme('table', $header, $rows);
1993
function user_admin_account() {
1994
$filter = user_build_filter_query();
1998
array('data' => t('Username'), 'field' => 'u.name'),
1999
array('data' => t('Status'), 'field' => 'u.status'),
2001
array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
2002
array('data' => t('Last access'), 'field' => 'u.access'),
2006
$sql = 'SELECT DISTINCT u.uid, u.name, u.status, u.created, u.access FROM {users} u LEFT JOIN {users_roles} ur ON u.uid = ur.uid '. $filter['join'] .' WHERE u.uid != 0 '. $filter['where'];
2007
$sql .= tablesort_sql($header);
2008
$result = pager_query($sql, 50, 0, NULL, $filter['args']);
2010
$form['options'] = array(
2011
'#type' => 'fieldset',
2012
'#title' => t('Update options'),
2013
'#prefix' => '<div class="container-inline">',
2014
'#suffix' => '</div>',
2017
foreach (module_invoke_all('user_operations') as $operation => $array) {
2018
$options[$operation] = $array['label'];
2020
$form['options']['operation'] = array(
2021
'#type' => 'select',
2022
'#options' => $options,
2023
'#default_value' => 'unblock',
2025
$form['options']['submit'] = array(
2026
'#type' => 'submit',
2027
'#value' => t('Update'),
2030
$destination = drupal_get_destination();
2032
$status = array(t('blocked'), t('active'));
2033
$roles = user_roles(1);
2035
while ($account = db_fetch_object($result)) {
2036
$accounts[$account->uid] = '';
2037
$form['name'][$account->uid] = array('#value' => theme('username', $account));
2038
$form['status'][$account->uid] = array('#value' => $status[$account->status]);
2039
$users_roles = array();
2040
$roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = %d', $account->uid);
2041
while ($user_role = db_fetch_object($roles_result)) {
2042
$users_roles[] = $roles[$user_role->rid];
2044
asort($users_roles);
2045
$form['roles'][$account->uid][0] = array('#value' => theme('item_list', $users_roles));
2046
$form['member_for'][$account->uid] = array('#value' => format_interval(time() - $account->created));
2047
$form['last_access'][$account->uid] = array('#value' => $account->access ? t('@time ago', array('@time' => format_interval(time() - $account->access))) : t('never'));
2048
$form['operations'][$account->uid] = array('#value' => l(t('edit'), "user/$account->uid/edit", array(), $destination));
2050
$form['accounts'] = array(
2051
'#type' => 'checkboxes',
2052
'#options' => $accounts
2054
$form['pager'] = array('#value' => theme('pager', NULL, 50, 0));
2060
* Theme user administration overview.
2062
function theme_user_admin_account($form) {
2065
theme('table_select_header_cell'),
2066
array('data' => t('Username'), 'field' => 'u.name'),
2067
array('data' => t('Status'), 'field' => 'u.status'),
2069
array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'),
2070
array('data' => t('Last access'), 'field' => 'u.access'),
2074
$output = drupal_render($form['options']);
2075
if (isset($form['name']) && is_array($form['name'])) {
2076
foreach (element_children($form['name']) as $key) {
2078
drupal_render($form['accounts'][$key]),
2079
drupal_render($form['name'][$key]),
2080
drupal_render($form['status'][$key]),
2081
drupal_render($form['roles'][$key]),
2082
drupal_render($form['member_for'][$key]),
2083
drupal_render($form['last_access'][$key]),
2084
drupal_render($form['operations'][$key]),
2089
$rows[] = array(array('data' => t('No users available.'), 'colspan' => '7'));
2092
$output .= theme('table', $header, $rows);
2093
if ($form['pager']['#value']) {
2094
$output .= drupal_render($form['pager']);
2097
$output .= drupal_render($form);
2103
* Submit the user administration update form.
2105
function user_admin_account_submit($form_id, $form_values) {
2106
$operations = module_invoke_all('user_operations');
2107
$operation = $operations[$form_values['operation']];
2108
// Filter out unchecked accounts.
2109
$accounts = array_filter($form_values['accounts']);
2110
if ($function = $operation['callback']) {
2111
// Add in callback arguments if present.
2112
if (isset($operation['callback arguments'])) {
2113
$args = array_merge(array($accounts), $operation['callback arguments']);
2116
$args = array($accounts);
2118
call_user_func_array($function, $args);
2120
cache_clear_all('*', 'cache_menu', TRUE);
2121
drupal_set_message(t('The update has been performed.'));
2125
function user_admin_account_validate($form_id, $form_values) {
2126
$form_values['accounts'] = array_filter($form_values['accounts']);
2127
if (count($form_values['accounts']) == 0) {
2128
form_set_error('', t('No users selected.'));
2133
* Implementation of hook_user_operations().
2135
function user_user_operations() {
2136
global $form_values;
2138
$operations = array(
2140
'label' => t('Unblock the selected users'),
2141
'callback' => 'user_user_operations_unblock',
2144
'label' => t('Block the selected users'),
2145
'callback' => 'user_user_operations_block',
2148
'label' => t('Delete the selected users'),
2152
if (user_access('administer access control')) {
2153
$roles = user_roles(1);
2154
unset($roles[DRUPAL_AUTHENTICATED_RID]); // Can't edit authenticated role.
2156
$add_roles = array();
2157
foreach ($roles as $key => $value) {
2158
$add_roles['add_role-'. $key] = $value;
2161
$remove_roles = array();
2162
foreach ($roles as $key => $value) {
2163
$remove_roles['remove_role-'. $key] = $value;
2166
if (count($roles)) {
2167
$role_operations = array(
2168
t('Add a role to the selected users') => array(
2169
'label' => $add_roles,
2171
t('Remove a role from the selected users') => array(
2172
'label' => $remove_roles,
2176
$operations += $role_operations;
2180
// If the form has been posted, we need to insert the proper data for role editing if necessary.
2182
$operation_rid = explode('-', $form_values['operation']);
2183
$operation = $operation_rid[0];
2184
$rid = $operation_rid[1];
2185
if ($operation == 'add_role' || $operation == 'remove_role') {
2186
if (user_access('administer access control')) {
2187
$operations[$form_values['operation']] = array(
2188
'callback' => 'user_multiple_role_edit',
2189
'callback arguments' => array($operation, $rid),
2193
watchdog('security', t('Detected malicious attempt to alter protected user fields.'), WATCHDOG_WARNING);
2203
* Callback function for admin mass unblocking users.
2205
function user_user_operations_unblock($accounts) {
2206
foreach ($accounts as $uid) {
2207
$account = user_load(array('uid' => (int)$uid));
2208
// Skip unblocking user if they are already unblocked.
2209
if ($account !== FALSE && $account->status == 0) {
2210
user_save($account, array('status' => 1));
2216
* Callback function for admin mass blocking users.
2218
function user_user_operations_block($accounts) {
2219
foreach ($accounts as $uid) {
2220
$account = user_load(array('uid' => (int)$uid));
2221
// Skip blocking user if they are already blocked.
2222
if ($account !== FALSE && $account->status == 1) {
2223
user_save($account, array('status' => 0));
2229
* Callback function for admin mass adding/deleting a user role.
2231
function user_multiple_role_edit($accounts, $operation, $rid) {
2232
// The role name is not necessary as user_save() will reload the user
2233
// object, but some modules' hook_user() may look at this first.
2234
$role_name = db_result(db_query('SELECT name FROM {role} WHERE rid = %d', $rid));
2236
switch ($operation) {
2238
foreach ($accounts as $uid) {
2239
$account = user_load(array('uid' => (int)$uid));
2240
// Skip adding the role to the user if they already have it.
2241
if ($account !== FALSE && !isset($account->roles[$rid])) {
2242
$roles = $account->roles + array($rid => $role_name);
2243
user_save($account, array('roles' => $roles));
2248
foreach ($accounts as $uid) {
2249
$account = user_load(array('uid' => (int)$uid));
2250
// Skip removing the role from the user if they already don't have it.
2251
if ($account !== FALSE && isset($account->roles[$rid])) {
2252
$roles = array_diff($account->roles, array($rid => $role_name));
2253
user_save($account, array('roles' => $roles));
2260
function user_multiple_delete_confirm() {
2263
$form['accounts'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
2264
// array_filter returns only elements with TRUE values
2265
foreach (array_filter($edit['accounts']) as $uid => $value) {
2266
$user = db_result(db_query('SELECT name FROM {users} WHERE uid = %d', $uid));
2267
$form['accounts'][$uid] = array('#type' => 'hidden', '#value' => $uid, '#prefix' => '<li>', '#suffix' => check_plain($user) ."</li>\n");
2269
$form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
2271
return confirm_form($form,
2272
t('Are you sure you want to delete these users?'),
2273
'admin/user/user', t('This action cannot be undone.'),
2274
t('Delete all'), t('Cancel'));
2277
function user_multiple_delete_confirm_submit($form_id, $form_values) {
2278
if ($form_values['confirm']) {
2279
foreach ($form_values['accounts'] as $uid => $value) {
2280
user_delete($form_values, $uid);
2282
drupal_set_message(t('The users have been deleted.'));
2284
return 'admin/user/user';
2287
function user_admin_settings() {
2288
// User registration settings.
2289
$form['registration'] = array('#type' => 'fieldset', '#title' => t('User registration settings'));
2290
$form['registration']['user_register'] = array('#type' => 'radios', '#title' => t('Public registrations'), '#default_value' => variable_get('user_register', 1), '#options' => array(t('Only site administrators can create new user accounts.'), t('Visitors can create accounts and no administrator approval is required.'), t('Visitors can create accounts but administrator approval is required.')));
2291
$form['registration']['user_email_verification'] = array('#type' => 'checkbox', '#title' => t('Require e-mail verification when a visitor creates an account'), '#default_value' => variable_get('user_email_verification', TRUE), '#description' => t('If this box is checked, new users will be required to validate their e-mail address prior to logging into to the site, and will be assigned a system-generated password. With it unchecked, users will be logged in immediately upon registering, and may select their own passwords during registration.'));
2292
$form['registration']['user_registration_help'] = array('#type' => 'textarea', '#title' => t('User registration guidelines'), '#default_value' => variable_get('user_registration_help', ''), '#description' => t("This text is displayed at the top of the user registration form. It's useful for helping or instructing your users."));
2294
// User e-mail settings.
2295
$form['email'] = array('#type' => 'fieldset', '#title' => t('User e-mail settings'));
2296
$form['email']['user_mail_welcome_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail'), '#default_value' => _user_mail_text('welcome_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
2297
$form['email']['user_mail_welcome_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail'), '#default_value' => _user_mail_text('welcome_body'), '#rows' => 15, '#description' => t('Customize the body of the welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
2298
$form['email']['user_mail_admin_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail (user created by administrator)'), '#default_value' => _user_mail_text('admin_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your welcome e-mail, which is sent to new member accounts created by an administrator.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
2299
$form['email']['user_mail_admin_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail (user created by administrator)'), '#default_value' => _user_mail_text('admin_body'), '#rows' => 15, '#description' => t('Customize the body of the welcome e-mail, which is sent to new member accounts created by an administrator.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
2300
$form['email']['user_mail_approval_subject'] = array('#type' => 'textfield', '#title' => t('Subject of welcome e-mail (awaiting admin approval)'), '#default_value' => _user_mail_text('approval_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your awaiting approval welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri, !login_url.');
2301
$form['email']['user_mail_approval_body'] = array('#type' => 'textarea', '#title' => t('Body of welcome e-mail (awaiting admin approval)'), '#default_value' => _user_mail_text('approval_body'), '#rows' => 15, '#description' => t('Customize the body of the awaiting approval welcome e-mail, which is sent to new members upon registering.') .' '. t('Available variables are:') .' !username, !site, !password, !uri, !uri_brief, !mailto, !login_uri, !edit_uri, !login_url.');
2302
$form['email']['user_mail_pass_subject'] = array('#type' => 'textfield', '#title' => t('Subject of password recovery e-mail'), '#default_value' => _user_mail_text('pass_subject'), '#maxlength' => 180, '#description' => t('Customize the subject of your forgotten password e-mail.') .' '. t('Available variables are:') .' !username, !site, !login_url, !uri, !uri_brief, !mailto, !date, !login_uri, !edit_uri.');
2303
$form['email']['user_mail_pass_body'] = array('#type' => 'textarea', '#title' => t('Body of password recovery e-mail'), '#default_value' => _user_mail_text('pass_body'), '#rows' => 15, '#description' => t('Customize the body of the forgotten password e-mail.') .' '. t('Available variables are:') .' !username, !site, !login_url, !uri, !uri_brief, !mailto, !login_uri, !edit_uri.');
2305
// If picture support is enabled, check whether the picture directory exists:
2306
if (variable_get('user_pictures', 0)) {
2307
$picture_path = file_create_path(variable_get('user_picture_path', 'pictures'));
2308
file_check_directory($picture_path, 1, 'user_picture_path');
2311
$form['pictures'] = array('#type' => 'fieldset', '#title' => t('Pictures'));
2312
$form['pictures']['user_pictures'] = array('#type' => 'radios', '#title' => t('Picture support'), '#default_value' => variable_get('user_pictures', 0), '#options' => array(t('Disabled'), t('Enabled')), '#description' => t('Enable picture support.'));
2313
$form['pictures']['user_picture_path'] = array('#type' => 'textfield', '#title' => t('Picture image path'), '#default_value' => variable_get('user_picture_path', 'pictures'), '#size' => 30, '#maxlength' => 255, '#description' => t('Subdirectory in the directory %dir where pictures will be stored.', array('%dir' => file_directory_path() .'/')));
2314
$form['pictures']['user_picture_default'] = array('#type' => 'textfield', '#title' => t('Default picture'), '#default_value' => variable_get('user_picture_default', ''), '#size' => 30, '#maxlength' => 255, '#description' => t('URL of picture to display for users with no custom picture selected. Leave blank for none.'));
2315
$form['pictures']['user_picture_dimensions'] = array('#type' => 'textfield', '#title' => t('Picture maximum dimensions'), '#default_value' => variable_get('user_picture_dimensions', '85x85'), '#size' => 15, '#maxlength' => 10, '#description' => t('Maximum dimensions for pictures, in pixels.'));
2316
$form['pictures']['user_picture_file_size'] = array('#type' => 'textfield', '#title' => t('Picture maximum file size'), '#default_value' => variable_get('user_picture_file_size', '30'), '#size' => 15, '#maxlength' => 10, '#description' => t('Maximum file size for pictures, in kB.'));
2317
$form['pictures']['user_picture_guidelines'] = array('#type' => 'textarea', '#title' => t('Picture guidelines'), '#default_value' => variable_get('user_picture_guidelines', ''), '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users."));
2319
return system_settings_form($form);
2322
function user_admin($callback_arg = '') {
2323
$op = isset($_POST['op']) ? $_POST['op'] : $callback_arg;
2328
$output = drupal_get_form('search_form', url('admin/user/search'), $_POST['keys'], 'user') . search_data($_POST['keys'], 'user');
2330
case t('Create new account'):
2332
$output = drupal_get_form('user_register');
2335
if ($_POST['accounts'] && $_POST['operation'] == 'delete') {
2336
$output = drupal_get_form('user_multiple_delete_confirm');
2339
$output = drupal_get_form('user_filter_form');
2340
$output .= drupal_get_form('user_admin_account');
2347
* Implementation of hook_help().
2349
function user_help($section) {
2353
case 'admin/help#user':
2354
$output = '<p>'. t('The user module allows users to register, login, and log out. Users benefit from being able to sign on because it associates content they create with their account and allows various permissions to be set for their roles. The user module supports user roles which can setup fine grained permissions allowing each role to do only what the administrator wants them to. Each user is assigned to one or more roles. By default there are two roles <em>anonymous</em> - a user who has not logged in, and <em>authenticated</em> a user who has signed up and who has been authorized.') .'</p>';
2355
$output .= '<p>'. t('Users can use their own name or handle and can fine tune some personal configuration settings through their individual my account page. Registered users need to authenticate by supplying either a local username and password, or a remote username and password such as DelphiForums ID, or one from a Drupal powered website. A visitor accessing your website is assigned an unique ID, the so-called session ID, which is stored in a cookie. For security\'s sake, the cookie does not contain personal information but acts as a key to retrieve the information stored on your server.') .'</p>';
2356
$output .= '<p>'. t('For more information please read the configuration and customization handbook <a href="@user">User page</a>.', array('@user' => 'http://drupal.org/handbook/modules/user/')) .'</p>';
2358
case 'admin/user/user':
2359
return '<p>'. t('Drupal allows users to register, login, log out, maintain user profiles, etc. Users of the site may not use their own names to post content until they have signed up for a user account.') .'</p>';
2360
case 'admin/user/user/create':
2361
case 'admin/user/user/account/create':
2362
return '<p>'. t('This web page allows the administrators to register a new users by hand. Note that you cannot have a user where either the e-mail address or the username match another user in the system.') .'</p>';
2363
case 'admin/user/rules':
2364
return '<p>'. t('Set up username and e-mail address access rules for new <em>and</em> existing accounts (currently logged in accounts will not be logged out). If a username or e-mail address for an account matches any deny rule, but not an allow rule, then the account will not be allowed to be created or to log in. A host rule is effective for every page view, not just registrations.') .'</p>';
2365
case 'admin/user/access':
2366
return '<p>'. t('Permissions let you control what users can do on your site. Each user role (defined on the <a href="@role">user roles page</a>) has its own set of permissions. For example, you could give users classified as "Administrators" permission to "administer nodes" but deny this power to ordinary, "authenticated" users. You can use permissions to reveal new features to privileged users (those with subscriptions, for example). Permissions also allow trusted users to share the administrative burden of running a busy site.', array('@role' => url('admin/user/roles'))) .'</p>';
2367
case 'admin/user/roles':
2368
return t('<p>Roles allow you to fine tune the security and administration of Drupal. A role defines a group of users that have certain privileges as defined in <a href="@permissions">user permissions</a>. Examples of roles include: anonymous user, authenticated user, moderator, administrator and so on. In this area you will define the <em>role names</em> of the various roles. To delete a role choose "edit".</p><p>By default, Drupal comes with two user roles:</p>
2370
<li>Anonymous user: this role is used for users that don\'t have a user account or that are not authenticated.</li>
2371
<li>Authenticated user: this role is automatically granted to all logged in users.</li>
2372
</ul>', array('@permissions' => url('admin/user/access')));
2373
case 'admin/user/search':
2374
return '<p>'. t('Enter a simple pattern ("*" may be used as a wildcard match) to search for a username. For example, one may search for "br" and Drupal might return "brian", "brad", and "brenda".') .'</p>';
2375
case 'user/help#user':
2376
$site = variable_get('site_name', 'Drupal');
2378
$affiliates = user_auth_help_links();
2379
if (count($affiliates)) {
2380
$affiliate_info = implode(', ', user_auth_help_links());
2383
$affiliate_info = t('one of our affiliates');
2387
<h3>Distributed authentication<a id="da"></a></h3>
2388
<p>One of the more tedious moments in visiting a new website is filling out the registration form. Here at @site, you do not have to fill out a registration form if you are already a member of !affiliate-info. This capability is called <em>distributed authentication</em>, and <a href="@drupal">Drupal</a>, the software which powers @site, fully supports it.</p>
2389
<p>Distributed authentication enables a new user to input a username and password into the login box, and immediately be recognized, even if that user never registered at @site. This works because Drupal knows how to communicate with external registration databases. For example, lets say that new user \'Joe\' is already a registered member of <a href="@delphi-forums">Delphi Forums</a>. Drupal informs Joe on registration and login screens that he may login with his Delphi ID instead of registering with @site. Joe likes that idea, and logs in with a username of joe@remote.delphiforums.com and his usual Delphi password. Drupal then contacts the <em>remote.delphiforums.com</em> server behind the scenes (usually using <a href="@xml">XML-RPC</a>, <a href="@http-post">HTTP POST</a>, or <a href="@soap">SOAP</a>) and asks: "Is the password for user Joe correct?". If Delphi replies yes, then we create a new @site account for Joe and log him into it. Joe may keep on logging into @site in the same manner, and he will always be logged into the same account.</p>', array('!affiliate-info' => $affiliate_info, '@site' => $site, '@drupal' => 'http://drupal.org', '@delphi-forums' => 'http://www.delphiforums.com', '@xml' => 'http://www.xmlrpc.com', '@http-post' => 'http://www.w3.org/Protocols/', '@soap' => 'http://www.soapware.org'));
2391
foreach (module_list() as $module) {
2392
if (module_hook($module, 'auth')) {
2393
$output .= "<h4><a id=\"$module\"></a>". module_invoke($module, 'info', 'name') .'</h4>';
2394
$output .= module_invoke($module, 'help', "user/help#$module");
2404
* Menu callback; Prints user-specific help information.
2406
function user_help_page() {
2407
return user_help('user/help#user');
2411
* Retrieve a list of all user setting/information categories and sort them by weight.
2413
function _user_categories($account) {
2414
$categories = array();
2416
foreach (module_list() as $module) {
2417
if ($data = module_invoke($module, 'user', 'categories', NULL, $account, '')) {
2418
$categories = array_merge($data, $categories);
2422
usort($categories, '_user_sort');
2427
function _user_sort($a, $b) {
2428
return $a['weight'] < $b['weight'] ? -1 : ($a['weight'] > $b['weight'] ? 1 : ($a['title'] < $b['title'] ? -1 : 1));
2432
* Retrieve a list of all form elements for the specified category.
2434
function _user_forms(&$edit, $account, $category, $hook = 'form') {
2436
foreach (module_list() as $module) {
2437
if ($data = module_invoke($module, 'user', $hook, $edit, $account, $category)) {
2438
$groups = array_merge_recursive($data, $groups);
2441
uasort($groups, '_user_sort');
2443
return empty($groups) ? FALSE : $groups;
2447
* Retrieve a pipe delimited string of autocomplete suggestions for existing users
2449
function user_autocomplete($string = '') {
2452
$result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER('%s%%')", $string, 0, 10);
2453
while ($user = db_fetch_object($result)) {
2454
$matches[$user->name] = check_plain($user->name);
2457
print drupal_to_js($matches);
2462
* List user administration filters that can be applied.
2464
function user_filters() {
2467
$roles = user_roles(1);
2468
unset($roles[DRUPAL_AUTHENTICATED_RID]); // Don't list authorized role.
2469
if (count($roles)) {
2470
$filters['role'] = array('title' => t('role'),
2471
'where' => "ur.rid = %d",
2472
'options' => $roles,
2477
$t_module = t('module');
2478
foreach (module_list() as $module) {
2479
if ($permissions = module_invoke($module, 'perm')) {
2480
asort($permissions);
2481
foreach ($permissions as $permission) {
2482
$options["$module $t_module"][$permission] = t($permission);
2487
$filters['permission'] = array('title' => t('permission'),
2488
'join' => 'LEFT JOIN {permission} p ON ur.rid = p.rid',
2489
'where' => " ((p.perm IS NOT NULL AND p.perm LIKE '%%%s%%') OR u.uid = 1) ",
2490
'options' => $options,
2493
$filters['status'] = array('title' => t('status'),
2494
'where' => 'u.status = %d',
2495
'options' => array(1 => t('active'), 0 => t('blocked')),
2501
* Build query for user administration filters based on session.
2503
function user_build_filter_query() {
2504
$filters = user_filters();
2507
$where = $args = $join = array();
2508
foreach ($_SESSION['user_overview_filter'] as $filter) {
2509
list($key, $value) = $filter;
2510
// This checks to see if this permission filter is an enabled permission for the authenticated role.
2511
// If so, then all users would be listed, and we can skip adding it to the filter query.
2512
if ($key == 'permission') {
2513
$account = new stdClass();
2514
$account->uid = 'user_filter';
2515
$account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);
2516
if (user_access($value, $account)) {
2520
$where[] = $filters[$key]['where'];
2522
$join[] = $filters[$key]['join'];
2524
$where = count($where) ? 'AND '. implode(' AND ', $where) : '';
2525
$join = count($join) ? ' '. implode(' ', array_unique($join)) : '';
2527
return array('where' => $where,
2534
* Return form for user administration filters.
2536
function user_filter_form() {
2537
$session = &$_SESSION['user_overview_filter'];
2538
$session = is_array($session) ? $session : array();
2539
$filters = user_filters();
2542
$form['filters'] = array('#type' => 'fieldset',
2543
'#title' => t('Show only users where'),
2544
'#theme' => 'user_filters',
2546
foreach ($session as $filter) {
2547
list($type, $value) = $filter;
2548
$string = ($i++ ? '<em>and</em> where <strong>%a</strong> is <strong>%b</strong>' : '<strong>%a</strong> is <strong>%b</strong>');
2549
// Merge an array of arrays into one if necessary.
2550
$options = $type == 'permission' ? call_user_func_array('array_merge', $filters[$type]['options']) : $filters[$type]['options'];
2551
$form['filters']['current'][] = array('#value' => t($string, array('%a' => $filters[$type]['title'] , '%b' => $options[$value])));
2554
foreach ($filters as $key => $filter) {
2555
$names[$key] = $filter['title'];
2556
$form['filters']['status'][$key] = array('#type' => 'select',
2557
'#options' => $filter['options'],
2561
$form['filters']['filter'] = array('#type' => 'radios',
2562
'#options' => $names,
2564
$form['filters']['buttons']['submit'] = array('#type' => 'submit',
2565
'#value' => (count($session) ? t('Refine') : t('Filter'))
2567
if (count($session)) {
2568
$form['filters']['buttons']['undo'] = array('#type' => 'submit',
2569
'#value' => t('Undo')
2571
$form['filters']['buttons']['reset'] = array('#type' => 'submit',
2572
'#value' => t('Reset')
2580
* Theme user administration filter form.
2582
function theme_user_filter_form($form) {
2583
$output = '<div id="user-admin-filter">';
2584
$output .= drupal_render($form['filters']);
2585
$output .= '</div>';
2586
$output .= drupal_render($form);
2591
* Theme user administration filter selector.
2593
function theme_user_filters($form) {
2594
$output = '<ul class="clear-block">';
2595
if (sizeof($form['current'])) {
2596
foreach (element_children($form['current']) as $key) {
2597
$output .= '<li>'. drupal_render($form['current'][$key]) .'</li>';
2601
$output .= '<li><dl class="multiselect">'. (sizeof($form['current']) ? '<dt><em>'. t('and') .'</em> '. t('where') .'</dt>' : '') .'<dd class="a">';
2602
foreach (element_children($form['filter']) as $key) {
2603
$output .= drupal_render($form['filter'][$key]);
2607
$output .= '<dt>'. t('is') .'</dt><dd class="b">';
2609
foreach (element_children($form['status']) as $key) {
2610
$output .= drupal_render($form['status'][$key]);
2615
$output .= '<div class="container-inline" id="user-admin-buttons">'. drupal_render($form['buttons']) .'</div>';
2616
$output .= '</li></ul>';
2622
* Process result from user administration filter form.
2624
function user_filter_form_submit($form_id, $form_values) {
2625
$op = $form_values['op'];
2626
$filters = user_filters();
2628
case t('Filter'): case t('Refine'):
2629
if (isset($form_values['filter'])) {
2630
$filter = $form_values['filter'];
2631
// Merge an array of arrays into one if necessary.
2632
$options = $filter == 'permission' ? call_user_func_array('array_merge', $filters[$filter]['options']) : $filters[$filter]['options'];
2633
if (isset($options[$form_values[$filter]])) {
2634
$_SESSION['user_overview_filter'][] = array($filter, $form_values[$filter]);
2639
array_pop($_SESSION['user_overview_filter']);
2642
$_SESSION['user_overview_filter'] = array();
2648
return 'admin/user/user';
2652
function user_forms() {
2653
$forms['user_admin_access_add_form']['callback'] = 'user_admin_access_form';
2654
$forms['user_admin_access_edit_form']['callback'] = 'user_admin_access_form';
2655
$forms['user_admin_new_role']['callback'] = 'user_admin_role';