apply_for_role.module

Tracking 6.x-1.x branch
  1. drupal
    1. 6 contributions/apply_for_role/apply_for_role.module

Allows users to apply for roles.

Functions & methods

NameDescription
apply_for_role_action_info_alterImplementation of hook_action_info_alter(). *
apply_for_role_add_applyStore a role application in the database.
apply_for_role_add_role
apply_for_role_apply_accessCheck that the user is allowed to create applications and that there are roles that they don't yet belong to.
apply_for_role_apply_formImplementation of hook_form().
apply_for_role_apply_form_submit
apply_for_role_apply_for_roleImplementation of hook_apply_for_role().
apply_for_role_approved_rolesReturn an array of roles that were approved for this user.
apply_for_role_approve_applyApprove a role application and put the user into the role.
apply_for_role_available_rolesReturn an array of the roles that are available for application by a user.
apply_for_role_delete_role
apply_for_role_deny_applyDeny a role application.
apply_for_role_helpImplementation of hook_help().
apply_for_role_hook_infoImplementation of hook_hook_info().
apply_for_role_menuImplementation of hook_menu().
apply_for_role_menu_alterImplementation of hook_menu_alter().
apply_for_role_permImplementation of hook_perm().
apply_for_role_process_applicationsProcess an application and store it for admin review.
apply_for_role_remove_apply
apply_for_role_themeImplementation of hook_theme()
apply_for_role_userImplementation of hook_user().
apply_for_role_user_has_roleCheck if a user has a given role.
theme_apply_for_role_status

Constants

NameDescription
APPLY_FOR_ROLE_APPROVED
APPLY_FOR_ROLE_DENIED
APPLY_FOR_ROLE_PENDING

File

View source
  1. <?php
  2. /**
  3. * @file
  4. * Allows users to apply for roles.
  5. */
  6. define('APPLY_FOR_ROLE_PENDING', 0);
  7. define('APPLY_FOR_ROLE_APPROVED', 1);
  8. define('APPLY_FOR_ROLE_DENIED', 2);
  9. if (module_exists('token')) {
  10. module_load_include('inc', 'apply_for_role', 'apply_for_role.token');
  11. }
  12. /**
  13. * Implementation of hook_help().
  14. */
  15. function apply_for_role_help($path, $arg) {
  16. switch ($path) {
  17. case 'admin/build/trigger/apply_for_role':
  18. $explanation = '<p>'. t('Triggers are system events, such as when new content is added or when a user logs in. Trigger module combines these triggers with actions (functional tasks), such as unpublishing content or e-mailing an administrator. The <a href="@url">Actions settings page</a> contains a list of existing actions and provides the ability to create and configure additional actions.', array('@url' => url('admin/settings/actions'))) .'</p>';
  19. return $explanation .'<p>'. t('Below you can assign actions to run when certain role application related triggers happen. For example, you could email a user when their application is approved.') .'</p>';
  20. case 'admin/help#apply_for_role':
  21. return $explanation = '<p>'. t('The <em>Apply for roles</em> module allows users to apply for roles from their user page and allows administrators to easily view, approve and delete role applications.', array('@url' => url('admin/settings/apply_for_role'))) .'</p>';
  22. }
  23. }
  24. /**
  25. * Implementation of hook_perm().
  26. */
  27. function apply_for_role_perm() {
  28. return array('administer apply for role', 'approve role applications', 'apply for roles');
  29. }
  30. /**
  31. * Check that the user is allowed to create applications and that there are
  32. * roles that they don't yet belong to.
  33. */
  34. function apply_for_role_apply_access($account) {
  35. return ((!empty($account->uid))
  36. && ($GLOBALS['user']->uid == $account->uid)
  37. && (user_access('apply for roles', $account))
  38. // && (count(apply_for_role_available_roles($account))
  39. );
  40. }
  41. /**
  42. * Implementation of hook_menu().
  43. */
  44. function apply_for_role_menu() {
  45. $items['admin/settings/apply_for_role'] = array(
  46. 'title' => t('Apply for role administration'),
  47. 'description' => t('Administer which roles users can apply for.'),
  48. 'page callback' => 'drupal_get_form',
  49. 'page arguments' => array('apply_for_role_settings_form'),
  50. 'access arguments' => array('administer apply for role'),
  51. 'file' => 'apply_for_role.admin.inc',
  52. );
  53. $items['admin/user/apply_for_role'] = array(
  54. 'title' => t('Manage role applications'),
  55. 'description' => t('View, approve and delete role applications.'),
  56. 'page callback' => 'drupal_get_form',
  57. 'page arguments' => array('apply_for_role_admin_form'),
  58. 'access arguments' => array('approve role applications'),
  59. 'file' => 'apply_for_role.admin.inc',
  60. );
  61. $items['admin/user/apply_for_role/approve/%user/%'] = array(
  62. 'title' => t('Approve role application'),
  63. 'page callback' => 'drupal_get_form',
  64. 'page arguments' => array('apply_for_role_approve_form', 4, 5),
  65. 'access arguments' => array('approve role applications'),
  66. 'type' => MENU_CALLBACK,
  67. 'file' => 'apply_for_role.admin.inc',
  68. );
  69. $items['admin/user/apply_for_role/deny/%user/%'] = array(
  70. 'title' => t('Deny role application'),
  71. 'page callback' => 'drupal_get_form',
  72. 'page arguments' => array('apply_for_role_deny_form', 4, 5),
  73. 'access arguments' => array('approve role applications'),
  74. 'type' => MENU_CALLBACK,
  75. 'file' => 'apply_for_role.admin.inc',
  76. );
  77. $items['admin/user/apply_for_role/remove/%user/%'] = array(
  78. 'title' => t('Remove role application'),
  79. 'page callback' => 'drupal_get_form',
  80. 'page arguments' => array('apply_for_role_remove_form', 4, 5),
  81. 'access arguments' => array('approve role applications'),
  82. 'type' => MENU_CALLBACK,
  83. 'file' => 'apply_for_role.admin.inc',
  84. );
  85. $items['user/%user/apply_for_role'] = array(
  86. 'title' => t('Apply for role'),
  87. 'page callback' => 'drupal_get_form',
  88. 'page arguments' => array('apply_for_role_apply_form', 1),
  89. 'access callback' => 'apply_for_role_apply_access',
  90. 'access arguments' => array(1),
  91. 'type' => MENU_LOCAL_TASK,
  92. );
  93. return $items;
  94. }
  95. /**
  96. * Implementation of hook_menu_alter().
  97. */
  98. function apply_for_role_menu_alter(&$callbacks) {
  99. if (module_exists('trigger') & isset($callbacks['admin/build/trigger/apply_for_role'])) {
  100. $callbacks['admin/build/trigger/apply_for_role']['access callback'] = 'trigger_access_check';
  101. }
  102. }
  103. function theme_apply_for_role_status($status) {
  104. $statuses = array(
  105. -1 => t('Removed'),
  106. APPLY_FOR_ROLE_PENDING => t('Pending'),
  107. APPLY_FOR_ROLE_APPROVED => t('Approved'),
  108. APPLY_FOR_ROLE_DENIED => t('Denied'),
  109. );
  110. return isset($statuses[$status]) ? $statuses[$status] : t('Unknown status');
  111. }
  112. /**
  113. * User interface
  114. */
  115. /**
  116. * Implementation of hook_form().
  117. */
  118. function apply_for_role_apply_form(&$form_state, $user) {
  119. drupal_set_title(check_plain($user->name));
  120. $form = array();
  121. $filter_roles = apply_for_role_available_roles($user);
  122. if (count($filter_roles)) {
  123. $form['user'] = array(
  124. '#type' => 'value',
  125. '#value' => $user,
  126. );
  127. // List of roles that were already approved.
  128. $approved = apply_for_role_approved_roles($user);
  129. if (variable_get('apply_for_role_display_approved', 0) && count($approved)) {
  130. $form['approved'] = array(
  131. '#value' => theme('item_list', $approved, t('You have applied for these roles and were approved:')),
  132. );
  133. }
  134. $form['rid'] = array(
  135. '#type' => variable_get('apply_for_role_multiple', 0) ? 'checkboxes' : 'select',
  136. '#title' => variable_get('apply_for_role_multiple', 0) ? t('Select a role or roles') : t('Select a role'),
  137. '#options' => $filter_roles,
  138. );
  139. $form['submit'] = array(
  140. '#type' => 'submit',
  141. '#value' => t('Apply')
  142. );
  143. }
  144. else {
  145. drupal_set_message(t('No roles are available at this time.'));
  146. }
  147. return $form;
  148. }
  149. function apply_for_role_apply_form_submit($form, &$form_state) {
  150. global $user;
  151. apply_for_role_process_applications($form_state['values']['user'], $form_state['values']['rid']);
  152. $form_state['redirect'] = 'user/'. $user->uid;
  153. }
  154. /**
  155. * Implementation of hook_theme()
  156. */
  157. function apply_for_role_theme() {
  158. return array(
  159. 'apply_for_role_admin_form' => array(
  160. 'arguments' => array('form' => NULL),
  161. 'file' => 'apply_for_role.admin.inc',
  162. ),
  163. 'apply_for_role_status' => array(
  164. 'arguments' => array('status' => NULL),
  165. )
  166. );
  167. }
  168. /**
  169. * Implementation of hook_user().
  170. */
  171. function apply_for_role_user($op, &$edit, &$user, $category = NULL) {
  172. switch ($op) {
  173. case 'register':
  174. // Admin created account aren't processed by the module.
  175. if (user_access('administer users')) {
  176. break;
  177. }
  178. if (variable_get('apply_for_role_register', 0)) {
  179. $filter_roles = array();
  180. foreach (variable_get('users_apply_roles', array()) as $rid => $role) {
  181. if ($rid > 2) {
  182. $filter_roles[$rid] = $role;
  183. }
  184. }
  185. if (count($filter_roles)) {
  186. $form['apply_for_role'] = array(
  187. '#type' => 'fieldset',
  188. '#title' => t('Apply for role'),
  189. '#collapsible' => FALSE,
  190. );
  191. if ((variable_get('apply_for_role_multiple', 0) == 0) && (variable_get('apply_for_role_register', 0) == 1)) {
  192. $filter_roles[0] = t('--');
  193. ksort($filter_roles);
  194. }
  195. $form['apply_for_role']['rid'] = array(
  196. '#type' => variable_get('apply_for_role_multiple', 0) ? 'checkboxes' : 'select',
  197. '#title' => variable_get('apply_for_role_multiple', 0) ? t('Select a role or roles') : t('Select a role'),
  198. '#options' => $filter_roles,
  199. '#required' => (variable_get('apply_for_role_register', 0) == 2) ? TRUE : FALSE,
  200. );
  201. }
  202. return $form;
  203. }
  204. break;
  205. case 'insert':
  206. if ((variable_get('apply_for_role_register', 0)) && (!empty($edit['rid']))) {
  207. apply_for_role_process_applications($user, $edit['rid']);
  208. $edit['rid'] = NULL;
  209. }
  210. break;
  211. case 'delete':
  212. db_query("DELETE FROM {users_roles_apply} WHERE uid = %d", $user->uid);
  213. break;
  214. }
  215. }
  216. /**
  217. * Implementation of hook_hook_info().
  218. *
  219. * Let Drupal know about our hook_apply_for_role($op, $apply) hook so that
  220. * it can be used triggers for actions.
  221. *
  222. * We provide information on these hooks This allows admins to do things
  223. * like send an email after the user applies for a role.
  224. */
  225. function apply_for_role_hook_info() {
  226. $info = array(
  227. 'apply_for_role' => array(
  228. 'apply_for_role' => array(
  229. 'apply' => array(
  230. 'runs when' => t('When a user submits an application for a role'),
  231. ),
  232. 'approve' => array(
  233. 'runs when' => t("When an admin approves a user's application for a role"),
  234. ),
  235. 'deny' => array(
  236. 'runs when' => t("When an admin denies a user's application for a role"),
  237. ),
  238. 'remove' => array(
  239. 'runs when' => t("When an admin deletes a user's application for a role"),
  240. ),
  241. ),
  242. ),
  243. );
  244. return $info;
  245. }
  246. /**
  247. * Implementation of hook_action_info_alter().
  248. *
  249. * None of the built-in actions will be enabled for our hook by default. We
  250. * need to implement hook_action_info_alter() so that we can enable a couple.
  251. */
  252. function apply_for_role_action_info_alter(&$info) {
  253. $actions = array(
  254. 'system_message_action',
  255. 'system_send_email_action',
  256. 'token_actions_message_action',
  257. 'token_actions_send_email_action',
  258. 'token_actions_goto_action',
  259. );
  260. $ops = array('apply', 'approve', 'deny', 'remove');
  261. foreach ($actions as $action) {
  262. if (isset($info[$action])) {
  263. $info[$action]['hooks']['apply_for_role'] = $ops;
  264. }
  265. }
  266. }
  267. /**
  268. * Implementation of hook_apply_for_role().
  269. *
  270. * We implement our own event to fire triggers.
  271. *
  272. * @param $op The operation that just occured: 'apply', 'approve', 'deny', 'remove'.
  273. * @param $apply A role application object.
  274. */
  275. function apply_for_role_apply_for_role($op, $apply) {
  276. // Keep objects for reuse so that changes actions make to objects can persist.
  277. static $objects;
  278. if (!module_exists('trigger')) {
  279. return;
  280. }
  281. $user = user_load(array('uid' => $apply->uid));
  282. $apply->user = $user;
  283. $aids = _trigger_get_hook_aids('apply_for_role', $op);
  284. $context = array(
  285. 'hook' => 'apply_for_role',
  286. 'op' => $op,
  287. 'user' => $user,
  288. 'apply_for_role' => $apply,
  289. );
  290. foreach ($aids as $aid => $action_info) {
  291. if ($action_info['type'] != 'user') {
  292. if (!isset($objects[$action_info['type']])) {
  293. $objects[$action_info['type']] = _trigger_normalize_user_context($action_info['type'], $user);
  294. }
  295. $context['user'] = $user;
  296. $context['apply'] = $apply;
  297. actions_do($aid, $objects[$action_info['type']], $context);
  298. }
  299. else {
  300. actions_do($aid, $user, $context);
  301. }
  302. }
  303. }
  304. /**
  305. * Callbacks
  306. */
  307. /**
  308. * Check if a user has a given role.
  309. *
  310. * @param $uid User id
  311. * @param $rid Role id
  312. * @return Boolean
  313. */
  314. function apply_for_role_user_has_role($uid, $rid) {
  315. if (!empty($uid) && !empty($rid)) {
  316. $user = user_load(array('uid' => $uid));
  317. return (!empty($user->uid) && isset($user->roles[$rid]));
  318. }
  319. return FALSE;
  320. }
  321. /**
  322. * Return an array of the roles that are available for application by a user.
  323. *
  324. * @param $user User object
  325. * @return array keyed by role id with the role names as values.
  326. */
  327. function apply_for_role_available_roles($user) {
  328. // Get the complete list of roles (other than anonyous)...
  329. $roles = user_roles(TRUE);
  330. // ...the roles that can be applied for...
  331. $enabled = (array) variable_get('users_apply_roles', array());
  332. // Check that all of the enabled roles exist.
  333. // TODO: Catch these when they are deleted.
  334. $enabled = array_intersect($roles, $enabled);
  335. // ...the roles the user has already applied for...
  336. $applied = array();
  337. $result = db_query("SELECT rid FROM {users_roles_apply} WHERE uid = %d", $user->uid);
  338. while ($row = db_fetch_object($result)) {
  339. $applied[$row->rid] = isset($roles[$row->rid]) ? $roles[$row->rid] : t('Invalid role');
  340. }
  341. // ... now figure out what's left from the enabled roles list once you remove
  342. // those they have and those they've applied for.
  343. $used = $user->roles + $applied;
  344. return array_diff($enabled, $used);
  345. }
  346. /**
  347. * Store a role application in the database.
  348. *
  349. * @param $user User object
  350. * @param $rid Role id
  351. * @return Boolean indicating success
  352. */
  353. function apply_for_role_add_apply($user, $rid) {
  354. $uid = $user->uid;
  355. if (!apply_for_role_user_has_role($uid, $rid)) {
  356. // Check if the user has already applied for this role
  357. if (!db_result(db_query("SELECT COUNT(*) FROM {users_roles_apply} WHERE uid = %d AND rid = %d", $uid, $rid))) {
  358. $apply = (object) array('uid' => $uid, 'rid' => $rid, 'approved' => 0, 'apply_date' => time());
  359. drupal_write_record('users_roles_apply', $apply);
  360. module_invoke_all('apply_for_role', 'apply', $apply);
  361. return TRUE;
  362. }
  363. }
  364. return FALSE;
  365. }
  366. /**
  367. * Approve a role application and put the user into the role.
  368. *
  369. * @param $user User object
  370. * @param $rid Role id
  371. * @return Boolean indicating success
  372. */
  373. function apply_for_role_approve_apply($user, $rid) {
  374. $uid = $user->uid;
  375. if ($apply = db_fetch_object(db_query("SELECT * FROM {users_roles_apply} WHERE uid = %d AND rid = %d AND approved <> %d", $uid, $rid, APPLY_FOR_ROLE_APPROVED))) {
  376. apply_for_role_add_role($uid, $rid);
  377. $apply->approve_date = time();
  378. $apply->approved = APPLY_FOR_ROLE_APPROVED;
  379. drupal_write_record('users_roles_apply', $apply, array('uid', 'rid'));
  380. module_invoke_all('apply_for_role', 'approve', $apply);
  381. return TRUE;
  382. }
  383. return FALSE;
  384. }
  385. /**
  386. * Deny a role application.
  387. *
  388. * @param $user User object
  389. * @param $rid Role id
  390. * @return Boolean indicating success
  391. */
  392. function apply_for_role_deny_apply($user, $rid) {
  393. $uid = $user->uid;
  394. if ($apply = db_fetch_object(db_query("SELECT * FROM {users_roles_apply} WHERE uid = %d AND rid = %d AND approved <> %d", $uid, $rid, APPLY_FOR_ROLE_DENIED))) {
  395. apply_for_role_delete_role($uid, $rid);
  396. $apply->approve_date = time();
  397. $apply->approved = APPLY_FOR_ROLE_DENIED;
  398. drupal_write_record('users_roles_apply', $apply, array('uid', 'rid'));
  399. module_invoke_all('apply_for_role', 'deny', $apply);
  400. return TRUE;
  401. }
  402. return FALSE;
  403. }
  404. /**
  405. * Deletea role application from the database.
  406. *
  407. * @param $user User object
  408. * @param $rid Role id
  409. * @return Boolean indicating success
  410. */
  411. function apply_for_role_remove_apply($user, $rid) {
  412. $uid = $user->uid;
  413. if ($apply = db_fetch_object(db_query("SELECT * FROM {users_roles_apply} WHERE uid = %d AND rid = %d", $uid, $rid))) {
  414. apply_for_role_delete_role($uid, $rid);
  415. db_query("DELETE FROM {users_roles_apply} WHERE uid = %d AND rid = %d", $uid, $rid);
  416. $apply->approval = -1;
  417. module_invoke_all('apply_for_role', 'remove', $apply);
  418. return TRUE;
  419. }
  420. return FALSE;
  421. }
  422. function apply_for_role_add_role($uid, $rid) {
  423. if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
  424. $account = user_load(array('uid' => $uid));
  425. $myroles = $account->roles;
  426. $rolenames = user_roles(TRUE);
  427. $myroles[$rid] = $rolenames[$rid];
  428. user_save($account, array('roles' => $myroles));
  429. }
  430. }
  431. function apply_for_role_delete_role($uid, $rid) {
  432. if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
  433. $account = user_load(array('uid' => $uid));
  434. $myroles = $account->roles;
  435. unset($myroles[$rid]);
  436. user_save($account, array('roles' => $myroles));
  437. }
  438. }
  439. /**
  440. * Process an application and store it for admin review.
  441. *
  442. * @param $user User object.
  443. * @param $applications Mixed, either a role id or an array keyed by role id.
  444. */
  445. function apply_for_role_process_applications($user, $applications) {
  446. $roles = user_roles(TRUE);
  447. // They can hand in either an array keyed by role id or single role id.
  448. // Ensure we've got an array keyed by role id with the name as the value.
  449. if (is_array($applications)) {
  450. // Filter out any thing with empty role names. And use the official role
  451. // name.
  452. $applications = array_intersect_key($roles, array_filter($applications));
  453. }
  454. else {
  455. $applications = array($applications => $roles[$applications]);
  456. }
  457. $received = array();
  458. $not_received = array();
  459. foreach ($applications as $rid => $role) {
  460. if (apply_for_role_add_apply($user, $rid)) {
  461. $received[] = $role;
  462. }
  463. else {
  464. $not_received[] = $role;
  465. }
  466. }
  467. if (!empty($received)) {
  468. drupal_set_message(
  469. format_plural(
  470. count($received),
  471. 'Your application was received for the following role:',
  472. 'Your applications were received for the following roles:',
  473. array('%roles' => implode(', ', $received))
  474. )
  475. );
  476. }
  477. if (!empty($not_received)) {
  478. drupal_set_message(
  479. format_plural(
  480. count($not_received),
  481. 'There was a problem processing your application for the following role:',
  482. 'There was a problem processing your applications for the following roles:',
  483. array('%roles' => implode(', ', $not_received))
  484. ), 'error'
  485. );
  486. }
  487. }
  488. /**
  489. * Return an array of roles that were approved for this user.
  490. *
  491. * @param $user User object.
  492. */
  493. function apply_for_role_approved_roles(&$user) {
  494. $approved = array();
  495. $roles = user_roles(TRUE);
  496. $result = db_query("SELECT rid FROM {users_roles_apply} WHERE uid = %d and approved = %d", $user->uid, APPLY_FOR_ROLE_APPROVED);
  497. while ($row = db_fetch_object($result)) {
  498. if (isset($roles[$row->rid]) && isset($user->roles[$row->rid]))
  499. $approved[$row->rid] = $roles[$row->rid];
  500. else
  501. continue;
  502. }
  503. return $approved;
  504. }