Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.1191 diff -u -p -r1.1191 user.module --- modules/user/user.module 9 Aug 2010 19:49:40 -0000 1.1191 +++ modules/user/user.module 9 Aug 2010 21:54:30 -0000 @@ -3605,9 +3605,34 @@ function user_modules_installed($modules * Implements hook_modules_uninstalled(). */ function user_modules_uninstalled($modules) { - db_delete('role_permission') - ->condition('module', $modules, 'IN') - ->execute(); + // Do not remove permissions that are defined by multiple modules. + $delete = array(); + foreach ($modules as $module) { + // Use module_invoke(), not module_implements(), which would not work for + // uninstalled modules in an implementation of hook_modules_uninstalled(). + if ($module_permissions = module_invoke($module, 'permission')) { + // Not array_merge(), as we are only interested in the keys. + $delete += $module_permissions; + } + } + // The same permission can be defined by multiple modules; if we have any + // permissions to delete, iterate over all other modules to identify all + // unique permissions to delete. + if ($delete) { + foreach (array_diff(module_implements('permission'), $modules) as $module) { + if ($module_permissions = module_invoke($module, 'permission')) { + $delete = array_diff_key($delete, $module_permissions); + } + } + } + // If any unique permissions are left, delete them. + if ($delete) { + db_delete('role_permission') + ->condition('permission', array_keys($delete)) + // Extra safety. + ->condition('module', $modules) + ->execute(); + } } /**