summaryrefslogtreecommitdiff
path: root/modules/user
diff options
context:
space:
mode:
Diffstat (limited to 'modules/user')
-rw-r--r--modules/user/user-rtl.css6
-rw-r--r--modules/user/user.admin.inc7
-rw-r--r--modules/user/user.css4
-rw-r--r--modules/user/user.module39
-rw-r--r--modules/user/user.permissions.js70
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');
+ });
}
};