/[drupal]/contributions/modules/userplus/userplus.module
ViewVC logotype

Contents of /contributions/modules/userplus/userplus.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.8 - (show annotations) (download) (as text)
Fri May 25 00:24:05 2007 UTC (2 years, 6 months ago) by marcp
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--2
Changes since 1.7: +73 -59 lines
File MIME type: text/x-php
Upgraded to 6.x.
1 <?php
2 // $Id: userplus.module,v 1.7 2007/03/02 23:45:58 marcp Exp $
3
4 /**
5 * @file
6 * Enhances user administration by allowing operations on multiple
7 * users at one time.
8 */
9
10 /**
11 * Implementation of hook_help().
12 */
13 function userplus_help($section) {
14 switch ($section) {
15 case 'admin/user/userplus':
16 return t('<p>This web page allows you to register new users and assign their roles. <strong>All users added this way automatically belong to the "authenticated user" role.</strong> Note that you cannot have a user where either the e-mail address or the username match another user in the system. Leave any surplus rows blank if you are only adding a few users.</p><p>It may take several runs through this page if you need to add a lot of users, however you can change the number of rows that appear on this page on the !settings page.</p>', array('!settings' => l('userplus settings', 'admin/settings/userplus')));
17 case 'admin/user/userplus/userperms':
18 return t('<p>This web page allows you to set role membership for all users at once. You can change the number of rows that appear on this page on the !settings page.</p>', array('!settings' => l('userplus settings', 'admin/settings/userplus')));
19 case 'admin/user/userplus/config':
20 return t('<p>This web page allows you to set configuration options for the "Userplus" module.</p>');
21 }
22 }
23
24 /**
25 * Implementation of hook_menu().
26 */
27 function userplus_menu() {
28 $items = array();
29
30 $items['admin/settings/userplus'] = array(
31 'title' => 'Userplus',
32 'description' => 'Settings for the userplus module.',
33 'page callback' => 'drupal_get_form',
34 'page arguments' => array('userplus_admin_settings'),
35 'access arguments' => array('administer users'),
36 'type' => MENU_NORMAL_ITEM
37 );
38
39 $items['admin/user/userplus'] = array(
40 'title' => 'Userplus',
41 'description' => 'Add multiple users; assign roles to multiple users.',
42 'page callback' => 'drupal_get_form',
43 'page arguments' => array('userplus_add_users'),
44 'access arguments' => array('administer users')
45 );
46
47 $items['admin/user/userplus/addmultiple'] = array(
48 'title' => 'add multiple users',
49 'access arguments' => array('administer users'),
50 'type' => MENU_DEFAULT_LOCAL_TASK,
51 'weight' => -2
52 );
53
54 $items['admin/user/userplus/userperms'] = array(
55 'title' => 'assign user roles',
56 'page callback' => 'drupal_get_form',
57 'page arguments' => array('userplus_admin_userperms'),
58 'access arguments' => array('administer users'),
59 'type' => MENU_LOCAL_TASK,
60 'weight' => 0
61 );
62
63 if (module_exists('og')) {
64 $items['admin/user/userplus/usergroups'] = array(
65 'title' => 'assign user groups',
66 'page callback' => 'drupal_get_form',
67 'page arguments' => array('userplus_admin_usergroups'),
68 'access arguments' => array('administer users'),
69 'type' => MENU_LOCAL_TASK,
70 'weight' => 1
71 );
72 }
73
74 return $items;
75 }
76
77 function userplus_add_users() {
78 $form['role_names'] = array('#tree' => true);
79
80 // get the list of roles, excluding AUTHENTICATED and ANONYMOUS...
81 $roles = user_roles(1);
82 unset($roles[DRUPAL_AUTHENTICATED_RID]);
83
84 foreach ($roles as $rid => $name) {
85 $form['role_names'][$rid] = array('#type' => 'value', '#value' => $name);
86 }
87
88 $form['user'] = array('#tree' => true);
89 $form['role'] = array('#tree' => true);
90
91 $max_add_users = variable_get('userplus_max_add_users', 12);
92
93 for ($i = 0; $i < $max_add_users; $i++) {
94 $form['user'][$i]['name'] =
95 array('#type' => 'textfield',
96 '#default_value' => '',
97 '#size' => 16,
98 '#maxlength' => 60);
99 $form['user'][$i]['mail'] =
100 array('#type' => 'textfield',
101 '#default_value' => '',
102 '#size' => 28,
103 '#maxlength' => 64);
104 $form['user'][$i]['pass'] =
105 array('#type' => 'password',
106 '#default_value' => '',
107 '#size' => 16,
108 '#maxlength' => 32);
109
110 foreach ($roles as $role_rid => $role_name) {
111 $form['role'][$i][$role_rid] =
112 array('#type' => 'checkbox',
113 '#default_value' => false);
114 }
115 }
116
117 $form['submit'] = array('#type' => 'submit', '#value' => t('Create accounts'));
118 return $form;
119 }
120
121 function userplus_add_users_submit($form_values, $form, $form_state) {
122 $good_edits = array();
123 $bad_edits = array();
124
125 if ($form_values) {
126 foreach ($form_values['user'] as $i => $u) {
127 // Only deal with it if the name and email address are set...
128 if ($u['name'] && $u['mail']) {
129 // Always put the user in 'authenticated user' role...
130 $u['roles'] = array(DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID);
131
132 if ($form_values['role']) {
133 foreach ($form_values['role'][$i] as $role_rid => $role_checked) {
134 if ($role_checked) {
135 $u['roles'][$role_rid] = $role_rid;
136 }
137 }
138 }
139
140 // HACK - We're going to need a unique id for any form errors, so use this index...
141 //
142 // Note that when the errors show up on the page, there won't be any information
143 // highlighted on the form because we go through with the submission anyway...
144 $error_index = 0;
145
146 // NOTE - We would rather call user_module_invoke('validate', ...) here,
147 // but it doesn't return any useful information and relies on the modules'
148 // hook_user('validate', ...) to call form_set_error()...
149 //
150 // So, instead, we do our own simple validation...
151 if (($val = _userplus_validate_user($u['name'], $u['mail'])) === true) {
152 $good_edits[] = $u;
153 }
154 else {
155 $bad_edits[] = $u;
156
157 if ($val['name']) {
158 form_set_error('name'. $error_index++, $val['name']);
159 }
160 else if ($val['mail']) {
161 form_set_error('mail'. $error_index++, $val['mail']);
162 }
163 else {
164 // This should never happen...
165 form_set_error('name'. $error_index++, t('Invalid name/e-mail address combo (%name, %email).', array('%email' => $u['mail'], '%name' => $u['name'])));
166 }
167 }
168 }
169 }
170
171 // Keep track of user names and email addresses that we are adding
172 // so we can check for duplicates...
173 $users_added = array();
174 $mails_added = array();
175
176 // Handle the good ones...
177 $message = '';
178 foreach ($good_edits as $u) {
179 // Check to see if either the user name or email is already listed
180 // on this current submission form -- if so, then we bounce the
181 // later one...
182 if (in_array($u['name'], $users_added)) {
183 form_set_error('name'. $error_index++, t('The name %name is already taken.', array('%name' => $u['name'])));
184 $bad_edits[] = $u;
185 continue;
186 }
187 else if (in_array($u['mail'], $mails_added)) {
188 form_set_error('mail'. $error_index++, t('The e-mail address %email, which was entered for user %name, is already taken.', array('%email' => $u['mail'], '%name' => $u['name'])));
189 $bad_edits[] = $u;
190 continue;
191 }
192 else {
193 $users_added[] = $u['name'];
194 $mails_added[] = $u['mail'];
195 }
196
197 watchdog('user',
198 t('New user: %name %email.',
199 array('%name' => $u['name'],
200 '%email' => '<'. $u['mail'] .'>')));
201
202 user_save('', array('name' => $u['name'],
203 'pass' => $u['pass'],
204 'init' => $u['mail'],
205 'mail' => $u['mail'],
206 'roles' => $u['roles'],
207 'status' => 1));
208
209 drupal_set_message(t('Created new user account %name.', array('%name' => $u['name'])));
210 }
211
212 drupal_set_message(format_plural(sizeof($users_added), '1 user was added.', '@count users were added.'));
213
214 // What about the bad ones? Perhaps we'd like them to show up pre-populated
215 // on this page when it gets reloaded...
216 foreach ($bad_edits as $u) {
217 // For now we aren't doing anything here...
218 }
219 }
220 }
221
222 function theme_userplus_add_users($edit) {
223 $header = array('', 'username', 'e-mail address', 'password');
224
225 foreach (element_children($edit['role_names']) as $rid) {
226 $header[] = $edit['role_names'][$rid]['#value'];
227 }
228
229 foreach (element_children($edit['user']) as $i) {
230 $user = $edit['user'][$i];
231
232 unset($row);
233
234 $row[] = array('data' => ''. ($i + 1) .'&nbsp', 'class' => 'form-index');
235 $row[] = drupal_render($user['name']);
236 $row[] = drupal_render($user['mail']);
237 $row[] = drupal_render($user['pass']);
238
239 foreach (element_children($edit['role'][$i]) as $role_rid) {
240 $row[] = drupal_render($edit['role'][$i][$role_rid]);
241 }
242
243 $rows[] = $row;
244 }
245
246 $output = theme('table', $header, $rows, array('id' => 'multi-users'));
247 $output .= drupal_render($edit['submit']);
248
249 // Don't forget the dreaded form_id -- http://drupal.org/node/38926 -- or
250 // the values won't be there when you get to your _submit handler...
251 $output .= drupal_render($edit['form_id']);
252
253 // Form_token is necessary to pass validation -- see
254 // http://drupal.org/node/89999 for more information.
255 $output .= drupal_render($edit['form_token']);
256
257 return $output;
258 }
259
260 /**
261 * Callback for array_filter below that returns
262 * true if passed in the value 1...
263 */
264 function _userplus_is_role_set($var) {
265 return ($var == 1);
266 }
267
268 // Assumes $edit['user'][uid][rid]...
269 function userplus_admin_userperms_submit($form_values, $form, $form_state) {
270 // Figure out all the users who are on this page so we can load
271 // their user object and replace the old roles with the new
272 // roles and then save the user object
273 $users = $form_values['user'];
274
275 foreach ($users as $uid => $values) {
276 $user = user_load(array('uid' => $uid));
277 if ($user) {
278 $new_roles = array_filter($users[$uid], '_userplus_is_role_set');
279
280 // Pass to user_save() the roles as an associative array where
281 // the key is role id -- doesn't matter what is pointed to, so
282 // we're always just passing in the number 1...
283 $user = user_save($user, array('roles' => $new_roles));
284 }
285 }
286
287 drupal_set_message(t('The changes have been saved.'));
288
289 // Clear the cached pages and menus:
290 cache_clear_all();
291 menu_rebuild();
292 }
293
294 function userplus_admin_userperms() {
295 // Compile user/role array:
296 $result = pager_query('SELECT u.uid, u.name FROM {users} u WHERE u.uid > 0 ORDER BY u.name', variable_get('userplus_max_show_user_roles', 25));
297 $users = array();
298 while ($user = db_fetch_object($result)) {
299 $users[$user->uid] = $user->name;
300 }
301
302 $result = db_query('SELECT ur.uid, ur.rid FROM {users_roles} ur WHERE ur.uid > 0 ORDER BY ur.uid');
303 $users_roles = array();
304 while ($user_role = db_fetch_object($result)) {
305 $users_roles[$user_role->uid][] = $user_role->rid;
306 }
307
308 // get the list of roles, excluding AUTHENTICATED and ANONYMOUS...
309 $roles = user_roles(1);
310 unset($roles[DRUPAL_AUTHENTICATED_RID]);
311
312 $form['user'] = array('#tree' => true);
313
314 $weight = 1;
315 foreach ($users as $uid => $user_name) {
316 foreach ($roles as $rid => $role_name) {
317 $checked = array_key_exists($uid, $users_roles) && is_array($users_roles[$uid]) ? in_array($rid, $users_roles[$uid]) : FALSE;
318 $form['user'][$uid][$rid] = array('#type' => 'checkbox', '#title' => $role_name, '#default_value' => $checked, '#weight' => $weight++);
319 }
320 }
321
322 // Stick the role names in the form so we can use them in the theme function...
323 $form['roles'] = array('#type' => 'value', '#value' => $roles);
324 // Stick the user names in the form so we can use them in the theme function...
325 $form['usernames'] = array('#type' => 'value', '#value' => $users);
326
327 $form['submit'] = array('#type' => 'submit', '#value' => t('Save permissions'));
328
329 return $form;
330 }
331
332 function theme_userplus_admin_userperms($edit) {
333 $rows = array();
334
335 // Render role/permission overview:
336 $header = array_merge(array(t('User')), $edit['roles']['#value']);
337
338 foreach (element_children($edit['user']) as $uid) {
339 unset($row);
340 $row[] = array('data' => l($edit['usernames']['#value'][$uid], "user/$uid/edit"), 'class' => 'username');
341 foreach (element_children($edit['user'][$uid]) as $rid) {
342 unset($edit['user'][$uid][$rid]['#title']);
343 $row[] = drupal_render($edit['user'][$uid][$rid]);
344 }
345
346 $rows[] = $row;
347 }
348
349 $output = theme('table', $header, $rows, array('id' => 'users-roles'));
350 $output .= '<br \>';
351 $output .= drupal_render($edit['submit']);
352 $output .= theme('pager', NULL, variable_get('userplus_max_show_user_roles', 25));
353
354 // Don't forget the dreaded form_id -- http://drupal.org/node/38926 -- or
355 // the values won't be there when you get to your _submit handler...
356 $output .= drupal_render($edit['form_id']);
357
358 // Form_token is necessary to pass validation -- see
359 // http://drupal.org/node/89999 for more information.
360 $output .= drupal_render($edit['form_token']);
361
362 return $output;
363 }
364
365 // Assumes $edit['user'][uid][nid]...
366 function userplus_admin_usergroups_submit($form_values, $form, $form_state) {
367 // Get the original group membership data from when
368 // the form was initially loaded...
369 $users_groups = unserialize($form_values['usersgroups']);
370
371 // Remove subscriptions for only those users that have been
372 // unsubscribed, and create subscriptions for only those users
373 // who are newly subscribed...
374 if (isset($form_values['user']) && is_array($form_values['user'])) {
375 foreach ($form_values['user'] as $uid => $groups) {
376 foreach ($groups as $nid => $state) {
377 if ($state == 0) {
378 if (isset($users_groups[$uid]) && in_array($nid, $users_groups[$uid])) {
379 og_delete_subscription($nid, $uid);
380 }
381 }
382 else {
383 if (!isset($users_groups[$uid]) || !in_array($nid, $users_groups[$uid])) {
384 og_save_subscription($nid, $uid, array('is_active' => 1, 'is_admin' => 0));
385 }
386 }
387 }
388 }
389 }
390
391 drupal_set_message(t('The changes have been saved.'));
392
393 // Clear the cached pages and menus:
394 cache_clear_all();
395 menu_rebuild();
396
397 drupal_goto($_GET['q'], drupal_get_destination());
398 }
399
400 function userplus_admin_usergroups() {
401 // Compile user/group array:
402 $result = pager_query('SELECT u.uid, u.name
403 FROM {users} u
404 WHERE u.uid > 0
405 ORDER BY u.name',
406 variable_get('userplus_max_show_user_groups', 25)
407 );
408 $users = array();
409 while ($user = db_fetch_object($result)) {
410 $users[$user->uid] = $user->name;
411 }
412
413 $result = db_query('SELECT ug.uid, ug.nid, ug.is_active
414 FROM {og_uid} ug
415 WHERE ug.nid > 0
416 ORDER BY ug.uid'
417 );
418
419 $users_groups = array();
420 while ($user_group = db_fetch_object($result)) {
421 $users_groups[$user_group->uid][] = $user_group->nid;
422 }
423
424 $result = db_query('SELECT ug.nid, n.title
425 FROM {og} ug
426 INNER JOIN {node} n
427 ON ug.nid = n.nid
428 ORDER BY n.title');
429 $group_names = array();
430 while ($group = db_fetch_object($result)) {
431 $group_names[$group->nid] = $group->title;
432 }
433
434 $form['user'] = array('#tree' => true);
435
436 $weight = 1;
437 foreach ($users as $uid => $user_name) {
438 foreach ($group_names as $nid => $goup_name) {
439 $checked = is_array($users_groups[$uid]) ? in_array($nid, $users_groups[$uid]) : FALSE;
440 $form['user'][$uid][$nid] = array('#type' => 'checkbox', '#title' => $group_name, '#default_value' => $checked, '#weight' => $weight++);
441 }
442 }
443
444 // Stick the role names in the form so we can use them in the theme function...
445 $form['groups'] = array('#value' => $group_names);
446 // Stick the user names in the form so we can use them in the theme function...
447 $form['usernames'] = array('#value' => $users);
448 // Stick the initial user-group mappings in there so we can use them in the submit handler...
449 $form['usersgroups'] = array('#type' => 'hidden', '#value' => serialize($users_groups));
450
451 $form['submit'] = array('#type' => 'submit', '#value' => t('Save groups'));
452
453 drupal_set_title('user groups');
454 return $form;
455 }
456
457 function theme_userplus_admin_usergroups($edit) {
458 $rows = array();
459
460 // Render group overview:
461 $header = array(t('User'));
462 foreach ($edit['groups']['#value'] as $nid => $name) {
463 $header[] = l($name, 'node/'. $nid);
464 }
465
466 foreach (element_children($edit['user']) as $uid) {
467 unset($row);
468 $row[] = array('data' => l($edit['usernames']['#value'][$uid], "user/$uid/edit"), 'class' => 'username');
469 foreach (element_children($edit['user'][$uid]) as $nid) {
470 unset($edit['user'][$uid][$nid]['#title']);
471 $row[] = drupal_render($edit['user'][$uid][$nid]);
472 }
473
474 $rows[] = $row;
475 }
476
477 $output = theme('table', $header, $rows, array('id' => 'users-groups'));
478 $output .= '<br \>';
479 $output .= drupal_render($edit['submit']);
480 $output .= theme('pager', NULL, variable_get('userplus_max_show_user_groups', 25));
481
482 $output .= drupal_render($edit['usersgroups']);
483
484 // Don't forget the dreaded form_id -- http://drupal.org/node/38926 -- or
485 // the values won't be there when you get to your _submit handler...
486 $output .= drupal_render($edit['form_id']);
487
488 // Form_token is necessary to pass validation -- see
489 // http://drupal.org/node/89999 for more information.
490 $output .= drupal_render($edit['form_token']);
491
492 return $output;
493 }
494
495 function userplus_admin_settings() {
496 // "add multiple users" settings
497 $form['add-multiple-users'] = array(
498 '#type' => 'fieldset',
499 '#collapsible' => true,
500 '#title' => t('"add multiple users" settings'));
501 $form['add-multiple-users']['userplus_max_add_users'] = array(
502 '#type' => 'textfield',
503 '#title' => t('Maximum number of users that can be added at once'),
504 '#default_value' => variable_get('userplus_max_add_users', '12'),
505 '#size' => 4,
506 '#maxlength' => 6,
507 '#description' => t('The number of rows that will appear on the !page page.', array('!page' => l('add multiple users', 'admin/user/userplus/addmultiple'))));
508
509 // "assign user roles" settings
510 $form['assign-user-roles'] = array(
511 '#type' => 'fieldset',
512 '#collapsible' => true,
513 '#title' => t('"assign user roles" settings'));
514 $form['assign-user-roles']['userplus_max_show_user_roles'] = array(
515 '#type' => 'textfield',
516 '#title' => t('Number of users to show per page'),
517 '#default_value' => variable_get('userplus_max_show_user_roles', '25'),
518 '#size' => 4,
519 '#maxlength' => 6,
520 '#description' => t('The number of rows that will appear, per page, when using the !page page.', array('!page' => l('assign user roles', 'admin/user/userplus/userperms'))));
521
522 if (module_exists('og')) {
523 // "assign user group" settings
524 $form['assign-user-groups'] = array(
525 '#type' => 'fieldset',
526 '#collapsible' => true,
527 '#title' => t('"assign user groups" settings'));
528 $form['assign-user-groups']['userplus_max_show_user_groups'] = array(
529 '#type' => 'textfield',
530 '#title' => t('Number of users to show per page'),
531 '#default_value' => variable_get('userplus_max_show_user_groups', '25'),
532 '#size' => 4,
533 '#maxlength' => 6,
534 '#description' => t('The number of rows that will appear, per page, when using the "assign user groups" page.'));
535 }
536
537 return system_settings_form($form);
538 }
539
540 /*
541 * _userplus_validate_user() is based on _user_edit_validate(). it would be nice to
542 * be able to call something in user.module that validates what's passed in against
543 * the users in the database without doing anything to affect the user interface.
544 *
545 * ideally we would like to call:
546 *
547 * user_module_invoke('validate', $u, $u, 'account');
548 *
549 * because this would invoke any other modules' validation for the user. unfortunately,
550 * hook_user('validate', ...) is expected to call form_set_error() when validation fails.
551 * this is a problem because multiple form_set_error('name', ...) or form_set_error('mail', ...)
552 * calls do not accumulate -- only the first one sets an error.
553 *
554 * note also that we don't bother passing in $uid since we are never going to get in
555 * here in an UPDATE situation.
556 *
557 */
558 function _userplus_validate_user($name = null, $mail = null) {
559 if ($name) {
560 // Validate the username:
561 if ($error = user_validate_name($name)) {
562 return array('name' => $error);
563 }
564 else if (db_num_rows(db_query('SELECT uid FROM {users} WHERE LOWER(name) = LOWER("%s")', $name)) > 0) {
565 return array('name' => t('The name %name is already taken.', array('%name' => $name)));
566 }
567 else if (drupal_is_denied('user', $name)) {
568 return array('name' => t('The name %name has been denied access.', array('%name' => $name)));
569 }
570 }
571
572 if ($mail) {
573 // Validate the e-mail address:
574 if ($error = user_validate_mail($mail)) {
575 return array('mail' => $error);
576 }
577 else if (db_num_rows(db_query('SELECT uid FROM {users} WHERE LOWER(mail) = LOWER("%s")', $mail)) > 0) {
578 return array('mail' => t('The e-mail address %email is already taken.', array('%email' => $mail)));
579 }
580 else if (drupal_is_denied('mail', $mail)) {
581 return array('mail' => t('The e-mail address %email has been denied access.', array('%email' => $mail)));
582 }
583 }
584
585 return true;
586 }
587
588 /**
589 * Implementation of hook_theme()...
590 */
591 function userplus_theme() {
592 return array(
593 'userplus_add_users' => array(
594 'arguments' => array('edit')
595 ),
596 'userplus_admin_usergroups' => array(
597 'arguments' => array('edit')
598 ),
599 'userplus_admin_userperms' => array(
600 'arguments' => array('edit')
601 )
602 );
603 }

  ViewVC Help
Powered by ViewVC 1.1.2