|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Admin page callback file for the user module. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Page callback: Generates the appropriate user administration form. |
|
10 * |
|
11 * This function generates the user registration, multiple user cancellation, |
|
12 * or filtered user list admin form, depending on the argument and the POST |
|
13 * form values. |
|
14 * |
|
15 * @param string $callback_arg |
|
16 * (optional) Indicates which form to build. Defaults to '', which will |
|
17 * trigger the user filter form. If the POST value 'op' is present, this |
|
18 * function uses that value as the callback argument. |
|
19 * |
|
20 * @return string |
|
21 * A renderable form array for the respective request. |
|
22 */ |
|
23 function user_admin($callback_arg = '') { |
|
24 $op = isset($_POST['op']) ? $_POST['op'] : $callback_arg; |
|
25 |
|
26 switch ($op) { |
|
27 case t('Create new account'): |
|
28 case 'create': |
|
29 $build['user_register'] = drupal_get_form('user_register_form'); |
|
30 break; |
|
31 default: |
|
32 if (!empty($_POST['accounts']) && isset($_POST['operation']) && ($_POST['operation'] == 'cancel')) { |
|
33 $build['user_multiple_cancel_confirm'] = drupal_get_form('user_multiple_cancel_confirm'); |
|
34 } |
|
35 else { |
|
36 $build['user_filter_form'] = drupal_get_form('user_filter_form'); |
|
37 $build['user_admin_account'] = drupal_get_form('user_admin_account'); |
|
38 } |
|
39 } |
|
40 return $build; |
|
41 } |
|
42 |
|
43 /** |
|
44 * Form builder; Return form for user administration filters. |
|
45 * |
|
46 * @ingroup forms |
|
47 * @see user_filter_form_submit() |
|
48 */ |
|
49 function user_filter_form() { |
|
50 $session = isset($_SESSION['user_overview_filter']) ? $_SESSION['user_overview_filter'] : array(); |
|
51 $filters = user_filters(); |
|
52 |
|
53 $i = 0; |
|
54 $form['filters'] = array( |
|
55 '#type' => 'fieldset', |
|
56 '#title' => t('Show only users where'), |
|
57 '#theme' => 'exposed_filters__user', |
|
58 ); |
|
59 foreach ($session as $filter) { |
|
60 list($type, $value) = $filter; |
|
61 if ($type == 'permission') { |
|
62 // Merge arrays of module permissions into one. |
|
63 // Slice past the first element '[any]' whose value is not an array. |
|
64 $options = call_user_func_array('array_merge', array_slice($filters[$type]['options'], 1)); |
|
65 $value = $options[$value]; |
|
66 } |
|
67 else { |
|
68 $value = $filters[$type]['options'][$value]; |
|
69 } |
|
70 $t_args = array('%property' => $filters[$type]['title'], '%value' => $value); |
|
71 if ($i++) { |
|
72 $form['filters']['current'][] = array('#markup' => t('and where %property is %value', $t_args)); |
|
73 } |
|
74 else { |
|
75 $form['filters']['current'][] = array('#markup' => t('%property is %value', $t_args)); |
|
76 } |
|
77 } |
|
78 |
|
79 $form['filters']['status'] = array( |
|
80 '#type' => 'container', |
|
81 '#attributes' => array('class' => array('clearfix')), |
|
82 '#prefix' => ($i ? '<div class="additional-filters">' . t('and where') . '</div>' : ''), |
|
83 ); |
|
84 $form['filters']['status']['filters'] = array( |
|
85 '#type' => 'container', |
|
86 '#attributes' => array('class' => array('filters')), |
|
87 ); |
|
88 foreach ($filters as $key => $filter) { |
|
89 $form['filters']['status']['filters'][$key] = array( |
|
90 '#type' => 'select', |
|
91 '#options' => $filter['options'], |
|
92 '#title' => $filter['title'], |
|
93 '#default_value' => '[any]', |
|
94 ); |
|
95 } |
|
96 |
|
97 $form['filters']['status']['actions'] = array( |
|
98 '#type' => 'actions', |
|
99 '#attributes' => array('class' => array('container-inline')), |
|
100 ); |
|
101 $form['filters']['status']['actions']['submit'] = array( |
|
102 '#type' => 'submit', |
|
103 '#value' => (count($session) ? t('Refine') : t('Filter')), |
|
104 ); |
|
105 if (count($session)) { |
|
106 $form['filters']['status']['actions']['undo'] = array( |
|
107 '#type' => 'submit', |
|
108 '#value' => t('Undo'), |
|
109 ); |
|
110 $form['filters']['status']['actions']['reset'] = array( |
|
111 '#type' => 'submit', |
|
112 '#value' => t('Reset'), |
|
113 ); |
|
114 } |
|
115 |
|
116 drupal_add_library('system', 'drupal.form'); |
|
117 |
|
118 return $form; |
|
119 } |
|
120 |
|
121 /** |
|
122 * Process result from user administration filter form. |
|
123 */ |
|
124 function user_filter_form_submit($form, &$form_state) { |
|
125 $op = $form_state['values']['op']; |
|
126 $filters = user_filters(); |
|
127 switch ($op) { |
|
128 case t('Filter'): |
|
129 case t('Refine'): |
|
130 // Apply every filter that has a choice selected other than 'any'. |
|
131 foreach ($filters as $filter => $options) { |
|
132 if (isset($form_state['values'][$filter]) && $form_state['values'][$filter] != '[any]') { |
|
133 // Merge an array of arrays into one if necessary. |
|
134 $options = ($filter == 'permission') ? form_options_flatten($filters[$filter]['options']) : $filters[$filter]['options']; |
|
135 // Only accept valid selections offered on the dropdown, block bad input. |
|
136 if (isset($options[$form_state['values'][$filter]])) { |
|
137 $_SESSION['user_overview_filter'][] = array($filter, $form_state['values'][$filter]); |
|
138 } |
|
139 } |
|
140 } |
|
141 break; |
|
142 case t('Undo'): |
|
143 array_pop($_SESSION['user_overview_filter']); |
|
144 break; |
|
145 case t('Reset'): |
|
146 $_SESSION['user_overview_filter'] = array(); |
|
147 break; |
|
148 case t('Update'): |
|
149 return; |
|
150 } |
|
151 |
|
152 $form_state['redirect'] = 'admin/people'; |
|
153 return; |
|
154 } |
|
155 |
|
156 /** |
|
157 * Form builder; User administration page. |
|
158 * |
|
159 * @ingroup forms |
|
160 * @see user_admin_account_validate() |
|
161 * @see user_admin_account_submit() |
|
162 */ |
|
163 function user_admin_account() { |
|
164 |
|
165 $header = array( |
|
166 'username' => array('data' => t('Username'), 'field' => 'u.name'), |
|
167 'status' => array('data' => t('Status'), 'field' => 'u.status'), |
|
168 'roles' => array('data' => t('Roles')), |
|
169 'member_for' => array('data' => t('Member for'), 'field' => 'u.created', 'sort' => 'desc'), |
|
170 'access' => array('data' => t('Last access'), 'field' => 'u.access'), |
|
171 'operations' => array('data' => t('Operations')), |
|
172 ); |
|
173 |
|
174 $query = db_select('users', 'u'); |
|
175 $query->condition('u.uid', 0, '<>'); |
|
176 user_build_filter_query($query); |
|
177 |
|
178 $count_query = clone $query; |
|
179 $count_query->addExpression('COUNT(u.uid)'); |
|
180 |
|
181 $query = $query->extend('PagerDefault')->extend('TableSort'); |
|
182 $query |
|
183 ->fields('u', array('uid', 'name', 'status', 'created', 'access')) |
|
184 ->limit(50) |
|
185 ->orderByHeader($header) |
|
186 ->setCountQuery($count_query); |
|
187 $result = $query->execute(); |
|
188 |
|
189 $form['options'] = array( |
|
190 '#type' => 'fieldset', |
|
191 '#title' => t('Update options'), |
|
192 '#attributes' => array('class' => array('container-inline')), |
|
193 ); |
|
194 $options = array(); |
|
195 foreach (module_invoke_all('user_operations') as $operation => $array) { |
|
196 $options[$operation] = $array['label']; |
|
197 } |
|
198 $form['options']['operation'] = array( |
|
199 '#type' => 'select', |
|
200 '#title' => t('Operation'), |
|
201 '#title_display' => 'invisible', |
|
202 '#options' => $options, |
|
203 '#default_value' => 'unblock', |
|
204 ); |
|
205 $options = array(); |
|
206 $form['options']['submit'] = array( |
|
207 '#type' => 'submit', |
|
208 '#value' => t('Update'), |
|
209 ); |
|
210 |
|
211 $destination = drupal_get_destination(); |
|
212 |
|
213 $status = array(t('blocked'), t('active')); |
|
214 $roles = array_map('check_plain', user_roles(TRUE)); |
|
215 $accounts = array(); |
|
216 foreach ($result as $account) { |
|
217 $users_roles = array(); |
|
218 $roles_result = db_query('SELECT rid FROM {users_roles} WHERE uid = :uid', array(':uid' => $account->uid)); |
|
219 foreach ($roles_result as $user_role) { |
|
220 $users_roles[] = $roles[$user_role->rid]; |
|
221 } |
|
222 asort($users_roles); |
|
223 |
|
224 $options[$account->uid] = array( |
|
225 'username' => theme('username', array('account' => $account)), |
|
226 'status' => $status[$account->status], |
|
227 'roles' => theme('item_list', array('items' => $users_roles)), |
|
228 'member_for' => format_interval(REQUEST_TIME - $account->created), |
|
229 'access' => $account->access ? t('@time ago', array('@time' => format_interval(REQUEST_TIME - $account->access))) : t('never'), |
|
230 'operations' => array('data' => array('#type' => 'link', '#title' => t('edit'), '#href' => "user/$account->uid/edit", '#options' => array('query' => $destination))), |
|
231 ); |
|
232 } |
|
233 |
|
234 $form['accounts'] = array( |
|
235 '#type' => 'tableselect', |
|
236 '#header' => $header, |
|
237 '#options' => $options, |
|
238 '#empty' => t('No people available.'), |
|
239 ); |
|
240 $form['pager'] = array('#markup' => theme('pager')); |
|
241 |
|
242 return $form; |
|
243 } |
|
244 |
|
245 /** |
|
246 * Submit the user administration update form. |
|
247 */ |
|
248 function user_admin_account_submit($form, &$form_state) { |
|
249 $operations = module_invoke_all('user_operations', $form, $form_state); |
|
250 $operation = $operations[$form_state['values']['operation']]; |
|
251 // Filter out unchecked accounts. |
|
252 $accounts = array_filter($form_state['values']['accounts']); |
|
253 if ($function = $operation['callback']) { |
|
254 // Add in callback arguments if present. |
|
255 if (isset($operation['callback arguments'])) { |
|
256 $args = array_merge(array($accounts), $operation['callback arguments']); |
|
257 } |
|
258 else { |
|
259 $args = array($accounts); |
|
260 } |
|
261 call_user_func_array($function, $args); |
|
262 |
|
263 drupal_set_message(t('The update has been performed.')); |
|
264 } |
|
265 } |
|
266 |
|
267 function user_admin_account_validate($form, &$form_state) { |
|
268 $form_state['values']['accounts'] = array_filter($form_state['values']['accounts']); |
|
269 if (count($form_state['values']['accounts']) == 0) { |
|
270 form_set_error('', t('No users selected.')); |
|
271 } |
|
272 } |
|
273 |
|
274 /** |
|
275 * Form builder; Configure user settings for this site. |
|
276 * |
|
277 * @ingroup forms |
|
278 * @see system_settings_form() |
|
279 */ |
|
280 function user_admin_settings() { |
|
281 // Settings for anonymous users. |
|
282 $form['anonymous_settings'] = array( |
|
283 '#type' => 'fieldset', |
|
284 '#title' => t('Anonymous users'), |
|
285 ); |
|
286 $form['anonymous_settings']['anonymous'] = array( |
|
287 '#type' => 'textfield', |
|
288 '#title' => t('Name'), |
|
289 '#default_value' => variable_get('anonymous', t('Anonymous')), |
|
290 '#description' => t('The name used to indicate anonymous users.'), |
|
291 '#required' => TRUE, |
|
292 ); |
|
293 |
|
294 // Administrative role option. |
|
295 $form['admin_role'] = array( |
|
296 '#type' => 'fieldset', |
|
297 '#title' => t('Administrator role'), |
|
298 ); |
|
299 |
|
300 // Do not allow users to set the anonymous or authenticated user roles as the |
|
301 // administrator role. |
|
302 $roles = user_roles(); |
|
303 unset($roles[DRUPAL_ANONYMOUS_RID]); |
|
304 unset($roles[DRUPAL_AUTHENTICATED_RID]); |
|
305 $roles[0] = t('disabled'); |
|
306 |
|
307 $form['admin_role']['user_admin_role'] = array( |
|
308 '#type' => 'select', |
|
309 '#title' => t('Administrator role'), |
|
310 '#default_value' => variable_get('user_admin_role', 0), |
|
311 '#options' => $roles, |
|
312 '#description' => t('This role will be automatically assigned new permissions whenever a module is enabled. Changing this setting will not affect existing permissions.'), |
|
313 ); |
|
314 |
|
315 // User registration settings. |
|
316 $form['registration_cancellation'] = array( |
|
317 '#type' => 'fieldset', |
|
318 '#title' => t('Registration and cancellation'), |
|
319 ); |
|
320 $form['registration_cancellation']['user_register'] = array( |
|
321 '#type' => 'radios', |
|
322 '#title' => t('Who can register accounts?'), |
|
323 '#default_value' => variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL), |
|
324 '#options' => array( |
|
325 USER_REGISTER_ADMINISTRATORS_ONLY => t('Administrators only'), |
|
326 USER_REGISTER_VISITORS => t('Visitors'), |
|
327 USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL => t('Visitors, but administrator approval is required'), |
|
328 ) |
|
329 ); |
|
330 $form['registration_cancellation']['user_email_verification'] = array( |
|
331 '#type' => 'checkbox', |
|
332 '#title' => t('Require e-mail verification when a visitor creates an account.'), |
|
333 '#default_value' => variable_get('user_email_verification', TRUE), |
|
334 '#description' => t('New users will be required to validate their e-mail address prior to logging into the site, and will be assigned a system-generated password. With this setting disabled, users will be logged in immediately upon registering, and may select their own passwords during registration.') |
|
335 ); |
|
336 module_load_include('inc', 'user', 'user.pages'); |
|
337 $form['registration_cancellation']['user_cancel_method'] = array( |
|
338 '#type' => 'item', |
|
339 '#title' => t('When cancelling a user account'), |
|
340 '#description' => t('Users with the %select-cancel-method or %administer-users <a href="@permissions-url">permissions</a> can override this default method.', array('%select-cancel-method' => t('Select method for cancelling account'), '%administer-users' => t('Administer users'), '@permissions-url' => url('admin/people/permissions'))), |
|
341 ); |
|
342 $form['registration_cancellation']['user_cancel_method'] += user_cancel_methods(); |
|
343 foreach (element_children($form['registration_cancellation']['user_cancel_method']) as $element) { |
|
344 // Remove all account cancellation methods that have #access defined, as |
|
345 // those cannot be configured as default method. |
|
346 if (isset($form['registration_cancellation']['user_cancel_method'][$element]['#access'])) { |
|
347 $form['registration_cancellation']['user_cancel_method'][$element]['#access'] = FALSE; |
|
348 } |
|
349 // Remove the description (only displayed on the confirmation form). |
|
350 else { |
|
351 unset($form['registration_cancellation']['user_cancel_method'][$element]['#description']); |
|
352 } |
|
353 } |
|
354 |
|
355 // Account settings. |
|
356 $form['personalization'] = array( |
|
357 '#type' => 'fieldset', |
|
358 '#title' => t('Personalization'), |
|
359 ); |
|
360 $form['personalization']['user_signatures'] = array( |
|
361 '#type' => 'checkbox', |
|
362 '#title' => t('Enable signatures.'), |
|
363 '#default_value' => variable_get('user_signatures', 0), |
|
364 ); |
|
365 // If picture support is enabled, check whether the picture directory exists. |
|
366 if (variable_get('user_pictures', 0)) { |
|
367 $picture_path = file_default_scheme() . '://' . variable_get('user_picture_path', 'pictures'); |
|
368 if (!file_prepare_directory($picture_path, FILE_CREATE_DIRECTORY)) { |
|
369 form_set_error('user_picture_path', t('The directory %directory does not exist or is not writable.', array('%directory' => $picture_path))); |
|
370 watchdog('file system', 'The directory %directory does not exist or is not writable.', array('%directory' => $picture_path), WATCHDOG_ERROR); |
|
371 } |
|
372 } |
|
373 $picture_support = variable_get('user_pictures', 0); |
|
374 $form['personalization']['user_pictures'] = array( |
|
375 '#type' => 'checkbox', |
|
376 '#title' => t('Enable user pictures.'), |
|
377 '#default_value' => $picture_support, |
|
378 ); |
|
379 drupal_add_js(drupal_get_path('module', 'user') . '/user.js'); |
|
380 $form['personalization']['pictures'] = array( |
|
381 '#type' => 'container', |
|
382 '#states' => array( |
|
383 // Hide the additional picture settings when user pictures are disabled. |
|
384 'invisible' => array( |
|
385 'input[name="user_pictures"]' => array('checked' => FALSE), |
|
386 ), |
|
387 ), |
|
388 ); |
|
389 $form['personalization']['pictures']['user_picture_path'] = array( |
|
390 '#type' => 'textfield', |
|
391 '#title' => t('Picture directory'), |
|
392 '#default_value' => variable_get('user_picture_path', 'pictures'), |
|
393 '#size' => 30, |
|
394 '#maxlength' => 255, |
|
395 '#description' => t('Subdirectory in the file upload directory where pictures will be stored.'), |
|
396 ); |
|
397 $form['personalization']['pictures']['user_picture_default'] = array( |
|
398 '#type' => 'textfield', |
|
399 '#title' => t('Default picture'), |
|
400 '#default_value' => variable_get('user_picture_default', ''), |
|
401 '#size' => 30, |
|
402 '#maxlength' => 255, |
|
403 '#description' => t('URL of picture to display for users with no custom picture selected. Leave blank for none.'), |
|
404 ); |
|
405 if (module_exists('image')) { |
|
406 $form['personalization']['pictures']['settings']['user_picture_style'] = array( |
|
407 '#type' => 'select', |
|
408 '#title' => t('Picture display style'), |
|
409 '#options' => image_style_options(TRUE, PASS_THROUGH), |
|
410 '#default_value' => variable_get('user_picture_style', ''), |
|
411 '#description' => t('The style selected will be used on display, while the original image is retained. Styles may be configured in the <a href="!url">Image styles</a> administration area.', array('!url' => url('admin/config/media/image-styles'))), |
|
412 ); |
|
413 } |
|
414 $form['personalization']['pictures']['user_picture_dimensions'] = array( |
|
415 '#type' => 'textfield', |
|
416 '#title' => t('Picture upload dimensions'), |
|
417 '#default_value' => variable_get('user_picture_dimensions', '85x85'), |
|
418 '#size' => 10, |
|
419 '#maxlength' => 10, |
|
420 '#field_suffix' => ' ' . t('pixels'), |
|
421 '#description' => t('Pictures larger than this will be scaled down to this size.'), |
|
422 ); |
|
423 $form['personalization']['pictures']['user_picture_file_size'] = array( |
|
424 '#type' => 'textfield', |
|
425 '#title' => t('Picture upload file size'), |
|
426 '#default_value' => variable_get('user_picture_file_size', '30'), |
|
427 '#size' => 10, |
|
428 '#maxlength' => 10, |
|
429 '#field_suffix' => ' ' . t('KB'), |
|
430 '#description' => t('Maximum allowed file size for uploaded pictures. Upload size is normally limited only by the PHP maximum post and file upload settings, and images are automatically scaled down to the dimensions specified above.'), |
|
431 '#element_validate' => array('element_validate_integer_positive'), |
|
432 ); |
|
433 $form['personalization']['pictures']['user_picture_guidelines'] = array( |
|
434 '#type' => 'textarea', |
|
435 '#title' => t('Picture guidelines'), |
|
436 '#default_value' => variable_get('user_picture_guidelines', ''), |
|
437 '#description' => t("This text is displayed at the picture upload form in addition to the default guidelines. It's useful for helping or instructing your users."), |
|
438 ); |
|
439 |
|
440 $form['email_title'] = array( |
|
441 '#type' => 'item', |
|
442 '#title' => t('E-mails'), |
|
443 ); |
|
444 $form['email'] = array( |
|
445 '#type' => 'vertical_tabs', |
|
446 ); |
|
447 // These email tokens are shared for all settings, so just define |
|
448 // the list once to help ensure they stay in sync. |
|
449 $email_token_help = t('Available variables are: [site:name], [site:url], [user:name], [user:mail], [site:login-url], [site:url-brief], [user:edit-url], [user:one-time-login-url], [user:cancel-url].'); |
|
450 |
|
451 $form['email_admin_created'] = array( |
|
452 '#type' => 'fieldset', |
|
453 '#title' => t('Welcome (new user created by administrator)'), |
|
454 '#collapsible' => TRUE, |
|
455 '#collapsed' => (variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) != USER_REGISTER_ADMINISTRATORS_ONLY), |
|
456 '#description' => t('Edit the welcome e-mail messages sent to new member accounts created by an administrator.') . ' ' . $email_token_help, |
|
457 '#group' => 'email', |
|
458 ); |
|
459 $form['email_admin_created']['user_mail_register_admin_created_subject'] = array( |
|
460 '#type' => 'textfield', |
|
461 '#title' => t('Subject'), |
|
462 '#default_value' => _user_mail_text('register_admin_created_subject', NULL, array(), FALSE), |
|
463 '#maxlength' => 180, |
|
464 ); |
|
465 $form['email_admin_created']['user_mail_register_admin_created_body'] = array( |
|
466 '#type' => 'textarea', |
|
467 '#title' => t('Body'), |
|
468 '#default_value' => _user_mail_text('register_admin_created_body', NULL, array(), FALSE), |
|
469 '#rows' => 15, |
|
470 ); |
|
471 |
|
472 $form['email_pending_approval'] = array( |
|
473 '#type' => 'fieldset', |
|
474 '#title' => t('Welcome (awaiting approval)'), |
|
475 '#collapsible' => TRUE, |
|
476 '#collapsed' => (variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) != USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL), |
|
477 '#description' => t('Edit the welcome e-mail messages sent to new members upon registering, when administrative approval is required.') . ' ' . $email_token_help, |
|
478 '#group' => 'email', |
|
479 ); |
|
480 $form['email_pending_approval']['user_mail_register_pending_approval_subject'] = array( |
|
481 '#type' => 'textfield', |
|
482 '#title' => t('Subject'), |
|
483 '#default_value' => _user_mail_text('register_pending_approval_subject', NULL, array(), FALSE), |
|
484 '#maxlength' => 180, |
|
485 ); |
|
486 $form['email_pending_approval']['user_mail_register_pending_approval_body'] = array( |
|
487 '#type' => 'textarea', |
|
488 '#title' => t('Body'), |
|
489 '#default_value' => _user_mail_text('register_pending_approval_body', NULL, array(), FALSE), |
|
490 '#rows' => 8, |
|
491 ); |
|
492 |
|
493 $form['email_no_approval_required'] = array( |
|
494 '#type' => 'fieldset', |
|
495 '#title' => t('Welcome (no approval required)'), |
|
496 '#collapsible' => TRUE, |
|
497 '#collapsed' => (variable_get('user_register', USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL) != USER_REGISTER_VISITORS), |
|
498 '#description' => t('Edit the welcome e-mail messages sent to new members upon registering, when no administrator approval is required.') . ' ' . $email_token_help, |
|
499 '#group' => 'email', |
|
500 ); |
|
501 $form['email_no_approval_required']['user_mail_register_no_approval_required_subject'] = array( |
|
502 '#type' => 'textfield', |
|
503 '#title' => t('Subject'), |
|
504 '#default_value' => _user_mail_text('register_no_approval_required_subject', NULL, array(), FALSE), |
|
505 '#maxlength' => 180, |
|
506 ); |
|
507 $form['email_no_approval_required']['user_mail_register_no_approval_required_body'] = array( |
|
508 '#type' => 'textarea', |
|
509 '#title' => t('Body'), |
|
510 '#default_value' => _user_mail_text('register_no_approval_required_body', NULL, array(), FALSE), |
|
511 '#rows' => 15, |
|
512 ); |
|
513 |
|
514 $form['email_password_reset'] = array( |
|
515 '#type' => 'fieldset', |
|
516 '#title' => t('Password recovery'), |
|
517 '#collapsible' => TRUE, |
|
518 '#collapsed' => TRUE, |
|
519 '#description' => t('Edit the e-mail messages sent to users who request a new password.') . ' ' . $email_token_help, |
|
520 '#group' => 'email', |
|
521 '#weight' => 10, |
|
522 ); |
|
523 $form['email_password_reset']['user_mail_password_reset_subject'] = array( |
|
524 '#type' => 'textfield', |
|
525 '#title' => t('Subject'), |
|
526 '#default_value' => _user_mail_text('password_reset_subject', NULL, array(), FALSE), |
|
527 '#maxlength' => 180, |
|
528 ); |
|
529 $form['email_password_reset']['user_mail_password_reset_body'] = array( |
|
530 '#type' => 'textarea', |
|
531 '#title' => t('Body'), |
|
532 '#default_value' => _user_mail_text('password_reset_body', NULL, array(), FALSE), |
|
533 '#rows' => 12, |
|
534 ); |
|
535 |
|
536 $form['email_activated'] = array( |
|
537 '#type' => 'fieldset', |
|
538 '#title' => t('Account activation'), |
|
539 '#collapsible' => TRUE, |
|
540 '#collapsed' => TRUE, |
|
541 '#description' => t('Enable and edit e-mail messages sent to users upon account activation (when an administrator activates an account of a user who has already registered, on a site where administrative approval is required).') . ' ' . $email_token_help, |
|
542 '#group' => 'email', |
|
543 ); |
|
544 $form['email_activated']['user_mail_status_activated_notify'] = array( |
|
545 '#type' => 'checkbox', |
|
546 '#title' => t('Notify user when account is activated.'), |
|
547 '#default_value' => variable_get('user_mail_status_activated_notify', TRUE), |
|
548 ); |
|
549 $form['email_activated']['settings'] = array( |
|
550 '#type' => 'container', |
|
551 '#states' => array( |
|
552 // Hide the additional settings when this email is disabled. |
|
553 'invisible' => array( |
|
554 'input[name="user_mail_status_activated_notify"]' => array('checked' => FALSE), |
|
555 ), |
|
556 ), |
|
557 ); |
|
558 $form['email_activated']['settings']['user_mail_status_activated_subject'] = array( |
|
559 '#type' => 'textfield', |
|
560 '#title' => t('Subject'), |
|
561 '#default_value' => _user_mail_text('status_activated_subject', NULL, array(), FALSE), |
|
562 '#maxlength' => 180, |
|
563 ); |
|
564 $form['email_activated']['settings']['user_mail_status_activated_body'] = array( |
|
565 '#type' => 'textarea', |
|
566 '#title' => t('Body'), |
|
567 '#default_value' => _user_mail_text('status_activated_body', NULL, array(), FALSE), |
|
568 '#rows' => 15, |
|
569 ); |
|
570 |
|
571 $form['email_blocked'] = array( |
|
572 '#type' => 'fieldset', |
|
573 '#title' => t('Account blocked'), |
|
574 '#collapsible' => TRUE, |
|
575 '#collapsed' => TRUE, |
|
576 '#description' => t('Enable and edit e-mail messages sent to users when their accounts are blocked.') . ' ' . $email_token_help, |
|
577 '#group' => 'email', |
|
578 ); |
|
579 $form['email_blocked']['user_mail_status_blocked_notify'] = array( |
|
580 '#type' => 'checkbox', |
|
581 '#title' => t('Notify user when account is blocked.'), |
|
582 '#default_value' => variable_get('user_mail_status_blocked_notify', FALSE), |
|
583 ); |
|
584 $form['email_blocked']['settings'] = array( |
|
585 '#type' => 'container', |
|
586 '#states' => array( |
|
587 // Hide the additional settings when the blocked email is disabled. |
|
588 'invisible' => array( |
|
589 'input[name="user_mail_status_blocked_notify"]' => array('checked' => FALSE), |
|
590 ), |
|
591 ), |
|
592 ); |
|
593 $form['email_blocked']['settings']['user_mail_status_blocked_subject'] = array( |
|
594 '#type' => 'textfield', |
|
595 '#title' => t('Subject'), |
|
596 '#default_value' => _user_mail_text('status_blocked_subject', NULL, array(), FALSE), |
|
597 '#maxlength' => 180, |
|
598 ); |
|
599 $form['email_blocked']['settings']['user_mail_status_blocked_body'] = array( |
|
600 '#type' => 'textarea', |
|
601 '#title' => t('Body'), |
|
602 '#default_value' => _user_mail_text('status_blocked_body', NULL, array(), FALSE), |
|
603 '#rows' => 3, |
|
604 ); |
|
605 |
|
606 $form['email_cancel_confirm'] = array( |
|
607 '#type' => 'fieldset', |
|
608 '#title' => t('Account cancellation confirmation'), |
|
609 '#collapsible' => TRUE, |
|
610 '#collapsed' => TRUE, |
|
611 '#description' => t('Edit the e-mail messages sent to users when they attempt to cancel their accounts.') . ' ' . $email_token_help, |
|
612 '#group' => 'email', |
|
613 ); |
|
614 $form['email_cancel_confirm']['user_mail_cancel_confirm_subject'] = array( |
|
615 '#type' => 'textfield', |
|
616 '#title' => t('Subject'), |
|
617 '#default_value' => _user_mail_text('cancel_confirm_subject', NULL, array(), FALSE), |
|
618 '#maxlength' => 180, |
|
619 ); |
|
620 $form['email_cancel_confirm']['user_mail_cancel_confirm_body'] = array( |
|
621 '#type' => 'textarea', |
|
622 '#title' => t('Body'), |
|
623 '#default_value' => _user_mail_text('cancel_confirm_body', NULL, array(), FALSE), |
|
624 '#rows' => 3, |
|
625 ); |
|
626 |
|
627 $form['email_canceled'] = array( |
|
628 '#type' => 'fieldset', |
|
629 '#title' => t('Account canceled'), |
|
630 '#collapsible' => TRUE, |
|
631 '#collapsed' => TRUE, |
|
632 '#description' => t('Enable and edit e-mail messages sent to users when their accounts are canceled.') . ' ' . $email_token_help, |
|
633 '#group' => 'email', |
|
634 ); |
|
635 $form['email_canceled']['user_mail_status_canceled_notify'] = array( |
|
636 '#type' => 'checkbox', |
|
637 '#title' => t('Notify user when account is canceled.'), |
|
638 '#default_value' => variable_get('user_mail_status_canceled_notify', FALSE), |
|
639 ); |
|
640 $form['email_canceled']['settings'] = array( |
|
641 '#type' => 'container', |
|
642 '#states' => array( |
|
643 // Hide the settings when the cancel notify checkbox is disabled. |
|
644 'invisible' => array( |
|
645 'input[name="user_mail_status_canceled_notify"]' => array('checked' => FALSE), |
|
646 ), |
|
647 ), |
|
648 ); |
|
649 $form['email_canceled']['settings']['user_mail_status_canceled_subject'] = array( |
|
650 '#type' => 'textfield', |
|
651 '#title' => t('Subject'), |
|
652 '#default_value' => _user_mail_text('status_canceled_subject', NULL, array(), FALSE), |
|
653 '#maxlength' => 180, |
|
654 ); |
|
655 $form['email_canceled']['settings']['user_mail_status_canceled_body'] = array( |
|
656 '#type' => 'textarea', |
|
657 '#title' => t('Body'), |
|
658 '#default_value' => _user_mail_text('status_canceled_body', NULL, array(), FALSE), |
|
659 '#rows' => 3, |
|
660 ); |
|
661 |
|
662 return system_settings_form($form); |
|
663 } |
|
664 |
|
665 /** |
|
666 * Menu callback: administer permissions. |
|
667 * |
|
668 * @ingroup forms |
|
669 * @see user_admin_permissions_submit() |
|
670 * @see theme_user_admin_permissions() |
|
671 */ |
|
672 function user_admin_permissions($form, $form_state, $rid = NULL) { |
|
673 |
|
674 // Retrieve role names for columns. |
|
675 $role_names = user_roles(); |
|
676 if (is_numeric($rid)) { |
|
677 $role_names = array($rid => $role_names[$rid]); |
|
678 } |
|
679 // Fetch permissions for all roles or the one selected role. |
|
680 $role_permissions = user_role_permissions($role_names); |
|
681 |
|
682 // Store $role_names for use when saving the data. |
|
683 $form['role_names'] = array( |
|
684 '#type' => 'value', |
|
685 '#value' => $role_names, |
|
686 ); |
|
687 // Render role/permission overview: |
|
688 $options = array(); |
|
689 $module_info = system_get_info('module'); |
|
690 $hide_descriptions = system_admin_compact_mode(); |
|
691 |
|
692 // Get a list of all the modules implementing a hook_permission() and sort by |
|
693 // display name. |
|
694 $modules = array(); |
|
695 foreach (module_implements('permission') as $module) { |
|
696 $modules[$module] = $module_info[$module]['name']; |
|
697 } |
|
698 asort($modules); |
|
699 |
|
700 foreach ($modules as $module => $display_name) { |
|
701 if ($permissions = module_invoke($module, 'permission')) { |
|
702 $form['permission'][] = array( |
|
703 '#markup' => $module_info[$module]['name'], |
|
704 '#id' => $module, |
|
705 ); |
|
706 foreach ($permissions as $perm => $perm_item) { |
|
707 // Fill in default values for the permission. |
|
708 $perm_item += array( |
|
709 'description' => '', |
|
710 'restrict access' => FALSE, |
|
711 'warning' => !empty($perm_item['restrict access']) ? t('Warning: Give to trusted roles only; this permission has security implications.') : '', |
|
712 ); |
|
713 $options[$perm] = ''; |
|
714 $form['permission'][$perm] = array( |
|
715 '#type' => 'item', |
|
716 '#markup' => $perm_item['title'], |
|
717 '#description' => theme('user_permission_description', array('permission_item' => $perm_item, 'hide' => $hide_descriptions)), |
|
718 ); |
|
719 foreach ($role_names as $rid => $name) { |
|
720 // Builds arrays for checked boxes for each role |
|
721 if (isset($role_permissions[$rid][$perm])) { |
|
722 $status[$rid][] = $perm; |
|
723 } |
|
724 } |
|
725 } |
|
726 } |
|
727 } |
|
728 |
|
729 // Have to build checkboxes here after checkbox arrays are built |
|
730 foreach ($role_names as $rid => $name) { |
|
731 $form['checkboxes'][$rid] = array( |
|
732 '#type' => 'checkboxes', |
|
733 '#options' => $options, |
|
734 '#default_value' => isset($status[$rid]) ? $status[$rid] : array(), |
|
735 '#attributes' => array('class' => array('rid-' . $rid)), |
|
736 ); |
|
737 $form['role_names'][$rid] = array('#markup' => check_plain($name), '#tree' => TRUE); |
|
738 } |
|
739 |
|
740 $form['actions'] = array('#type' => 'actions'); |
|
741 $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save permissions')); |
|
742 |
|
743 $form['#attached']['js'][] = drupal_get_path('module', 'user') . '/user.permissions.js'; |
|
744 |
|
745 return $form; |
|
746 } |
|
747 |
|
748 /** |
|
749 * Save permissions selected on the administer permissions page. |
|
750 * |
|
751 * @see user_admin_permissions() |
|
752 */ |
|
753 function user_admin_permissions_submit($form, &$form_state) { |
|
754 foreach ($form_state['values']['role_names'] as $rid => $name) { |
|
755 user_role_change_permissions($rid, $form_state['values'][$rid]); |
|
756 } |
|
757 |
|
758 drupal_set_message(t('The changes have been saved.')); |
|
759 |
|
760 // Clear the cached pages and blocks. |
|
761 cache_clear_all(); |
|
762 } |
|
763 |
|
764 /** |
|
765 * Returns HTML for the administer permissions page. |
|
766 * |
|
767 * @param $variables |
|
768 * An associative array containing: |
|
769 * - form: A render element representing the form. |
|
770 * |
|
771 * @ingroup themeable |
|
772 */ |
|
773 function theme_user_admin_permissions($variables) { |
|
774 $form = $variables['form']; |
|
775 |
|
776 $roles = user_roles(); |
|
777 foreach (element_children($form['permission']) as $key) { |
|
778 $row = array(); |
|
779 // Module name |
|
780 if (is_numeric($key)) { |
|
781 $row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => array('module'), 'id' => 'module-' . $form['permission'][$key]['#id'], 'colspan' => count($form['role_names']['#value']) + 1); |
|
782 } |
|
783 else { |
|
784 // Permission row. |
|
785 $row[] = array( |
|
786 'data' => drupal_render($form['permission'][$key]), |
|
787 'class' => array('permission'), |
|
788 ); |
|
789 foreach (element_children($form['checkboxes']) as $rid) { |
|
790 $form['checkboxes'][$rid][$key]['#title'] = $roles[$rid] . ': ' . $form['permission'][$key]['#markup']; |
|
791 $form['checkboxes'][$rid][$key]['#title_display'] = 'invisible'; |
|
792 $row[] = array('data' => drupal_render($form['checkboxes'][$rid][$key]), 'class' => array('checkbox')); |
|
793 } |
|
794 } |
|
795 $rows[] = $row; |
|
796 } |
|
797 $header[] = (t('Permission')); |
|
798 foreach (element_children($form['role_names']) as $rid) { |
|
799 $header[] = array('data' => drupal_render($form['role_names'][$rid]), 'class' => array('checkbox')); |
|
800 } |
|
801 $output = theme('system_compact_link'); |
|
802 $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'permissions'))); |
|
803 $output .= drupal_render_children($form); |
|
804 return $output; |
|
805 } |
|
806 |
|
807 /** |
|
808 * Returns HTML for an individual permission description. |
|
809 * |
|
810 * @param $variables |
|
811 * An associative array containing: |
|
812 * - permission_item: An associative array representing the permission whose |
|
813 * description is being themed. Useful keys include: |
|
814 * - description: The text of the permission description. |
|
815 * - warning: A security-related warning message about the permission (if |
|
816 * there is one). |
|
817 * - hide: A boolean indicating whether or not the permission description was |
|
818 * requested to be hidden rather than shown. |
|
819 * |
|
820 * @ingroup themeable |
|
821 */ |
|
822 function theme_user_permission_description($variables) { |
|
823 if (!$variables['hide']) { |
|
824 $description = array(); |
|
825 $permission_item = $variables['permission_item']; |
|
826 if (!empty($permission_item['description'])) { |
|
827 $description[] = $permission_item['description']; |
|
828 } |
|
829 if (!empty($permission_item['warning'])) { |
|
830 $description[] = '<em class="permission-warning">' . $permission_item['warning'] . '</em>'; |
|
831 } |
|
832 if (!empty($description)) { |
|
833 return implode(' ', $description); |
|
834 } |
|
835 } |
|
836 } |
|
837 |
|
838 /** |
|
839 * Form to re-order roles or add a new one. |
|
840 * |
|
841 * @ingroup forms |
|
842 * @see theme_user_admin_roles() |
|
843 */ |
|
844 function user_admin_roles($form, $form_state) { |
|
845 $roles = user_roles(); |
|
846 |
|
847 $form['roles'] = array( |
|
848 '#tree' => TRUE, |
|
849 ); |
|
850 $order = 0; |
|
851 foreach ($roles as $rid => $name) { |
|
852 $form['roles'][$rid]['#role'] = (object) array( |
|
853 'rid' => $rid, |
|
854 'name' => $name, |
|
855 'weight' => $order, |
|
856 ); |
|
857 $form['roles'][$rid]['#weight'] = $order; |
|
858 $form['roles'][$rid]['weight'] = array( |
|
859 '#type' => 'textfield', |
|
860 '#title' => t('Weight for @title', array('@title' => $name)), |
|
861 '#title_display' => 'invisible', |
|
862 '#size' => 4, |
|
863 '#default_value' => $order, |
|
864 '#attributes' => array('class' => array('role-weight')), |
|
865 ); |
|
866 $order++; |
|
867 } |
|
868 |
|
869 $form['name'] = array( |
|
870 '#type' => 'textfield', |
|
871 '#title' => t('Name'), |
|
872 '#title_display' => 'invisible', |
|
873 '#size' => 32, |
|
874 '#maxlength' => 64, |
|
875 ); |
|
876 $form['add'] = array( |
|
877 '#type' => 'submit', |
|
878 '#value' => t('Add role'), |
|
879 '#validate' => array('user_admin_role_validate'), |
|
880 '#submit' => array('user_admin_role_submit'), |
|
881 ); |
|
882 $form['actions'] = array('#type' => 'actions'); |
|
883 $form['actions']['submit'] = array( |
|
884 '#type' => 'submit', |
|
885 '#value' => t('Save order'), |
|
886 '#submit' => array('user_admin_roles_order_submit'), |
|
887 ); |
|
888 |
|
889 return $form; |
|
890 } |
|
891 |
|
892 /** |
|
893 * Form submit function. Update the role weights. |
|
894 */ |
|
895 function user_admin_roles_order_submit($form, &$form_state) { |
|
896 foreach ($form_state['values']['roles'] as $rid => $role_values) { |
|
897 $role = $form['roles'][$rid]['#role']; |
|
898 $role->weight = $role_values['weight']; |
|
899 user_role_save($role); |
|
900 } |
|
901 drupal_set_message(t('The role settings have been updated.')); |
|
902 } |
|
903 |
|
904 /** |
|
905 * Returns HTML for the role order and new role form. |
|
906 * |
|
907 * @param $variables |
|
908 * An associative array containing: |
|
909 * - form: A render element representing the form. |
|
910 * |
|
911 * @ingroup themeable |
|
912 */ |
|
913 function theme_user_admin_roles($variables) { |
|
914 $form = $variables['form']; |
|
915 |
|
916 $header = array(t('Name'), t('Weight'), array('data' => t('Operations'), 'colspan' => 2)); |
|
917 foreach (element_children($form['roles']) as $rid) { |
|
918 $name = $form['roles'][$rid]['#role']->name; |
|
919 $row = array(); |
|
920 if (in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { |
|
921 $row[] = t('@name <em>(locked)</em>', array('@name' => $name)); |
|
922 $row[] = drupal_render($form['roles'][$rid]['weight']); |
|
923 $row[] = ''; |
|
924 $row[] = l(t('edit permissions'), 'admin/people/permissions/' . $rid); |
|
925 } |
|
926 else { |
|
927 $row[] = check_plain($name); |
|
928 $row[] = drupal_render($form['roles'][$rid]['weight']); |
|
929 $row[] = l(t('edit role'), 'admin/people/permissions/roles/edit/' . $rid); |
|
930 $row[] = l(t('edit permissions'), 'admin/people/permissions/' . $rid); |
|
931 } |
|
932 $rows[] = array('data' => $row, 'class' => array('draggable')); |
|
933 } |
|
934 $rows[] = array(array('data' => drupal_render($form['name']) . drupal_render($form['add']), 'colspan' => 4, 'class' => 'edit-name')); |
|
935 |
|
936 drupal_add_tabledrag('user-roles', 'order', 'sibling', 'role-weight'); |
|
937 |
|
938 $output = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'user-roles'))); |
|
939 $output .= drupal_render_children($form); |
|
940 |
|
941 return $output; |
|
942 } |
|
943 |
|
944 /** |
|
945 * Form to configure a single role. |
|
946 * |
|
947 * @ingroup forms |
|
948 * @see user_admin_role_validate() |
|
949 * @see user_admin_role_submit() |
|
950 */ |
|
951 function user_admin_role($form, $form_state, $role) { |
|
952 if ($role->rid == DRUPAL_ANONYMOUS_RID || $role->rid == DRUPAL_AUTHENTICATED_RID) { |
|
953 drupal_goto('admin/people/permissions/roles'); |
|
954 } |
|
955 |
|
956 // Display the edit role form. |
|
957 $form['name'] = array( |
|
958 '#type' => 'textfield', |
|
959 '#title' => t('Role name'), |
|
960 '#default_value' => $role->name, |
|
961 '#size' => 30, |
|
962 '#required' => TRUE, |
|
963 '#maxlength' => 64, |
|
964 '#description' => t('The name for this role. Example: "moderator", "editorial board", "site architect".'), |
|
965 ); |
|
966 $form['rid'] = array( |
|
967 '#type' => 'value', |
|
968 '#value' => $role->rid, |
|
969 ); |
|
970 $form['weight'] = array( |
|
971 '#type' => 'value', |
|
972 '#value' => $role->weight, |
|
973 ); |
|
974 $form['actions'] = array('#type' => 'actions'); |
|
975 $form['actions']['submit'] = array( |
|
976 '#type' => 'submit', |
|
977 '#value' => t('Save role'), |
|
978 ); |
|
979 $form['actions']['delete'] = array( |
|
980 '#type' => 'submit', |
|
981 '#value' => t('Delete role'), |
|
982 '#submit' => array('user_admin_role_delete_submit'), |
|
983 ); |
|
984 |
|
985 return $form; |
|
986 } |
|
987 |
|
988 /** |
|
989 * Form validation handler for the user_admin_role() form. |
|
990 */ |
|
991 function user_admin_role_validate($form, &$form_state) { |
|
992 if (!empty($form_state['values']['name'])) { |
|
993 if ($form_state['values']['op'] == t('Save role')) { |
|
994 $role = user_role_load_by_name($form_state['values']['name']); |
|
995 if ($role && $role->rid != $form_state['values']['rid']) { |
|
996 form_set_error('name', t('The role name %name already exists. Choose another role name.', array('%name' => $form_state['values']['name']))); |
|
997 } |
|
998 } |
|
999 elseif ($form_state['values']['op'] == t('Add role')) { |
|
1000 if (user_role_load_by_name($form_state['values']['name'])) { |
|
1001 form_set_error('name', t('The role name %name already exists. Choose another role name.', array('%name' => $form_state['values']['name']))); |
|
1002 } |
|
1003 } |
|
1004 } |
|
1005 else { |
|
1006 form_set_error('name', t('You must specify a valid role name.')); |
|
1007 } |
|
1008 } |
|
1009 |
|
1010 /** |
|
1011 * Form submit handler for the user_admin_role() form. |
|
1012 */ |
|
1013 function user_admin_role_submit($form, &$form_state) { |
|
1014 $role = (object) $form_state['values']; |
|
1015 if ($form_state['values']['op'] == t('Save role')) { |
|
1016 user_role_save($role); |
|
1017 drupal_set_message(t('The role has been renamed.')); |
|
1018 } |
|
1019 elseif ($form_state['values']['op'] == t('Add role')) { |
|
1020 user_role_save($role); |
|
1021 drupal_set_message(t('The role has been added.')); |
|
1022 } |
|
1023 $form_state['redirect'] = 'admin/people/permissions/roles'; |
|
1024 return; |
|
1025 } |
|
1026 |
|
1027 /** |
|
1028 * Form submit handler for the user_admin_role() form. |
|
1029 */ |
|
1030 function user_admin_role_delete_submit($form, &$form_state) { |
|
1031 $form_state['redirect'] = 'admin/people/permissions/roles/delete/' . $form_state['values']['rid']; |
|
1032 } |
|
1033 |
|
1034 /** |
|
1035 * Form to confirm role delete operation. |
|
1036 */ |
|
1037 function user_admin_role_delete_confirm($form, &$form_state, $role) { |
|
1038 $form['rid'] = array( |
|
1039 '#type' => 'value', |
|
1040 '#value' => $role->rid, |
|
1041 ); |
|
1042 return confirm_form($form, t('Are you sure you want to delete the role %name ?', array('%name' => $role->name)), 'admin/people/permissions/roles', t('This action cannot be undone.'), t('Delete')); |
|
1043 } |
|
1044 |
|
1045 /** |
|
1046 * Form submit handler for user_admin_role_delete_confirm(). |
|
1047 */ |
|
1048 function user_admin_role_delete_confirm_submit($form, &$form_state) { |
|
1049 user_role_delete((int) $form_state['values']['rid']); |
|
1050 drupal_set_message(t('The role has been deleted.')); |
|
1051 $form_state['redirect'] = 'admin/people/permissions/roles'; |
|
1052 } |
|
1053 |