Commit ee64752e authored by Dries's avatar Dries

- Patch #300993 by dropcube, Dave Reid: user roles and permission API. Great patch.

parent c9e82a3b
......@@ -853,6 +853,17 @@ function template_preprocess_block(&$variables) {
$variables['template_files'][] = 'block-' . $variables['block']->module . '-' . $variables['block']->delta;
}
/**
* Implement hook_user_role_delete().
*
* Remove deleted role from blocks that use it.
*/
function block_user_role_delete($role) {
db_delete('block_role')
->condition('rid', $role->rid)
->execute();
}
/**
* Implement hook_filter_format_delete().
*/
......
......@@ -963,3 +963,15 @@ function _filter_autop($text) {
/**
* @} End of "Standard filters".
*/
/**
* Implement hook_user_role_delete().
*
* Remove deleted role from formats that use it.
*/
function filter_user_role_delete($role) {
db_update('filter_format')
->expression('roles', 'REPLACE(roles, :rid, :replacement)', array(':rid' => ',' . $role->rid, ':replacement' => ''))
->condition('roles', '%,' . $role->rid . '%', 'LIKE')
->execute();
}
......@@ -892,26 +892,19 @@ protected function drupalCreateRole(array $permissions, $name = NULL) {
$name = $this->randomName();
}
// Check the all the permissions strings are valid.
if (!$this->checkPermissions($permissions)) {
return FALSE;
}
// Create new role.
db_insert('role')
->fields(array('name' => $name))
->execute();
$role = db_query('SELECT * FROM {role} WHERE name = :name', array(':name' => $name))->fetchObject();
$this->assertTrue($role, t('Created role of name: @name, id: @rid', array('@name' => $name, '@rid' => (isset($role->rid) ? $role->rid : t('-n/a-')))), t('Role'));
$role = new stdClass();
$role->name = $name;
user_role_save($role);
user_role_set_permissions($role->name, $permissions);
$this->assertTrue(isset($role->rid), t('Created role of name: @name, id: @rid', array('@name' => $name, '@rid' => (isset($role->rid) ? $role->rid : t('-n/a-')))), t('Role'));
if ($role && !empty($role->rid)) {
// Assign permissions to role and mark it for clean-up.
$query = db_insert('role_permission')->fields(array('rid', 'permission'));
foreach ($permissions as $permission_string) {
$query->values(array(
'rid' => $role->rid,
'permission' => $permission_string,
));
}
$query->execute();
$count = db_query('SELECT COUNT(*) FROM {role_permission} WHERE rid = :rid', array(':rid' => $role->rid))->fetchField();
$this->assertTrue($count == count($permissions), t('Created permissions: @perms', array('@perms' => implode(', ', $permissions))), t('Role'));
return $role->rid;
......
......@@ -385,21 +385,6 @@ function system_install() {
->execute();
}
$query = db_insert('role_permission')->fields(array('rid', 'permission'));
// Anonymous role permissions.
$query->values(array(
'rid' => DRUPAL_ANONYMOUS_RID,
'permission' => 'access content',
));
// Authenticated role permissions.
foreach (array('access comments', 'access content', 'post comments', 'post comments without approval', 'view own unpublished content') as $permission) {
$query->values(array(
'rid' => DRUPAL_AUTHENTICATED_RID,
'permission' => $permission,
));
}
$query->execute();
variable_set('theme_default', 'garland');
......
......@@ -663,19 +663,8 @@ function user_admin_permissions($form_state, $rid = NULL) {
*/
function user_admin_permissions_submit($form, &$form_state) {
foreach ($form_state['values']['role_names'] as $rid => $name) {
$checked = array_filter($form_state['values'][$rid]);
// Delete existing permissions for the role. This handles "unchecking" checkboxes.
db_delete('role_permission')
->condition('rid', $rid)
->execute();
$query = db_insert('role_permission')->fields(array('rid', 'permission'));
foreach ($checked as $permission) {
$query->values(array(
'rid' => $rid,
'permission' => $permission,
));
}
$query->execute();
$permissions = array_filter($form_state['values'][$rid]);
user_role_set_permissions($rid, $permissions);
}
drupal_set_message(t('The changes have been saved.'));
......@@ -776,13 +765,13 @@ function user_admin_role() {
function user_admin_role_validate($form, &$form_state) {
if ($form_state['values']['name']) {
if ($form_state['values']['op'] == t('Save role')) {
$existing_role = (bool) db_query_range("SELECT 1 FROM {role} WHERE name = :name AND rid <> :rid", array(':name' => $form_state['values']['name'], ':rid' => $form_state['values']['rid']), 0, 1)->fetchField();
if ($existing_role) {
$role = user_role_load($form_state['values']['name']);
if ($role && $role->rid != $form_state['values']['rid']) {
form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_state['values']['name'])));
}
}
elseif ($form_state['values']['op'] == t('Add role')) {
if ((bool) db_query_range('SELECT 1 FROM {role} WHERE name = :name', array(':name' => $form_state['values']['name']), 0, 1)->fetchField()) {
if (user_role_load($form_state['values']['name'])) {
form_set_error('name', t('The role name %name already exists. Please choose another role name.', array('%name' => $form_state['values']['name'])));
}
}
......@@ -793,31 +782,17 @@ function user_admin_role_validate($form, &$form_state) {
}
function user_admin_role_submit($form, &$form_state) {
$role = (object)$form_state['values'];
if ($form_state['values']['op'] == t('Save role')) {
db_update('role')
->fields(array('name' => $form_state['values']['name']))
->condition('rid', $form_state['values']['rid'])
->execute();
user_role_save($role);
drupal_set_message(t('The role has been renamed.'));
}
elseif ($form_state['values']['op'] == t('Delete role')) {
db_delete('role')
->condition('rid', $form_state['values']['rid'])
->execute();
db_delete('role_permission')
->condition('rid', $form_state['values']['rid'])
->execute();
// Update the users who have this role set:
db_delete('users_roles')
->condition('rid', $form_state['values']['rid'])
->execute();
user_role_delete($form_state['values']['rid']);
drupal_set_message(t('The role has been deleted.'));
}
elseif ($form_state['values']['op'] == t('Add role')) {
db_insert('role')
->fields(array('name' => $form_state['values']['name']))
->execute();
user_role_save($role);
drupal_set_message(t('The role has been added.'));
}
$form_state['redirect'] = 'admin/config/people/roles';
......
......@@ -422,6 +422,66 @@ function hook_user_view($account) {
}
}
/**
* Inform other modules that a user role has been added.
*
* Modules implementing this hook can act on the user role object when saved to
* the database. It's recommended that you implement this hook if your module
* adds additional data to user roles object. The module should save its custom
* additions to the database.
*
* @param $role
* A user role object.
*/
function hook_user_role_insert($role) {
// Save extra fields provided by the module to user roles.
db_insert('my_module_table')
->fields(array(
'rid' => $role->rid,
'role_description' => $role->description,
))
->execute();
}
/**
* Inform other modules that a user role has been updated.
*
* Modules implementing this hook can act on the user role object when updated.
* It's recommended that you implement this hook if your module adds additional
* data to user roles object. The module should save its custom additions to
* the database.
*
* @param $role
* A user role object.
*/
function hook_user_role_update($role) {
// Save extra fields provided by the module to user roles.
db_merge('my_module_table')
->key(array('rid' => $role->rid))
->fields(array(
'role_description' => $role->description
))
->execute();
}
/**
* Inform other modules that a user role has been deleted.
*
* This hook allows you act when a user role has been deleted.
* If your module stores references to roles, it's recommended that you
* implement this hook and delete existing instances of the deleted role
* in your module database tables.
*
* @param $role
* The $role object being deleted.
*/
function hook_user_role_delete($role) {
// Delete existing instances of the deleted role.
db_delete('my_module_table')
->condition('rid', $role->rid)
->execute();
}
/**
* @} End of "addtogroup hooks".
*/
......@@ -2206,6 +2206,114 @@ function user_roles($membersonly = FALSE, $permission = NULL) {
return array_filter($roles);
}
/**
* Fetch a user role from database.
*
* @param $role
* A string with the role name, or an integer with the role ID.
* @return
* A fully-loaded role object if a role with the given name or ID
* exists, FALSE otherwise.
*/
function user_role_load($role) {
$field = is_int($role) ? 'rid' : 'name';
return db_select('role', 'r')
->fields('r')
->condition($field, $role)
->execute()
->fetchObject();
}
/**
* Save a user role to the database.
*
* @param $role
* A role object to modify or add. If $role->rid is not specified, a new
* role will be created.
* @return
* Status constant indicating if role was created or updated.
* Failure to write the user role record will return FALSE. Otherwise.
* SAVED_NEW or SAVED_UPDATED is returned depending on the operation
* performed.
*/
function user_role_save($role) {
if ($role->name) {
// Prevent leading and trailing spaces in role names.
$role->name = trim($role->name);
}
if (!empty($role->rid) && $role->name) {
$status = drupal_write_record('role', $role, 'rid');
module_invoke_all('user_role_update', $role);
}
else {
$status = drupal_write_record('role', $role);
module_invoke_all('user_role_insert', $role);
}
return $status;
}
/**
* Delete a user role from database.
*
* @param $role
* A string with the role name, or an integer with the role ID.
*/
function user_role_delete($role) {
$role = user_role_load($role);
db_delete('role')
->condition('rid', $role->rid)
->execute();
db_delete('role_permission')
->condition('rid', $role->rid)
->execute();
// Update the users who have this role set:
db_delete('users_roles')
->condition('rid', $role->rid)
->execute();
// Clear the user access cache.
user_access(NULL, NULL, TRUE);
module_invoke_all('user_role_delete', $role);
}
/**
* Assign permissions to a user role.
*
* @param $role
* A string with the role name, or an integer with the role ID.
* @param $permissions
* An array of permissions strings.
* @param $merge
* A boolean indicating whether to add permissions or to merge
* with all existing permissions.
*/
function user_role_set_permissions($role, array $permissions = array(), $merge = FALSE) {
$role = user_role_load($role);
if (!$merge) {
// Delete existing permissions for the role.
db_delete('role_permission')
->condition('rid', $role->rid)
->execute();
}
// Assign the new permissions for the role.
foreach ($permissions as $permission_string) {
db_merge('role_permission')
->key(array(
'rid' => $role->rid,
'permission' => $permission_string,
))
->execute();
}
// Clear the user access cache.
user_access(NULL, NULL, TRUE);
return TRUE;
}
/**
* Implement hook_user_operations().
*/
......
......@@ -183,20 +183,18 @@ function default_install() {
))->execute();
db_insert('taxonomy_vocabulary_node_type')->fields(array('vid' => $vid, 'type' => 'article'))->execute();
// Create a default role for site administrators.
$rid = db_insert('role')->fields(array('name' => 'administrator'))->execute();
// Enable default permissions for system roles.
user_role_set_permissions(DRUPAL_ANONYMOUS_RID, array('access content'));
user_role_set_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'post comments without approval'));
// Create a default role for site administrators, with all available permissions assigned.
$admin_role = new stdClass();
$admin_role->name = 'administrator';
user_role_save($admin_role);
user_role_set_permissions($admin_role->name, array_keys(module_invoke_all('permission')));
// Set this as the administrator role.
variable_set('user_admin_role', $rid);
// Assign all available permissions to this role.
foreach (module_invoke_all('permission') as $key => $value) {
db_insert('role_permission')
->fields(array(
'rid' => $rid,
'permission' => $key,
))->execute();
}
variable_set('user_admin_role', $admin_role->rid);
// Update the menu router information.
menu_rebuild();
......
......@@ -66,6 +66,10 @@ function expert_install() {
$query->values($record);
}
$query->execute();
// Enable default permissions for system roles.
user_role_set_permissions(DRUPAL_ANONYMOUS_RID, array('access content'));
user_role_set_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'post comments without approval'));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment