diff options
Diffstat (limited to 'modules/user')
-rw-r--r-- | modules/user/user-rtl.css | 6 | ||||
-rw-r--r-- | modules/user/user.admin.inc | 7 | ||||
-rw-r--r-- | modules/user/user.css | 4 | ||||
-rw-r--r-- | modules/user/user.module | 39 | ||||
-rw-r--r-- | modules/user/user.permissions.js | 70 |
5 files changed, 102 insertions, 24 deletions
diff --git a/modules/user/user-rtl.css b/modules/user/user-rtl.css index 5a1442c1c..642c94347 100644 --- a/modules/user/user-rtl.css +++ b/modules/user/user-rtl.css @@ -4,6 +4,12 @@ padding-right: 1.5em; } +#user-admin-roles .form-item-name { + float: right; + margin-left: 1em; + margin-right: 0; +} + /** * Password strength indicator. */ diff --git a/modules/user/user.admin.inc b/modules/user/user.admin.inc index 0596bde4c..0044b18a4 100644 --- a/modules/user/user.admin.inc +++ b/modules/user/user.admin.inc @@ -712,7 +712,12 @@ function user_admin_permissions($form, $form_state, $rid = NULL) { // Have to build checkboxes here after checkbox arrays are built foreach ($role_names as $rid => $name) { - $form['checkboxes'][$rid] = array('#type' => 'checkboxes', '#options' => $options, '#default_value' => isset($status[$rid]) ? $status[$rid] : array()); + $form['checkboxes'][$rid] = array( + '#type' => 'checkboxes', + '#options' => $options, + '#default_value' => isset($status[$rid]) ? $status[$rid] : array(), + '#attributes' => array('class' => array('rid-' . $rid)), + ); $form['role_names'][$rid] = array('#markup' => check_plain($name), '#tree' => TRUE); } diff --git a/modules/user/user.css b/modules/user/user.css index d6ed7c366..079ec38ab 100644 --- a/modules/user/user.css +++ b/modules/user/user.css @@ -22,8 +22,8 @@ clear: both; } #user-admin-roles .form-item-name { - float: left; - margin-right: 1em; + float: left; /* LTR */ + margin-right: 1em; /* LTR */ } /** diff --git a/modules/user/user.module b/modules/user/user.module index 84430b2f7..044ad4698 100644 --- a/modules/user/user.module +++ b/modules/user/user.module @@ -74,10 +74,26 @@ function user_help($path, $arg) { } /** - * Invokes hook_user() in every module. + * Invokes a user hook in every module. * * We cannot use module_invoke() for this, because the arguments need to * be passed by reference. + * + * @param $type + * A text string that controls which user hook to invoke. Valid choices are: + * - cancel: Invokes hook_user_cancel(). + * - insert: Invokes hook_user_insert(). + * - login: Invokes hook_user_login(). + * - presave: Invokes hook_user_presave(). + * - update: Invokes hook_user_update(). + * @param $edit + * An associative array variable containing form values to be passed + * as the first parameter of the hook function. + * @param $account + * The user account object to be passed as the second parameter of the hook + * function. + * @param $category + * The category of user information being acted upon. */ function user_module_invoke($type, &$edit, $account, $category = NULL) { foreach (module_implements('user_' . $type) as $module) { @@ -2287,6 +2303,27 @@ function user_cancel_url($account) { return url("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login), array('absolute' => TRUE)); } +/** + * Creates a unique hash value for use in time-dependent per-user URLs. + * + * This hash is normally used to build a unique and secure URL that is sent to + * the user by email for purposes such as resetting the user's password. In + * order to validate the URL, the same hash can be generated again, from the + * same information, and compared to the hash value from the URL. The URL + * normally contains both the time stamp and the numeric user ID. The login + * name and hashed password are retrieved from the database as necessary. For a + * usage example, see user_cancel_url() and user_cancel_confirm(). + * + * @param $password + * The hashed user account password value. + * @param $timestamp + * A unix timestamp. + * @param $login + * The user account login name. + * + * @return + * A string that is safe for use in URLs and SQL statements. + */ function user_pass_rehash($password, $timestamp, $login) { return drupal_hmac_base64($timestamp . $login, drupal_get_hash_salt() . $password); } diff --git a/modules/user/user.permissions.js b/modules/user/user.permissions.js index 4ef576cd4..988820e12 100644 --- a/modules/user/user.permissions.js +++ b/modules/user/user.permissions.js @@ -5,34 +5,64 @@ */ Drupal.behaviors.permissions = { attach: function (context) { - $('table#permissions:not(.permissions-processed)').each(function () { + var self = this; + $('table#permissions').once('permissions', function () { + // On a site with many roles and permissions, this behavior initially has + // to perform thousands of DOM manipulations to inject checkboxes and hide + // them. By detaching the table from the DOM, all operations can be + // performed without triggering internal layout and re-rendering processes + // in the browser. + var $table = $(this); + if ($table.prev().length) { + var $ancestor = $table.prev(), method = 'after'; + } + else { + var $ancestor = $table.parent(), method = 'append'; + } + $table.detach(); + // Create dummy checkboxes. We use dummy checkboxes instead of reusing // the existing checkboxes here because new checkboxes don't alter the // submitted form. If we'd automatically check existing checkboxes, the // permission table would be polluted with redundant entries. This // is deliberate, but desirable when we automatically check them. - $(':checkbox', this).not('[name^="2["]').not('[name^="1["]').each(function () { - $(this).addClass('real-checkbox'); - $('<input type="checkbox" class="dummy-checkbox" disabled="disabled" checked="checked" />') - .attr('title', Drupal.t("This permission is inherited from the authenticated user role.")) - .insertAfter(this) - .hide(); - }); + var $dummy = $('<input type="checkbox" class="dummy-checkbox" disabled="disabled" checked="checked" />') + .attr('title', Drupal.t("This permission is inherited from the authenticated user role.")) + .hide(); - // Helper function toggles all dummy checkboxes based on the checkboxes' - // state. If the "authenticated user" checkbox is checked, the checked - // and disabled checkboxes are shown, the real checkboxes otherwise. - var toggle = function () { - $(this).closest('tr') - .find('.real-checkbox')[this.checked ? 'hide' : 'show']().end() - .find('.dummy-checkbox')[this.checked ? 'show' : 'hide'](); - }; + $('input[type=checkbox]', this).not('.rid-2, .rid-1').addClass('real-checkbox').each(function () { + $dummy.clone().insertAfter(this); + }); // Initialize the authenticated user checkbox. - $(':checkbox[name^="2["]', this) - .click(toggle) - .each(function () { toggle.call(this); }); - }).addClass('permissions-processed'); + $('input[type=checkbox].rid-2', this) + .bind('click.permissions', self.toggle) + // .triggerHandler() cannot be used here, as it only affects the first + // element. + .each(self.toggle); + + // Re-insert the table into the DOM. + $ancestor[method]($table); + }); + }, + + /** + * Toggles all dummy checkboxes based on the checkboxes' state. + * + * If the "authenticated user" checkbox is checked, the checked and disabled + * checkboxes are shown, the real checkboxes otherwise. + */ + toggle: function () { + var authCheckbox = this, $row = $(this).closest('tr'); + // jQuery performs too many layout calculations for .hide() and .show(), + // leading to a major page rendering lag on sites with many roles and + // permissions. Therefore, we toggle visibility directly. + $row.find('.real-checkbox').each(function () { + this.style.display = (authCheckbox.checked ? 'none' : ''); + }); + $row.find('.dummy-checkbox').each(function () { + this.style.display = (authCheckbox.checked ? '' : 'none'); + }); } }; |