0f7f0378daa0093c18adb142c194933d9ff21dab
[yaffs-website] / web / core / modules / user / src / Form / UserPermissionsForm.php
1 <?php
2
3 namespace Drupal\user\Form;
4
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;
11
12 /**
13  * Provides the user permissions administration form.
14  *
15  * @internal
16  */
17 class UserPermissionsForm extends FormBase {
18
19   /**
20    * The permission handler.
21    *
22    * @var \Drupal\user\PermissionHandlerInterface
23    */
24   protected $permissionHandler;
25
26   /**
27    * The role storage.
28    *
29    * @var \Drupal\user\RoleStorageInterface
30    */
31   protected $roleStorage;
32
33   /**
34    * The module handler.
35    *
36    * @var \Drupal\Core\Extension\ModuleHandlerInterface
37    */
38   protected $moduleHandler;
39
40   /**
41    * Constructs a new UserPermissionsForm.
42    *
43    * @param \Drupal\user\PermissionHandlerInterface $permission_handler
44    *   The permission handler.
45    * @param \Drupal\user\RoleStorageInterface $role_storage
46    *   The role storage.
47    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
48    *   The module handler.
49    */
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;
54   }
55
56   /**
57    * {@inheritdoc}
58    */
59   public static function create(ContainerInterface $container) {
60     return new static(
61       $container->get('user.permissions'),
62       $container->get('entity.manager')->getStorage('user_role'),
63       $container->get('module_handler')
64     );
65   }
66
67   /**
68    * {@inheritdoc}
69    */
70   public function getFormId() {
71     return 'user_admin_permissions';
72   }
73
74   /**
75    * Gets the roles to display in this form.
76    *
77    * @return \Drupal\user\RoleInterface[]
78    *   An array of role objects.
79    */
80   protected function getRoles() {
81     return $this->roleStorage->loadMultiple();
82   }
83
84   /**
85    * {@inheritdoc}
86    */
87   public function buildForm(array $form, FormStateInterface $form_state) {
88     $role_names = [];
89     $role_permissions = [];
90     $admin_roles = [];
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();
97     }
98
99     // Store $role_names for use when saving the data.
100     $form['role_names'] = [
101       '#type' => 'value',
102       '#value' => $role_names,
103     ];
104     // Render role/permission overview:
105     $hide_descriptions = system_admin_compact_mode();
106
107     $form['system_compact_link'] = [
108       '#id' => FALSE,
109       '#type' => 'system_compact_link',
110     ];
111
112     $form['permissions'] = [
113       '#type' => 'table',
114       '#header' => [$this->t('Permission')],
115       '#id' => 'permissions',
116       '#attributes' => ['class' => ['permissions', 'js-permissions']],
117       '#sticky' => TRUE,
118     ];
119     foreach ($role_names as $name) {
120       $form['permissions']['#header'][] = [
121         'data' => $name,
122         'class' => ['checkbox'],
123       ];
124     }
125
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;
130     }
131
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)
143       );
144       unset($permissions_by_provider['system']['access content']);
145     }
146
147     foreach ($permissions_by_provider as $provider => $permissions) {
148       // Module name.
149       $form['permissions'][$provider] = [
150         [
151           '#wrapper_attributes' => [
152             'colspan' => count($role_names) + 1,
153             'class' => ['module'],
154             'id' => 'module-' . $provider,
155           ],
156           '#markup' => $this->moduleHandler->getName($provider),
157         ],
158       ];
159       foreach ($permissions as $perm => $perm_item) {
160         // Fill in default values for the permission.
161         $perm_item += [
162           'description' => '',
163           'restrict access' => FALSE,
164           'warning' => !empty($perm_item['restrict access']) ? $this->t('Warning: Give to trusted roles only; this permission has security implications.') : '',
165         ];
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>',
169           '#context' => [
170             'title' => $perm_item['title'],
171           ],
172         ];
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'];
177         }
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'],
184             ],
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],
189           ];
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;
194           }
195         }
196       }
197     }
198
199     $form['actions'] = ['#type' => 'actions'];
200     $form['actions']['submit'] = [
201       '#type' => 'submit',
202       '#value' => $this->t('Save permissions'),
203       '#button_type' => 'primary',
204     ];
205
206     $form['#attached']['library'][] = 'user/drupal.user.permissions';
207
208     return $form;
209   }
210
211   /**
212    * {@inheritdoc}
213    */
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));
217     }
218
219     $this->messenger()->addStatus($this->t('The changes have been saved.'));
220   }
221
222 }