3 namespace Drupal\user\Form;
5 use Drupal\Core\Extension\ModuleHandlerInterface;
6 use Drupal\Core\Form\FormBase;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\user\PermissionHandlerInterface;
9 use Drupal\user\RoleStorageInterface;
10 use Symfony\Component\DependencyInjection\ContainerInterface;
13 * Provides the user permissions administration form.
17 class UserPermissionsForm extends FormBase {
20 * The permission handler.
22 * @var \Drupal\user\PermissionHandlerInterface
24 protected $permissionHandler;
29 * @var \Drupal\user\RoleStorageInterface
31 protected $roleStorage;
36 * @var \Drupal\Core\Extension\ModuleHandlerInterface
38 protected $moduleHandler;
41 * Constructs a new UserPermissionsForm.
43 * @param \Drupal\user\PermissionHandlerInterface $permission_handler
44 * The permission handler.
45 * @param \Drupal\user\RoleStorageInterface $role_storage
47 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
50 public function __construct(PermissionHandlerInterface $permission_handler, RoleStorageInterface $role_storage, ModuleHandlerInterface $module_handler) {
51 $this->permissionHandler = $permission_handler;
52 $this->roleStorage = $role_storage;
53 $this->moduleHandler = $module_handler;
59 public static function create(ContainerInterface $container) {
61 $container->get('user.permissions'),
62 $container->get('entity.manager')->getStorage('user_role'),
63 $container->get('module_handler')
70 public function getFormId() {
71 return 'user_admin_permissions';
75 * Gets the roles to display in this form.
77 * @return \Drupal\user\RoleInterface[]
78 * An array of role objects.
80 protected function getRoles() {
81 return $this->roleStorage->loadMultiple();
87 public function buildForm(array $form, FormStateInterface $form_state) {
89 $role_permissions = [];
91 foreach ($this->getRoles() as $role_name => $role) {
92 // Retrieve role names for columns.
93 $role_names[$role_name] = $role->label();
94 // Fetch permissions for the roles.
95 $role_permissions[$role_name] = $role->getPermissions();
96 $admin_roles[$role_name] = $role->isAdmin();
99 // Store $role_names for use when saving the data.
100 $form['role_names'] = [
102 '#value' => $role_names,
104 // Render role/permission overview:
105 $hide_descriptions = system_admin_compact_mode();
107 $form['system_compact_link'] = [
109 '#type' => 'system_compact_link',
112 $form['permissions'] = [
114 '#header' => [$this->t('Permission')],
115 '#id' => 'permissions',
116 '#attributes' => ['class' => ['permissions', 'js-permissions']],
119 foreach ($role_names as $name) {
120 $form['permissions']['#header'][] = [
122 'class' => ['checkbox'],
126 $permissions = $this->permissionHandler->getPermissions();
127 $permissions_by_provider = [];
128 foreach ($permissions as $permission_name => $permission) {
129 $permissions_by_provider[$permission['provider']][$permission_name] = $permission;
132 // Move the access content permission to the Node module if it is installed.
133 if ($this->moduleHandler->moduleExists('node')) {
134 // Insert 'access content' before the 'view own unpublished content' key
135 // in order to maintain the UI even though the permission is provided by
136 // the system module.
137 $keys = array_keys($permissions_by_provider['node']);
138 $offset = (int) array_search('view own unpublished content', $keys);
139 $permissions_by_provider['node'] = array_merge(
140 array_slice($permissions_by_provider['node'], 0, $offset),
141 ['access content' => $permissions_by_provider['system']['access content']],
142 array_slice($permissions_by_provider['node'], $offset)
144 unset($permissions_by_provider['system']['access content']);
147 foreach ($permissions_by_provider as $provider => $permissions) {
149 $form['permissions'][$provider] = [
151 '#wrapper_attributes' => [
152 'colspan' => count($role_names) + 1,
153 'class' => ['module'],
154 'id' => 'module-' . $provider,
156 '#markup' => $this->moduleHandler->getName($provider),
159 foreach ($permissions as $perm => $perm_item) {
160 // Fill in default values for the permission.
163 'restrict access' => FALSE,
164 'warning' => !empty($perm_item['restrict access']) ? $this->t('Warning: Give to trusted roles only; this permission has security implications.') : '',
166 $form['permissions'][$perm]['description'] = [
167 '#type' => 'inline_template',
168 '#template' => '<div class="permission"><span class="title">{{ title }}</span>{% if description or warning %}<div class="description">{% if warning %}<em class="permission-warning">{{ warning }}</em> {% endif %}{{ description }}</div>{% endif %}</div>',
170 'title' => $perm_item['title'],
173 // Show the permission description.
174 if (!$hide_descriptions) {
175 $form['permissions'][$perm]['description']['#context']['description'] = $perm_item['description'];
176 $form['permissions'][$perm]['description']['#context']['warning'] = $perm_item['warning'];
178 foreach ($role_names as $rid => $name) {
179 $form['permissions'][$perm][$rid] = [
180 '#title' => $name . ': ' . $perm_item['title'],
181 '#title_display' => 'invisible',
182 '#wrapper_attributes' => [
183 'class' => ['checkbox'],
185 '#type' => 'checkbox',
186 '#default_value' => in_array($perm, $role_permissions[$rid]) ? 1 : 0,
187 '#attributes' => ['class' => ['rid-' . $rid, 'js-rid-' . $rid]],
188 '#parents' => [$rid, $perm],
190 // Show a column of disabled but checked checkboxes.
191 if ($admin_roles[$rid]) {
192 $form['permissions'][$perm][$rid]['#disabled'] = TRUE;
193 $form['permissions'][$perm][$rid]['#default_value'] = TRUE;
199 $form['actions'] = ['#type' => 'actions'];
200 $form['actions']['submit'] = [
202 '#value' => $this->t('Save permissions'),
203 '#button_type' => 'primary',
206 $form['#attached']['library'][] = 'user/drupal.user.permissions';
214 public function submitForm(array &$form, FormStateInterface $form_state) {
215 foreach ($form_state->getValue('role_names') as $role_name => $name) {
216 user_role_change_permissions($role_name, (array) $form_state->getValue($role_name));
219 $this->messenger()->addStatus($this->t('The changes have been saved.'));